Added support for certificate chains to manager so that lighty can deliver them via SSL.

This commit is contained in:
Nigel Graham 2009-05-24 08:36:21 +02:00
parent 4b4271d324
commit 2cf6ddcbb9
8 changed files with 187 additions and 12 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.DS_Store

View File

@ -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 */

View File

@ -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;
}
?>

View File

@ -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",

View File

@ -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");

View File

@ -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'];
}
}
}
}
?>

View File

@ -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;?>&nbsp;</td>
<td class="listr"><?=$issuer_name;?>&nbsp;</td>
<td class="listr"><?=$certcount;?>&nbsp;</td>
<td class="listr"><?=$subj;?>&nbsp;</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>

View File

@ -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']) {