Teach the certificate generation code how to make a self-signed certificate, and

change the GUI cert generation code to use it. Also, move the GUI cert
generation code to its own function so we can add a GUI option to regenerate it
later. Also use some more sane defaults for the contents of the default self-
signed certificate's fields so it will be more unique and
less likely to trigger problems in browser certificate storage handling.
Also add a CLI script to regenerate a new GUI certificate.
Several master commits rolled into one patch for 2.1.x.
This commit is contained in:
jim-p 2014-10-21 14:42:43 -04:00
parent 5b473705fa
commit a376c57de5
3 changed files with 77 additions and 38 deletions

View File

@ -270,22 +270,28 @@ function cert_import(& $cert, $crt_str, $key_str) {
function cert_create(& $cert, $caref, $keylen, $lifetime, $dn, $type="user", $digest_alg = "sha256") {
$ca =& lookup_ca($caref);
if (!$ca)
return false;
$cert['type'] = $type;
$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(array(0 => $ca_str_key, 1 => ""));
if(!$ca_res_key) return false;
$ca_serial = ++$ca['serial'];
if ($type != "self-signed") {
$cert['caref'] = $caref;
$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(array(0 => $ca_str_key, 1 => ""));
if(!$ca_res_key) return false;
$ca_serial = ++$ca['serial'];
}
switch ($type) {
case "ca":
$cert_type = "v3_ca";
break;
case "server":
case "self-signed":
$cert_type = "server";
break;
default:
@ -304,11 +310,20 @@ function cert_create(& $cert, $caref, $keylen, $lifetime, $dn, $type="user", $di
$res_key = openssl_pkey_new($args);
if(!$res_key) return false;
// If this is a self-signed cert, blank out the CA and sign with the cert's key
if ($type == "self-signed") {
$ca = null;
$ca_res_crt = null;
$ca_res_key = $res_key;
$ca_serial = 0;
$cert['type'] = "server";
}
// generate a certificate signing request
$res_csr = openssl_csr_new($dn, $res_key, $args);
if(!$res_csr) return false;
// self sign the certificate
// sign the certificate using an internal CA
$res_crt = openssl_csr_sign($res_csr, $ca_res_crt, $ca_res_key, $lifetime,
$args, $ca_serial);
if(!$res_crt) return false;
@ -319,10 +334,8 @@ function cert_create(& $cert, $caref, $keylen, $lifetime, $dn, $type="user", $di
return false;
// return our certificate information
$cert['caref'] = $caref;
$cert['crt'] = base64_encode($str_crt);
$cert['prv'] = base64_encode($str_key);
$cert['type'] = $type;
return true;
}

View File

@ -767,6 +767,43 @@ function system_pccard_start() {
return $res;
}
function system_webgui_create_certificate() {
global $config, $g;
if (!is_array($config['ca']))
$config['ca'] = array();
$a_ca =& $config['ca'];
if (!is_array($config['cert']))
$config['cert'] = array();
$a_cert =& $config['cert'];
log_error("Creating SSL Certificate for this host");
$cert = array();
$cert['refid'] = uniqid();
$cert['descr'] = gettext("webConfigurator default ({$cert['refid']})");
$dn = array(
'countryName' => "US",
'stateOrProvinceName' => "State",
'localityName' => "Locality",
'organizationName' => "{$g['product_name']} webConfigurator Self-Signed Certificate",
'emailAddress' => "admin@{$config['system']['hostname']}.{$config['system']['domain']}",
'commonName' => "{$config['system']['hostname']}-{$cert['refid']}");
$old_err_level = error_reporting(0); /* otherwise openssl_ functions throw warings directly to a page screwing menu tab */
if (!cert_create($cert, null, 2048, 2000, $dn, "self-signed", "sha256")){
while($ssl_err = openssl_error_string()){
log_error("Error creating WebGUI Certificate: openssl library returns: " . $ssl_err);
}
error_reporting($old_err_level);
return null;
}
error_reporting($old_err_level);
$a_cert[] = $cert;
$config['system']['webgui']['ssl-certref'] = $cert['refid'];
write_config(gettext("Generated new self-signed HTTPS certificate ({$cert['refid']})"));
return $cert;
}
function system_webgui_start() {
global $config, $g;
@ -790,36 +827,17 @@ function system_webgui_start() {
// Ensure that we have a webConfigurator CERT
$cert =& lookup_cert($config['system']['webgui']['ssl-certref']);
if(!is_array($cert) && !$cert['crt'] && !$cert['prv']) {
if (!is_array($config['ca']))
$config['ca'] = array();
$a_ca =& $config['ca'];
if (!is_array($config['cert']))
$config['cert'] = array();
$a_cert =& $config['cert'];
log_error("Creating SSL Certificate for this host");
$cert = array();
$cert['refid'] = uniqid();
$cert['descr'] = gettext("webConfigurator default");
mwexec("/usr/local/bin/openssl genrsa 1024 > {$g['tmp_path']}/ssl.key");
mwexec("/usr/local/bin/openssl req -new -x509 -nodes -sha256 -days 2000 -key {$g['tmp_path']}/ssl.key > {$g['tmp_path']}/ssl.crt");
$crt = file_get_contents("{$g['tmp_path']}/ssl.crt");
$key = file_get_contents("{$g['tmp_path']}/ssl.key");
unlink("{$g['tmp_path']}/ssl.key");
unlink("{$g['tmp_path']}/ssl.crt");
cert_import($cert, $crt, $key);
$a_cert[] = $cert;
$config['system']['webgui']['ssl-certref'] = $cert['refid'];
write_config(gettext("Importing HTTPS certificate"));
if(!$config['system']['webgui']['port'])
$portarg = "443";
$ca = ca_chain($cert);
$cert = system_webgui_create_certificate();
$crt = $cert['crt'];
$key = $cert['prv'];
} else {
$crt = base64_decode($cert['crt']);
$key = base64_decode($cert['prv']);
if(!$config['system']['webgui']['port'])
$portarg = "443";
$ca = ca_chain($cert);
}
if(!$config['system']['webgui']['port'])
$portarg = "443";
$ca = ca_chain($cert);
}
/* generate lighttpd configuration */

View File

@ -0,0 +1,8 @@
require_once("system.inc");
echo gettext("Generating a new self-signed SSL certificate for the GUI...");
$cert = system_webgui_create_certificate();
echo gettext("Done.\n");
echo gettext("Restarting webConfigurator...");
send_event("service restart webgui");
echo gettext("Done.\n");