diff options
author | Scott Ullrich <sullrich@pfsense.org> | 2009-08-24 18:15:25 -0400 |
---|---|---|
committer | Scott Ullrich <sullrich@pfsense.org> | 2009-08-24 18:15:25 -0400 |
commit | d43ad788f295023f6e7d923fa07f0928a9a270d0 (patch) | |
tree | 4c8d54143bcab1e79440ee837b57ba0395549253 | |
parent | af539291187b159b4c7ddab791536f59193c21ea (diff) | |
parent | 29dc1e6e81998c881c15c08c526d7de65ff8e76b (diff) | |
download | pfsense-d43ad788f295023f6e7d923fa07f0928a9a270d0.zip pfsense-d43ad788f295023f6e7d923fa07f0928a9a270d0.tar.gz |
Merge branch 'master' of git://rcs.pfsense.org/pfsense/nigel-ca-chain into review/master
Conflicts:
etc/inc/certs.inc
etc/inc/upgrade_config.inc
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | etc/inc/captiveportal.inc | 8 | ||||
-rw-r--r-- | etc/inc/certs.inc | 331 | ||||
-rw-r--r-- | etc/inc/globals.inc | 2 | ||||
-rw-r--r-- | etc/inc/system.inc | 20 | ||||
-rw-r--r-- | etc/inc/upgrade_config.inc | 33 | ||||
-rw-r--r-- | usr/local/www/system_camanager.php | 25 | ||||
-rw-r--r-- | usr/local/www/system_certmanager.php | 11 |
8 files changed, 417 insertions, 14 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e43b0f9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/etc/inc/captiveportal.inc b/etc/inc/captiveportal.inc index 59c39ee..a3a80a5 100644 --- a/etc/inc/captiveportal.inc +++ b/etc/inc/captiveportal.inc @@ -226,14 +226,14 @@ EOD; $key = base64_decode($config['captiveportal']['private-key']); /* generate lighttpd configuration */ system_generate_lighty_config("{$g['varetc_path']}/lighty-CaptivePortal-SSL.conf", - $cert, $key, "lighty-CaptivePortal-ssl.pid", "8001", "/usr/local/captiveportal/", - "cert-portal.pem", "1", $maxproc, $use_fastcgi, true); + $cert, $key, "", "lighty-CaptivePortal-ssl.pid", "8001", "/usr/local/captiveportal/", + "cert-portal.pem", "ca-portal.pem", "1", $maxproc, $use_fastcgi, true); } /* generate lighttpd configuration */ system_generate_lighty_config("{$g['varetc_path']}/lighty-CaptivePortal.conf", - "", "", "lighty-CaptivePortal.pid", "8000", "/usr/local/captiveportal/", - "cert-portal.pem", "1", $maxproc, $use_fastcgi, true); + "", "", "", "lighty-CaptivePortal.pid", "8000", "/usr/local/captiveportal/", + "cert-portal.pem", "ca-portal.pem", "1", $maxproc, $use_fastcgi, true); /* attempt to start lighttpd */ $res = mwexec("/usr/local/sbin/lighttpd -f {$g['varetc_path']}/lighty-CaptivePortal.conf"); diff --git a/etc/inc/certs.inc b/etc/inc/certs.inc index 4177545..a2d4fd0 100644 --- a/etc/inc/certs.inc +++ b/etc/inc/certs.inc @@ -1,3 +1,4 @@ +<<<<<<< HEAD:etc/inc/certs.inc <?php /* $Id$ */ /* @@ -222,3 +223,333 @@ function cert_get_subject_array($crt) { } ?> +======= +<?php +/* $Id$ */ +/* + Copyright (C) 2008 Shrew Soft Inc + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + DISABLE_PHP_LINT_CHECKING +*/ + +require_once("functions.inc"); + +function & lookup_ca($refid) { + global $config; + + if (is_array($config['system']['ca'])) + foreach ($config['system']['ca'] as & $ca) + if ($ca['refid'] == $refid) + return $ca; + + return false; +} + +function & lookup_ca_by_subject($subject) { + global $config; + + if (is_array($config['system']['ca'])) + foreach ($config['system']['ca'] as & $ca) + { + $ca_subject = cert_get_subject($ca['crt']); + if ($ca_subject == $subject) + return $ca; + } + + return false; +} + +function & lookup_cert($refid) { + global $config; + + if (is_array($config['system']['cert'])) + foreach ($config['system']['cert'] as & $cert) + if ($cert['refid'] == $refid) + return $cert; + + return false; +} + +function ca_chain_array(& $cert) { + if($cert['caref']) { + $chain = array(); + $crt =& lookup_ca($cert['caref']); + $chain[] = $crt; + while ($crt) { + $caref = $crt['caref']; + if($caref) + $crt =& lookup_ca($caref); + else + $crt = false; + if($crt) + $chain[] = $crt; + } + return $chain; + } + return false; +} + +function ca_chain(& $cert) { + if($cert['caref']) { + $ca = ""; + $cas = ca_chain_array($cert); + if (is_array($cas)) + foreach ($cas as & $ca_cert) + { + $ca .= base64_decode($ca_cert['crt']); + $ca .= "\n"; + } + return $ca; + } + return ""; +} + +function ca_import(& $ca, $str) { + global $config; + + $ca['crt'] = base64_encode($str); + + $subject = cert_get_subject($str, false); + $issuer = cert_get_issuer($str, false); + + // Find my issuer unless self-signed + if($issuer <> $subject) { + $issuer_crt =& lookup_ca_by_subject($issuer); + if($issuer_crt) + $ca['caref'] = $issuer_crt['refid']; + } + + /* Correct if child certificate was loaded first */ + if (is_array($config['system']['ca'])) + foreach ($config['system']['ca'] as & $oca) + { + $issuer = cert_get_issuer($oca['crt']); + if($ca['refid']<>$oca['refid'] && $issuer==$subject) + $oca['caref'] = $ca['refid']; + } + if (is_array($config['system']['cert'])) + foreach ($config['system']['cert'] as & $cert) + { + $issuer = cert_get_issuer($cert['crt']); + if($issuer==$subject) + $cert['caref'] = $ca['refid']; + } + return true; +} + +function ca_create(& $ca, $keylen, $lifetime, $dn) { + + $args = array( + "digest_alg" => "sha1", + "private_key_bits" => $keylen, + "private_key_type" => OPENSSL_KEYTYPE_RSA, + "encrypt_key" => false); + + // generate a new key pair + $res_key = openssl_pkey_new(); + + // generate a certificate signing request + $res_csr = openssl_csr_new($dn, $res_key, $args); + + // self sign the certificate + $res_crt = openssl_csr_sign($res_csr, null, $res_key, $lifetime, $args); + + // export our certificate data + openssl_pkey_export($res_key, $str_key); + openssl_x509_export($res_crt, $str_crt); + + // return our ca information + $ca['crt'] = base64_encode($str_crt); + $ca['prv'] = base64_encode($str_key); + $ca['serial'] = 0; + + return true; +} + +function cert_import(& $cert, $crt_str, $key_str) { + + $cert['crt'] = base64_encode($crt_str); + $cert['prv'] = base64_encode($key_str); + + $subject = cert_get_subject($crt_str, false); + $issuer = cert_get_issuer($crt_str, false); + + // Find my issuer unless self-signed + if($issuer <> $subject) { + $issuer_crt =& lookup_ca_by_subject($issuer); + if($issuer_crt) + $cert['caref'] = $issuer_crt['refid']; + } + return true; +} + +function cert_create(& $cert, $caref, $keylen, $lifetime, $dn) { + + $ca =& lookup_ca($caref); + if (!$ca) + return false; + + $ca_str_crt = base64_decode($ca['crt']); + $ca_str_key = base64_decode($ca['prv']); + $ca_res_crt = openssl_x509_read($ca_str_crt); + $ca_res_key = openssl_pkey_get_private($ca_str_key); + $ca_serial = $ca['serial']++; + + $args = array( + "digest_alg" => "sha1", + "private_key_bits" => $keylen, + "private_key_type" => OPENSSL_KEYTYPE_RSA, + "encrypt_key" => false); + + // generate a new key pair + $res_key = openssl_pkey_new(); + + // generate a certificate signing request + $res_csr = openssl_csr_new($dn, $res_key, $args); + + // self sign the certificate + $res_crt = openssl_csr_sign($res_csr, $ca_res_crt, $ca_res_key, $lifetime, + $args, $ca_serial); + + // export our certificate data + openssl_pkey_export($res_key, $str_key); + openssl_x509_export($res_crt, $str_crt); + + // return our certificate information + $cert['caref'] = $caref; + $cert['crt'] = base64_encode($str_crt); + $cert['prv'] = base64_encode($str_key); + + return true; +} + +function csr_generate(& $cert, $keylen, $dn) { + + $args = array( + "digest_alg" => "sha1", + "private_key_bits" => $keylen, + "private_key_type" => OPENSSL_KEYTYPE_RSA, + "encrypt_key" => false); + + // generate a new key pair + $res_key = openssl_pkey_new(); + + // generate a certificate signing request + $res_csr = openssl_csr_new($dn, $res_key, $args); + + // export our request data + openssl_pkey_export($res_key, $str_key); + openssl_csr_export($res_csr, $str_csr); + + // return our request information + $cert['csr'] = base64_encode($str_csr); + $cert['prv'] = base64_encode($str_key); + + return true; +} + +function csr_complete(& $cert, $str_crt) { + + // return our request information + $cert['crt'] = base64_encode($str_crt); + unset($cert['csr']); + + return true; +} + +function csr_get_subject($str_crt, $decode = true) { + + if ($decode) + $str_crt = base64_decode($str_crt); + + $components = openssl_csr_get_subject($str_crt); + + if (!is_array($components)) + return "unknown"; + + foreach ($components as $a => $v) { + if (!strlen($subject)) + $subject = "{$a}={$v}"; + else + $subject = "{$a}={$v}, {$subject}"; + } + + return $subject; +} + +function cert_get_subject($str_crt, $decode = true) { + + if ($decode) + $str_crt = base64_decode($str_crt); + + $inf_crt = openssl_x509_parse($str_crt); + $components = $inf_crt['subject']; + + if (!is_array($components)) + return "unknown"; + + foreach ($components as $a => $v) { + if (!strlen($subject)) + $subject = "{$a}={$v}"; + else + $subject = "{$a}={$v}, {$subject}"; + } + + return $subject; +} + +function cert_get_subject_array($crt) { + $str_crt = base64_decode($crt); + $inf_crt = openssl_x509_parse($str_crt); + $components = $inf_crt['subject']; + $subject_array = array(); + + foreach($components as $a => $v) + $subject_array[] = array('a' => $a, 'v' => $v); + + return $subject_array; +} + +function cert_get_issuer($str_crt, $decode = true) { + + if ($decode) + $str_crt = base64_decode($str_crt); + + $inf_crt = openssl_x509_parse($str_crt); + $components = $inf_crt['issuer']; + + if (!is_array($components)) + return "unknown"; + foreach ($components as $a => $v) { + if (!strlen($issuer)) + $issuer = "{$a}={$v}"; + else + $issuer = "{$a}={$v}, {$issuer}"; + } + + return $issuer; +} + +?> diff --git a/etc/inc/globals.inc b/etc/inc/globals.inc index 666f759..df162cd 100644 --- a/etc/inc/globals.inc +++ b/etc/inc/globals.inc @@ -80,7 +80,7 @@ $g = array( "product_email" => "coreteam@pfsense.org", "hideplatform" => false, "debug" => false, - "latest_config" => "5.9", + "latest_config" => "6.0", "nopkg_platforms" => array("cdrom"), "minimum_ram_warning" => "115", "minimum_ram_warning_text" => "128 megabytes", diff --git a/etc/inc/system.inc b/etc/inc/system.inc index 3939471..11c5678 100644 --- a/etc/inc/system.inc +++ b/etc/inc/system.inc @@ -523,6 +523,7 @@ function system_webgui_start() { $portarg = "80"; $crt = ""; $key = ""; + $ca = ""; /* non-standard port? */ if (isset($config['system']['webgui']['port']) && $config['system']['webgui']['port'] <> "") @@ -536,13 +537,14 @@ function system_webgui_start() { $key = base64_decode($cert['prv']); if(!$config['system']['webgui']['port']) $portarg = "443"; + $ca = ca_chain($cert); } else log_error("Invalid webConfigurator https certificate, defaulting to http"); } /* generate lighttpd configuration */ system_generate_lighty_config("{$g['varetc_path']}/lighty-webConfigurator.conf", - $crt, $key, "lighty-webConfigurator.pid", $portarg, "/usr/local/www/"); + $crt, $key, $ca, "lighty-webConfigurator.pid", $portarg, "/usr/local/www/"); /* attempt to start lighthttpd */ $res = mwexec("/usr/local/sbin/lighttpd -f {$g['varetc_path']}/lighty-webConfigurator.conf"); @@ -560,10 +562,12 @@ function system_webgui_start() { function system_generate_lighty_config($filename, $cert, $key, + $ca, $pid_file, $port = 80, $document_root = "/usr/local/www/", $cert_location = "cert.pem", + $ca_location = "ca.pem", $max_procs = 2, $max_requests = "1", $fast_cgi_enable = true, @@ -852,9 +856,11 @@ EOD; $cert = str_replace("\r", "", $cert); $key = str_replace("\r", "", $key); + $ca = str_replace("\r", "", $ca); $cert = str_replace("\n\n", "\n", $cert); $key = str_replace("\n\n", "\n", $key); + $ca = str_replace("\n\n", "\n", $ca); if($cert <> "" and $key <> "") { $fd = fopen("{$g['varetc_path']}/{$cert_location}", "w"); @@ -867,10 +873,22 @@ EOD; fwrite($fd, "\n"); fwrite($fd, $key); fclose($fd); + if($ca <> "") { + $fd = fopen("{$g['varetc_path']}/{$ca_location}", "w"); + if (!$fd) { + printf("Error: cannot open ca.pem in system_webgui_start().\n"); + return 1; + } + chmod("{$g['varetc_path']}/{$ca_location}", 0600); + fwrite($fd, $ca); + fclose($fd); + } $lighty_config .= "\n"; $lighty_config .= "## ssl configuration\n"; $lighty_config .= "ssl.engine = \"enable\"\n"; $lighty_config .= "ssl.pemfile = \"{$g['varetc_path']}/{$cert_location}\"\n\n"; + if($ca <> "") + $lighty_config .= "ssl.ca-file = \"{$g['varetc_path']}/{$ca_location}\"\n\n"; } $fd = fopen("{$filename}", "w"); diff --git a/etc/inc/upgrade_config.inc b/etc/inc/upgrade_config.inc index 7d05575..161133b 100644 --- a/etc/inc/upgrade_config.inc +++ b/etc/inc/upgrade_config.inc @@ -1740,7 +1740,40 @@ function upgrade_058_to_059() { function upgrade_059_to_060() { global $config; +<<<<<<< HEAD:etc/inc/upgrade_config.inc /* Insert upgrade code here */ } +======= + + if (is_array($config['system']['ca'])) + { + /* Locate issuer for all CAs */ + foreach ($config['system']['ca'] as & $ca) + { + $subject = cert_get_subject($ca['crt']); + $issuer = cert_get_issuer($ca['crt']); + if($issuer <> $subject) { + $issuer_crt =& lookup_ca_by_subject($issuer); + if($issuer_crt) + $ca['caref'] = $issuer_crt['refid']; + } + } + + /* Locate issuer for all certificates */ + if (is_array($config['system']['cert'])) + foreach ($config['system']['cert'] as & $cert) + { + $subject = cert_get_subject($cert['crt']); + $issuer = cert_get_issuer($cert['crt']); + if($issuer <> $subject) { + $issuer_crt =& lookup_ca_by_subject($issuer); + if($issuer_crt) + $cert['caref'] = $issuer_crt['refid']; + } + } + + } +} + ?> diff --git a/usr/local/www/system_camanager.php b/usr/local/www/system_camanager.php index 758ccea..3458da5 100644 --- a/usr/local/www/system_camanager.php +++ b/usr/local/www/system_camanager.php @@ -389,6 +389,7 @@ function method_change() { <tr> <td width="20%" class="listhdrr">Name</td> <td width="10%" class="listhdrr">Internal</td> + <td width="10%" class="listhdrr">Issuer</td> <td width="10%" class="listhdrr">Certificates</td> <td width="40%" class="listhdrr">Distinguished Name</td> <td width="10%" class="list"></td> @@ -398,22 +399,35 @@ function method_change() { foreach($a_ca as $ca): $name = htmlspecialchars($ca['name']); $subj = cert_get_subject($ca['crt']); + $issuer = cert_get_issuer($ca['crt']); + if($subj == $issuer) + $issuer_name = "<em>self-signed</em>"; + else + $issuer_name = "<em>external</em>"; $subj = htmlspecialchars($subj); + $issuer = htmlspecialchars($issuer); $certcount = 0; + $issuer_ca = lookup_ca($ca['caref']); + if ($issuer_ca) + $issuer_name = $issuer_ca['name']; + // TODO : Need gray certificate icon if($ca['prv']) { $caimg = "/themes/{$g['theme']}/images/icons/icon_frmfld_cert.png"; $internal = "YES"; - foreach ($a_cert as $cert) - if ($cert['caref'] == $ca['refid']) - $certcount++; } else { $caimg = "/themes/{$g['theme']}/images/icons/icon_frmfld_cert.png"; $internal = "NO"; } + foreach ($a_cert as $cert) + if ($cert['caref'] == $ca['refid']) + $certcount++; + foreach ($a_ca as $cert) + if ($cert['caref'] == $ca['refid']) + $certcount++; ?> <tr> <td class="listlr"> @@ -429,6 +443,7 @@ function method_change() { </table> </td> <td class="listr"><?=$internal;?> </td> + <td class="listr"><?=$issuer_name;?> </td> <td class="listr"><?=$certcount;?> </td> <td class="listr"><?=$subj;?> </td> <td valign="middle" nowrap class="list"> @@ -445,7 +460,7 @@ function method_change() { endforeach; ?> <tr> - <td class="list" colspan="4"></td> + <td class="list" colspan="5"></td> <td class="list"> <a href="system_camanager.php?act=new"> <img src="/themes/<?= $g['theme'];?>/images/icons/icon_plus.gif" title="add or import ca" alt="add ca" width="17" height="17" border="0" /> @@ -453,7 +468,7 @@ function method_change() { </td> </tr> <tr> - <td colspan="4"> + <td colspan="5"> <p> <?=gettext("Additional trusted certificate authorities can be added here.");?> </p> diff --git a/usr/local/www/system_certmanager.php b/usr/local/www/system_certmanager.php index 4803187..be3f88b 100644 --- a/usr/local/www/system_certmanager.php +++ b/usr/local/www/system_certmanager.php @@ -694,7 +694,7 @@ function internalca_change() { <table width="100%" border="0" cellpadding="0" cellspacing="0"> <tr> <td width="20%" class="listhdrr">Name</td> - <td width="20%" class="listhdrr">CA</td> + <td width="20%" class="listhdrr">Issuer</td> <td width="40%" class="listhdrr">Distinguished Name</td> <td width="10%" class="list"></td> </tr> @@ -704,8 +704,13 @@ function internalca_change() { $name = htmlspecialchars($cert['name']); if ($cert['crt']) { - $subj = htmlspecialchars(cert_get_subject($cert['crt'])); - $caname = "<em>external</em>"; + $subj = cert_get_subject($cert['crt']); + $issuer = cert_get_issuer($cert['crt']); + if($subj==$issuer) + $caname = "<em>self-signed</em>"; + else + $caname = "<em>external</em>"; + $subj = htmlspecialchars($subj); } if ($cert['csr']) { |