diff options
author | Nigel Graham <nigel@maven-group.org> | 2009-05-24 08:36:21 +0200 |
---|---|---|
committer | Nigel Graham <nigel@maven-group.org> | 2009-05-24 08:36:21 +0200 |
commit | 2cf6ddcbb9e9aac46391678bf032f74295ee8d7d (patch) | |
tree | cf4d8bf9ce1cbb0e05bcea36c2cbffb0068583f8 | |
parent | 4b4271d32446788901a84a880f8ba14ac747801f (diff) | |
download | pfsense-2cf6ddcbb9e9aac46391678bf032f74295ee8d7d.zip pfsense-2cf6ddcbb9e9aac46391678bf032f74295ee8d7d.tar.gz |
Added support for certificate chains to manager so that lighty can deliver them via SSL.
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | etc/inc/captiveportal.inc | 4 | ||||
-rw-r--r-- | etc/inc/certs.inc | 103 | ||||
-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, 187 insertions, 12 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 736763b..8414e89 100644 --- a/etc/inc/captiveportal.inc +++ b/etc/inc/captiveportal.inc @@ -223,13 +223,13 @@ 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, $key, "", "lighty-CaptivePortal-ssl.pid", "8001", "/usr/local/captiveportal/", "cert-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/", + "", "", "", "lighty-CaptivePortal.pid", "8000", "/usr/local/captiveportal/", "cert-portal.pem", "1", $maxproc, $use_fastcgi, true); /* attempt to start lighttpd */ diff --git a/etc/inc/certs.inc b/etc/inc/certs.inc index b7c0e60..40c0922 100644 --- a/etc/inc/certs.inc +++ b/etc/inc/certs.inc @@ -41,6 +41,20 @@ function & lookup_ca($refid) { 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;
@@ -52,10 +66,70 @@ function & lookup_cert($refid) { return false;
}
+function ca_chain_array(& $cert) {
+ if($cert['caref']) {
+ $chain = array();
+ $cert =& lookup_ca($cert['caref']);
+ $chain[] = $cert;
+ while ($cert) {
+ $caref = $cert['caref'];
+ if($caref)
+ $cert =& lookup_ca($caref);
+ else
+ $cert = false;
+ if($cert)
+ $chain[] = $cert;
+ }
+ return $chain;
+ }
+ return false;
+}
+
+function ca_chain(& $cert) {
+ if($cert['caref']) {
+ $ca = "";
+ $cas = ca_chain($cert);
+ if (is_array($cas))
+ foreach ($cas as & $ca_cert)
+ {
+ $ca .= base64_decode($ca_cert['crt']);
+ $ca .= "\n";
+ }
+ return $ca;
+ }
+ return false;
+}
+
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;
}
@@ -93,6 +167,15 @@ 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;
}
@@ -223,4 +306,24 @@ function cert_get_subject_array($crt) { 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 d8473b9..9955342 100644 --- a/etc/inc/globals.inc +++ b/etc/inc/globals.inc @@ -59,7 +59,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 f05a3e9..6e8814d 100644 --- a/etc/inc/system.inc +++ b/etc/inc/system.inc @@ -509,6 +509,7 @@ function system_webgui_start() { $portarg = "80"; $crt = ""; $key = ""; + $ca = ""; /* non-standard port? */ if ($config['system']['webgui']['port']) @@ -522,13 +523,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"); @@ -546,10 +548,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, @@ -834,9 +838,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"); @@ -849,10 +855,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 a3ea728..42ead89 100644 --- a/etc/inc/upgrade_config.inc +++ b/etc/inc/upgrade_config.inc @@ -1739,4 +1739,37 @@ function upgrade_058_to_059() { $schedl['schedlabel'] = uniqid(); } } + +function upgrade_059_to_060() { + global $config; + + 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 1015cb4..b403a00 100644 --- a/usr/local/www/system_camanager.php +++ b/usr/local/www/system_camanager.php @@ -388,6 +388,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> @@ -397,22 +398,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"> @@ -428,6 +442,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"> @@ -444,7 +459,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" /> @@ -452,7 +467,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 cf9035b..f469ee0 100644 --- a/usr/local/www/system_certmanager.php +++ b/usr/local/www/system_certmanager.php @@ -693,7 +693,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> @@ -703,8 +703,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']) { |