From 3a877e4ae636fd00d8610faecde84ad7067b60ac Mon Sep 17 00:00:00 2001 From: jim-p Date: Mon, 4 Nov 2019 14:30:54 -0500 Subject: [PATCH] Enforce a max lifetime for CA/Cert/CRL. Issue #3956 --- src/etc/inc/certs.inc | 16 +++++++++------- src/usr/local/www/system_camanager.php | 10 ++++++++-- src/usr/local/www/system_certmanager.php | 16 +++++++++++++--- src/usr/local/www/system_crlmanager.php | 9 +++------ 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/etc/inc/certs.inc b/src/etc/inc/certs.inc index 11db60ab4d..75fd2e66ce 100644 --- a/src/etc/inc/certs.inc +++ b/src/etc/inc/certs.inc @@ -51,6 +51,8 @@ $cert_altname_types = array( 'email' => gettext('email address'), ); +global $cert_max_lifetime; +$cert_max_lifetime = 12000; function & lookup_ca($refid) { global $config; @@ -937,20 +939,20 @@ function cert_usedby_description($refid, $certificates_used_by_packages) { /* Detect a rollover at 2038 on some platforms (e.g. ARM) * See: https://redmine.pfsense.org/issues/9098 */ -function crl_get_max_lifetime($max = 9999) { - if ($max <= 0) { - return 0; - } +function cert_get_max_lifetime() { + global $cert_max_lifetime; + $max = $cert_max_lifetime; + $current_time = time(); while ((int)($current_time + ($max * 24 * 60 * 60)) < 0) { $max--; } - return $max; + return min($max, $cert_max_lifetime); } function crl_create(& $crl, $caref, $name, $serial = 0, $lifetime = 3650) { global $config; - $max_lifetime = crl_get_max_lifetime(); + $max_lifetime = cert_get_max_lifetime(); $ca =& lookup_ca($caref); if (!$ca) { return false; @@ -987,7 +989,7 @@ function crl_update(& $crl) { require_once('X509_CRL.php'); global $config; - $max_lifetime = crl_get_max_lifetime(); + $max_lifetime = cert_get_max_lifetime(); $ca =& lookup_ca($crl['caref']); if (!$ca) { return false; diff --git a/src/usr/local/www/system_camanager.php b/src/usr/local/www/system_camanager.php index 9cca03955c..3eeb64c7c6 100644 --- a/src/usr/local/www/system_camanager.php +++ b/src/usr/local/www/system_camanager.php @@ -42,6 +42,8 @@ $ca_keylens = array("1024", "2048", "3072", "4096", "6144", "7680", "8192", "153 $ca_keytypes = array("RSA", "ECDSA"); global $openssl_digest_algs; global $cert_strict_values; +$max_lifetime = cert_get_max_lifetime(); +$default_lifetime = min(3650, $max_lifetime); $openssl_ecnames = openssl_get_curve_names(); if (isset($_REQUEST['id']) && is_numericint($_REQUEST['id'])) { @@ -116,7 +118,7 @@ if ($act == "new") { $pconfig['keylen'] = "2048"; $pconfig['ecname'] = "brainpoolP256r1"; $pconfig['digest_alg'] = "sha256"; - $pconfig['lifetime'] = "3650"; + $pconfig['lifetime'] = $default_lifetime; $pconfig['dn_commonname'] = "internal-ca"; } @@ -229,6 +231,9 @@ if ($_POST['save']) { if (!in_array($_POST["digest_alg"], $openssl_digest_algs)) { array_push($input_errors, gettext("Please select a valid Digest Algorithm.")); } + if ($_POST['lifetime'] > $max_lifetime) { + $input_errors[] = gettext("Lifetime is longer than the maximum allowed value. Use a shorter lifetime."); + } } /* save modifications */ @@ -700,7 +705,8 @@ $section->addInput(new Form_Input( 'lifetime', '*Lifetime (days)', 'number', - $pconfig['lifetime'] + $pconfig['lifetime'], + ['max' => $max_lifetime] )); $section->addInput(new Form_Input( diff --git a/src/usr/local/www/system_certmanager.php b/src/usr/local/www/system_certmanager.php index 58f2540040..92244b5b7f 100644 --- a/src/usr/local/www/system_certmanager.php +++ b/src/usr/local/www/system_certmanager.php @@ -49,6 +49,8 @@ $cert_types = array( global $cert_altname_types; global $openssl_digest_algs; global $cert_strict_values; +$max_lifetime = cert_get_max_lifetime(); +$default_lifetime = min(3650, $max_lifetime); $openssl_ecnames = openssl_get_curve_names(); if (isset($_REQUEST['userid']) && is_numericint($_REQUEST['userid'])) { @@ -106,7 +108,7 @@ if ($act == "new") { $pconfig['csr_digest_alg'] = "sha256"; $pconfig['csrsign_digest_alg'] = "sha256"; $pconfig['type'] = "user"; - $pconfig['lifetime'] = "3650"; + $pconfig['lifetime'] = $default_lifetime; } if ($act == "exp") { @@ -230,6 +232,9 @@ if ($_POST['save']) { $input_errors[] = gettext("This private does not appear to be valid."); $input_errors[] = gettext("Key data field should be blank, or a valid x509 private key"); } + if ($_POST['lifetime'] > $max_lifetime) { + $input_errors[] = gettext("Lifetime is longer than the maximum allowed value. Use a shorter lifetime."); + } } if ($pconfig['method'] == "import") { @@ -260,6 +265,9 @@ if ($_POST['save']) { gettext("Certificate Type"), gettext("Lifetime"), gettext("Common Name")); + if ($_POST['lifetime'] > $max_lifetime) { + $input_errors[] = gettext("Lifetime is longer than the maximum allowed value. Use a shorter lifetime."); + } } if ($pconfig['method'] == "external") { @@ -740,7 +748,8 @@ if ($act == "new" || (($_POST['save'] == gettext("Save")) && $input_errors)) { 'csrsign_lifetime', '*Certificate Lifetime (days)', 'number', - $pconfig['csrsign_lifetime'] ? $pconfig['csrsign_lifetime']:'3650' + $pconfig['csrsign_lifetime'] ? $pconfig['csrsign_lifetime']:$default_lifetime, + ['max' => $max_lifetime] ))->setHelp('The length of time the signed certificate will be valid, in days. %1$s' . 'Server certificates should not have a lifetime over 825 days or some platforms ' . 'may consider the certificate invalid.', '
'); @@ -841,7 +850,8 @@ if ($act == "new" || (($_POST['save'] == gettext("Save")) && $input_errors)) { 'lifetime', '*Lifetime (days)', 'number', - $pconfig['lifetime'] + $pconfig['lifetime'], + ['max' => $max_lifetime] ))->setHelp('The length of time the signed certificate will be valid, in days. %1$s' . 'Server certificates should not have a lifetime over 825 days or some platforms ' . 'may consider the certificate invalid.', '
'); diff --git a/src/usr/local/www/system_crlmanager.php b/src/usr/local/www/system_crlmanager.php index 07c6c3d10f..65ff5b0652 100644 --- a/src/usr/local/www/system_crlmanager.php +++ b/src/usr/local/www/system_crlmanager.php @@ -34,11 +34,8 @@ require_once("openvpn.inc"); require_once("pfsense-utils.inc"); require_once("vpn.inc"); -$max_lifetime = crl_get_max_lifetime(); -$default_lifetime = 3650; -if ($max_lifetime < $default_lifetime) { - $default_lifetime = $max_lifetime; -} +$max_lifetime = cert_get_max_lifetime(); +$default_lifetime = min(9999, $max_lifetime); global $openssl_crl_status; @@ -436,7 +433,7 @@ if ($act == "new" || $act == gettext("Save")) { 'Serial', 'number', $pconfig['serial'], - ['min' => '0', 'max' => '9999'] + ['min' => '0'] )); $form->add($section);