0) || ($count_ip > 0)) { $server_altnames = "@alt_names"; } else { $server_altnames = "DNS:$common_name,email:copy"; } $configHOME = $config['home_dir']; $configRANDFILE = $config['random']; $configCa_dir = $config['ca_dir']; $configCert_dir = $config['cert_dir']; $configCrl_dir = $config['crl_dir']; $configDatabase = $config['index']; $configNew_certs_dir = $config['new_certs_dir']; $configPrivate_dir = $config['private_dir']; $configSerial = $config['serial']; $configCacert_pem = $config['cacert_pem']; $configCacrl_pem = $config['cacrl_pem']; $configCakey = $config['cakey']; $configDefault_md = $config['default_md']; $configBase_url = $config['base_url']; $configCrl_dist = $config['crl_distrib']; $configComment_root = $config['comment_root']; $configPolicy_url = $config['policy_url']; $configRevoke_url = $config['revoke_url']; $configComment_email = $config['comment_email']; $configComment_sign = $config['comment_sign']; $configComment_srv = $config['comment_srv']; $cnf_contents = " HOME = $configHOME RANDFILE = $configRANDFILE dir = $configCa_dir certs = $configCert_dir crl_dir = $configCrl_dir database = $configDatabase new_certs_dir = $configNew_certs_dir private_dir = $configPrivate_dir serial = $configSerial certificate = $configCacert_pem crl = $configCacrl_pem private_key = $configCakey crl_extentions = crl_ext default_days = 365 default_crl_days = 30 preserve = no default_md = $configDefault_md [ req ] default_bits = $keysize string_mask = nombstr prompt = no distinguished_name = req_name req_extensions = req_ext [ req_name] C=$country ST=$province L=$locality 0.O=$organization 1.O='$issuer' OU=$unit CN=$common_name emailAddress=$email [ ca ] default_ca = email_cert [ root_cert ] x509_extensions = root_ext default_days = 3650 policy = policy_supplied [ email_cert ] x509_extensions = email_ext default_days = 365 policy = policy_supplied [ email_signing_cert ] x509_extensions = email_signing_ext default_days = 365 policy = policy_supplied [ server_cert ] x509_extensions = server_ext default_days = 365 policy = policy_supplied [ vpn_cert ] x509_extensions = vpn_client_server_ext default_days = 365 policy = policy_supplied [ time_stamping_cert ] x509_extensions = time_stamping_ext default_days = 365 policy = policy_supplied [ policy_supplied ] countryName = supplied stateOrProvinceName = supplied localityName = supplied organizationName = supplied organizationalUnitName = supplied commonName = supplied emailAddress = supplied [ req_ext] basicConstraints = CA:false [ crl_ext ] issuerAltName=issuer:copy authorityKeyIdentifier=keyid:always,issuer:always [ root_ext ] basicConstraints = CA:true keyUsage = cRLSign, keyCertSign nsCertType = sslCA, emailCA, objCA subjectKeyIdentifier = hash subjectAltName = email:copy crlDistributionPoints = URI:$configBase_url$configCrl_dist nsComment = $configComment_root #nsCaRevocationUrl = nsCaPolicyUrl = $configBase_url$configPolicy_url [ email_ext ] basicConstraints = critical, CA:false keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = critical, emailProtection, clientAuth nsCertType = critical, client, email subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer:always subjectAltName = email:copy issuerAltName = issuer:copy crlDistributionPoints = URI:$configBase_url$configCrl_dist nsComment = $configComment_email nsBaseUrl = $configBase_url nsRevocationUrl = $configBase_url$configRevoke_url$serial nsCaPolicyUrl = $configBase_url$configPolicy_url [ email_signing_ext ] basicConstraints = critical, CA:false keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = critical, emailProtection, clientAuth, codeSigning nsCertType = critical, client, email subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer:always subjectAltName = email:copy issuerAltName = issuer:copy crlDistributionPoints = URI:$configBase_url$configCrl_dist nsComment = $configComment_sign nsBaseUrl = $configBase_url nsRevocationUrl = $configBase_url$configRevoke_url$serial nsCaPolicyUrl = $configBase_url$configPolicy_url [ server_ext ] basicConstraints = critical, CA:false keyUsage = critical, digitalSignature, keyEncipherment nsCertType = server extendedKeyUsage = critical, serverAuth subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer:always subjectAltName = $server_altnames issuerAltName = issuer:copy crlDistributionPoints = URI:$configBase_url$configCrl_dist nsComment = $configComment_srv nsBaseUrl = $configBase_url nsRevocationUrl = $configBase_url$configRevoke_url$serial nsCaPolicyUrl = $configBase_url$configPolicy_url [ time_stamping_ext ] basicConstraints = CA:false keyUsage = critical, nonRepudiation, digitalSignature extendedKeyUsage = timeStamping subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer:always subjectAltName = DNS:$common_name,email:copy issuerAltName = issuer:copy crlDistributionPoints = URI:$configBase_url$configCrl_dist nsComment = $config[comment_stamp] nsBaseUrl = $configBase_url nsRevocationUrl = $configBase_url$configRevoke_url$serial [ vpn_client_ext ] basicConstraints = critical, CA:false keyUsage = critical, digitalSignature extendedKeyUsage = critical, clientAuth nsCertType = critical, client subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer:always subjectAltName = DNS:$common_name,email:copy [ vpn_server_ext ] basicConstraints = critical, CA:false keyUsage = critical, digitalSignature, keyEncipherment extendedKeyUsage = critical, serverAuth nsCertType = critical, server subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer:always subjectAltName = DNS:$common_name,email:copy [ vpn_client_server_ext ] basicConstraints = critical, CA:false keyUsage = critical, digitalSignature, keyEncipherment extendedKeyUsage = critical, serverAuth, clientAuth nsCertType = critical, server, client subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer:always subjectAltName = DNS:$common_name,email:copy [alt_names] $alt_names "; # Write out the config file. $cnf_file = tempnam('../../tmp', 'cnf-'); // Why is this not in the phpki dir ? why ../../ ? $handle = fopen($cnf_file, "w"); fwrite($handle, $cnf_contents); fclose($handle); return($cnf_file); } // // Search the certificate index and return resulting // records in array[cert_serial_number][field_name]. // Fields: serial, country, province, locality, organization, // issuer, unit, common_name, email // function CAdb_to_array($search = '.*') { global $config; # Prepend a default status to search string if missing. #if (! ereg('^\^\[.*\]', $search)) $search = '^[VRE].*'.$search; if (! preg_match("/^\^\[.*\]/", $search)) { $search = '^[VRE].*'.$search; } # Include valid certs? #if (ereg('^\^\[.*V.*\]',$search)) $inclval = true; if (preg_match('/^\^\[.*V.*\]/', $search)) { $inclval = true; } # Include revoked certs? #if (ereg('^\^\[.*R.*\]',$search)) $inclrev = true; if (preg_match('/^\^\[.*R.*\]/', $search)) { $inclrev = true; } # Include expired certs? #if (ereg('^\^\[.*E.*\]',$search)) $inclexp = true; if (preg_match('/^\^\[.*E.*\]/', $search)) { $inclexp = true; } # There isn't really a status of 'E' in the openssl index. # Change (E)xpired to (V)alid within the search string. #$search = ereg_replace('^(\^\[.*)E(.*\])','\\1V\\2',$search); $search = preg_replace('/^(\^\[.*)E(.*\])/', '${1}V${2}', $search); $db = array(); exec('egrep -i '.escshellarg($search).' '.$config['index'], $x); foreach ($x as $y) { $i = CAdb_explode_entry($y); if (($i['status'] == "Valid" && $inclval) || ($i['status'] == "Revoked" && $inclrev) || ($i['status'] == "Expired" && $inclexp)) { $db[$i['serial']] = $i; } } return($db); } // // Returns an array containing the index record for // certificate $serial. // function CAdb_get_entry($serial) { global $config; $regexp = "^[VR]\t.*\t.*\t$serial\t.*\t.*$"; $x = exec('egrep '.escshellarg($regexp).' '.$config['index']); if ($x) { return CAdb_explode_entry($x); } else { return false; } } // // Returns the serial number of a VALID certificate matching // $email and/or $name. Returns FALSE if no match is found. // function CAdb_in($email = "", $name = "") { global $config; $email = escshellcmd($email); $name = escshellcmd($name); $regexp = "^[V].*CN=$name/(Email|emailAddress)=$email"; $x = exec('egrep '.escshellarg($regexp).' '.$config['index']); if ($x) { list($j,$j,$j,$serial,$j,$j) = explode("\t", $x); return "$serial"; } else { return false; } } // // Alias for CAdb_in() // function CAdb_serial($email, $name = '') { return CAdb_in($email, $name = ''); } // // Alias for CAdb_in() // function CAdb_exists($email, $name = '') { return CAdb_in($email, $name = ''); } // // Returns the certificate 'issuer' // function CAdb_issuer($serial) { global $config; $rec = CAdb_get_entry($serial); return $rec['issuer']; } // // Returns an array containing the respective fields given a // a raw line ($dbentry) from the certificate index. // Fields: serial, country, province locality, organization, // issuer, unit, common_name, email // function CAdb_explode_entry($dbentry) { $a = explode("\t", $dbentry); $b = preg_split('/\/([A-Z]|[a-z])+=/', $a[5]); switch ($a[0]) { case "V": $db['status'] = "Valid"; break; case "R": $db['status'] = "Revoked"; break; } // CA_cert_start/enddate // A date will be returned in this format // Feb 27 16:00:09 2020 GMT // Add a 'digital' sort key for digital date sorting later sscanf(CA_cert_startdate($a[3]), "%s%s%s%s", $mm, $dd, $tt, $yy); $db['issued'] = strftime("%Y-%b-%d", strtotime("$yy-$mm-$dd")); $db['issuedSort'] = strftime("%Y-%m-%d", strtotime("$yy-$mm-$dd")); sscanf(CA_cert_enddate($a[3]), "%s%s%s%s", $mm, $dd, $tt, $yy); $db['expires'] = strftime("%Y-%b-%d", strtotime("$yy-$mm-$dd")); $db['expiresSort'] = strftime("%Y-%m-%d", strtotime("$yy-$mm-$dd")); if (time() > strtotime("$yy-$mm-$dd")) { $db['status'] = "Expired"; } // Compatibility with migrated certs from openvpn-bridge if (count($b) == 7) { $db['serial'] = $a[3]; $db['country'] = $b[1]; $db['province'] = $b[2]; $db['locality'] = ''; $db['organization'] = $b[3]; $db['issuer'] = ''; $db['unit'] = $b[4]; $db['common_name'] = $b[5]; $db['email'] = $b[6]; } // Compatibility with renewed certs from openvpn-bridge elseif (count($b) == 8) { $db['serial'] = $a[3]; $db['country'] = $b[1]; $db['province'] = $b[2]; $db['locality'] = $b[3]; $db['organization'] = $b[4]; $db['issuer'] = ''; $db['unit'] = $b[5]; $db['common_name'] = $b[6]; $db['email'] = $b[7]; } // Else, it's a certificate created with phpki else { $db['serial'] = $a[3]; $db['country'] = $b[1]; $db['province'] = $b[2]; $db['locality'] = $b[3]; $db['organization'] = $b[4]; $db['issuer'] = $b[5]; $db['unit'] = $b[6]; $db['common_name'] = $b[7]; $db['email'] = $b[8]; } return $db; } // // Returns the date & time a specified certificate is revoked, // Returns FALSE if the certificate is not revoked. // function CAdb_is_revoked($serial) { global $config; $regexp = "^R\t.*\t.*\t$serial\t.*\t.*$"; $x = exec('egrep '.escshellarg($regexp).' '.$config['index']); if ($x) { list($j,$j,$revoke_date,$j,$j,$j) = explode("\t", $x); // Revoke date = 'R' + start date and is in this format // 200227162209Z sscanf($revoke_date, "%2s%2s%2s", $yy, $mm, $dd); return strftime("%b %d, %Y", strtotime("$yy-$mm-$dd")); } else { return false; } } // // Returns TRUE if a certificate is valid, otherwise FALSE. // function CAdb_is_valid($serial) { global $config; $regexp = "^V\t.*\t.*\t$serial\t.*\t.*$"; if (exec('egrep '.escshellarg($regexp).' '.$config['index'])) { return true; } else { return false; } } // // Returns the long-form certificate description as output by // openssl x509 -in certificatefile -text -purpose // function CA_cert_text($serial) { global $config; $certfile = $config['new_certs_dir'] . "/$serial.pem"; return(shell_exec(X509.' -in '.escshellarg($certfile).' -text -purpose 2>&1')); } // // Returns the long-form text of the Certificate Revocation List // openssl crl -in crlfile -text // function CA_crl_text() { global $config; $crlfile = $config['cacrl_pem']; return(shell_exec(CRL.' -in '.escshellarg($crlfile).' -text 2>&1')); } // Returns the static takey.pem file function ta_key_text() { global $config; return(shell_exec('cat '.escshellarg($config['private_dir']).'/takey.pem 2>&1')); } // Returns the dhparam file function dhparam_text() { global $config; return(shell_exec('cat '.escshellarg($config['private_dir']).'/dhparam2048.pem 2>&1')); } // Returns the root CA certificate file (PEM Encoded) function root_pem_text() { global $config; return(shell_exec('cat '.escshellarg($config['cacert_pem']).' 2>&1')); } // // Returns the subject of a certificate. // function CA_cert_subject($serial) { global $config; $certfile = $config['new_certs_dir'] . "/$serial.pem"; $x = exec(X509.' -in '.escshellarg($certfile).' -noout -subject 2>&1'); return(str_replace('subject=', '', $x)); } // // Returns the common name of a certificate. // function CA_cert_cname($serial) { global $config; #return(ereg_replace('^.*/CN=(.*)/.*','\\1',CA_cert_subject($serial))); return(preg_replace('/^.*\/CN=(.*)\/.*/', '${1}', CA_cert_subject($serial))); } // // Returns the email address of a certificate. // function CA_cert_email($serial) { global $config; $certfile = $config['new_certs_dir'] . "/$serial.pem"; $x = exec(X509.' -in '.escshellarg($certfile).' -noout -email 2>&1'); return($x); } // // Returns the effective date of a certificate. // function CA_cert_startdate($serial) { global $config; $certfile = $config['new_certs_dir'] . "/$serial.pem"; $x = exec(X509.' -in '.escshellarg($certfile).' -noout -startdate 2>&1'); return(str_replace('notBefore=', '', $x)); } // // Returns the expiration date of a certificate. // function CA_cert_enddate($serial) { global $config; $certfile = $config['new_certs_dir'] . "/$serial.pem"; $x = exec(X509.' -in '.escshellarg($certfile).' -noout -enddate 2>&1'); return(str_replace('notAfter=', '', $x)); } // // Revokes a specified certificate. // function CA_revoke_cert($serial) { global $config; $fd = fopen($config['index'], 'a'); flock($fd, LOCK_EX); $certfile = $config['new_certs_dir'] . "/$serial.pem"; $cmd_output[] = 'Revoking the certificate.'; $configCa_pwd = $config['ca_pwd']; $configOpenssl_cnf = $config['openssl_cnf']; exec(CA." -config $configOpenssl_cnf -revoke ".escshellarg($certfile)." -passin pass:'$configCa_pwd' 2>&1", $cmd_output, $ret); if ($ret == 0) { unset($cmd_output); list($ret, $cmd_output[]) = CA_generate_crl(); } fclose($fd); return array(($ret == true || $ret == 0 ? true : false), implode('
', $cmd_output)); } // // Creates a new certificate request, and certificate in various formats // according to specified parameters. PKCS12 bundle files contain the // private key, certificate, and CA certificate. // // Returns an array containing the output of failed openssl commands. // function CA_create_cert($cert_type = 'email', $country, $province, $locality, $organization, $unit, $common_name, $email, $expiry, $passwd, $keysize = 2048, $dns_names, $ip_addr) { global $config; # Wait here if another user has the database locked. $fd = fopen($config['index'], "a"); flock($fd, LOCK_EX); # Get the next available serial number $serial = trim(implode('', file($config['serial']))); $userkey = $config['private_dir'] . "/$serial-key.pem"; $userreq = $config['req_dir'] ."/$serial-req.pem"; $usercert = $config['new_certs_dir'] . "/$serial.pem"; $userder = $config['cert_dir'] . "/$serial.der"; $userpfx = $config['pfx_dir'] . "/$serial.pfx"; $expiry_days = round($expiry * 365.25, 0); $cnf_file = CA_create_cnf($country, $province, $locality, $organization, $unit, $common_name, $email, $keysize, $dns_names, $ip_addr, $serial); # Escape certain dangerous characters in user input $email = escshellcmd($email); $_passwd = escshellarg($passwd); $friendly_name = escshellarg($common_name); $extensions = escshellarg($cert_type.'_ext'); # Create the certificate request unset($cmd_output); $cmd_output[] = 'Creating certificate request.'; if (($_passwd) && ($_passwd != "''")) { exec(REQ." -new -newkey rsa:$keysize -keyout '$userkey' -out '$userreq' -config '$cnf_file' -days '$expiry_days' -passout pass:'$_passwd' 2>&1", $cmd_output, $ret); } else { exec(REQ." -new -newkey rsa:$keysize -keyout '$userkey' -out '$userreq' -config '$cnf_file' -days '$expiry_days' -nodes 2>&1", $cmd_output, $ret); } # Sign the certificate request and create the certificate if ($ret == 0) { unset($cmd_output); $cmd_output[] = "Signing $cert_type certificate request."; $configCa_pwd = $config['ca_pwd']; exec(CA." -config '$cnf_file' -in '$userreq' -out /dev/null -notext -days '$expiry_days' -passin pass:'$configCa_pwd' -batch -extensions $extensions 2>&1", $cmd_output, $ret); }; # Create DER format certificate if ($ret == 0) { unset($cmd_output); $cmd_output[] = "Creating DER format certificate."; exec(X509." -in '$usercert' -out '$userder' -inform PEM -outform DER 2>&1", $cmd_output, $ret); }; # Create a PKCS12 certificate file for download to Windows if ($ret == 0) { unset($cmd_output); $cmd_output[] = "Creating PKCS12 format certificate."; $configCacert_pem = $config['cacert_pem']; $configOrganization = $config['organization']; $configRandom = $config['random']; if (($_passwd) && ($_passwd != "''")) { $cmd_output[] = "infile: $usercert keyfile: $userkey outfile: $userpfx pass:'$_passwd'"; exec(PKCS12." -export -in '$usercert' -inkey '$userkey' -certfile '$configCacert_pem' -caname '$configOrganization' -out '$userpfx' -name $friendly_name -rand '$configRandom' -passin pass:'$_passwd' -passout pass:'$_passwd' 2>&1", $cmd_output, $ret); } else { $cmd_output[] = "infile: $usercert keyfile: $userkey outfile: $userpfx"; // reetp - this needs looking at exec(PKCS12." -export -in '$usercert' -inkey '$userkey' -certfile '$configCacert_pem' -caname '$configOrganization' -out '$userpfx' -name $friendly_name -nodes -passout pass: 2>&1", $cmd_output, $ret); //exec(PKCS12." -export -in '$usercert' -inkey '$userkey' -certfile '$config[cacert_pem]' -caname '$config[organization]' -out '$userpfx' -name $friendly_name -nodes 2>&1", $cmd_output, $ret); } }; #Unlock the CA database fclose($fd); #Remove temporary openssl config file. if (file_exists($cnf_file)) { unlink($cnf_file); } if ($ret == 0) { # Successful! # Return status=true and serial number of issued certificate. return array(true, $serial); } else { # Not successful. :-( # Clean up our loose ends. # Return status=false and openssl output/errors for debug. CA_remove_cert($serial); $cmd_output[] = 'Click on the "Help" link above for information on how to report this problem.'; return array(false, implode("
", $cmd_output)); } } // // Renews a specified certificate, revoking any existing valid versions. // Uses old certificate request to Creates a new request, and certificate // in various formats. // // Returns an array containing the output of failed openssl commands. // // FIXME: Yes, I know... This functions contains much duplicative code // from CA_create_cert(). Bleh! // function CA_renew_cert($old_serial, $expiry, $passwd) { global $config; # Do not renew a revoked certificate if a valid one exists for this # URL. Find and renew the valid certificate instead. if (CAdb_is_revoked($old_serial)) { $ret = CAdb_in(CA_cert_email($old_serial), CA_cert_cname($old_serial)); if ($ret && $old_serial != $ret) { $old_serial = $ret; } } # Valid certificates must be revoked prior to renewal. if (CAdb_is_valid($old_serial)) { $ret = CA_revoke_cert($old_serial); if (! $ret[0]) { return $ret; } } $cert_type = CA_cert_type($old_serial); $extensions = $cert_type.'_ext'; # Get common_name from old certificate for use as the # "friendly name" of PKCS12 certificate. $rec = CAdb_get_entry($old_serial); $country = $rec['country']; $province = $rec['province']; $locality = $rec['locality']; $organization = $rec['organization']; $unit = $rec['unit']; $common_name = $rec['common_name']; $email = $rec['email']; # Wait here if another user has the database locked. $fd = fopen($config['index'], "a"); flock($fd, LOCK_EX); # Get the next available serial number $serial = trim(implode('', file($config['serial']))); $old_userkey = $config['private_dir'] . "/$old_serial-key.pem"; $old_userreq = $config['req_dir'] . "/$old_serial-req.pem"; $userkey = $config['private_dir'] . "/$serial-key.pem"; $userreq = $config['req_dir'] . "/$serial-req.pem"; $usercert = $config['new_certs_dir'] . "/$serial.pem"; $userder = $config['cert_dir'] . "/$serial.der"; $userpfx = $config['pfx_dir'] . "/$serial.pfx"; $expiry_days = round($expiry * 365.25, 0); $cmd_output = array(); $ret = 0; # Create a new certificate request by copying the old request. if (! file_exists($old_userreq) || ! copy($old_userreq, $userreq)) { $cmd_output[] = 'Could not create new certificate request file.'; $ret = 1; } # Copy private key to new file. if ($ret == 0 && (! file_exists($old_userkey) || ! copy($old_userkey, $userkey))) { $cmd_output[] = "Could not update private key file."; $ret = 1; } $cnf_file = CA_create_cnf($country, $province, $locality, $organization, $unit, $common_name, $email); # "friendly name" of PKCS12 certificate. $friendly_name = escshellarg($rec['common_name']); # Escape dangerous characters in user input. $_passwd = escshellarg($passwd); $configCa_pwd = $config['ca_pwd']; $configCacert_pem = $config['cacert_pem']; $configOrganization = $config['organization']; $configRandom = $config['random']; # Sign the certificate request and create the certificate. if ($ret == 0) { unset($cmd_output); $cmd_output[] = "Signing the $cert_type certificate request."; exec(CA." -config '$cnf_file' -in '$userreq' -out /dev/null -notext -days '$expiry_days' -passin pass:'$configCa_pwd' -batch -extensions $extensions 2>&1", $cmd_output, $ret); }; # Create DER format certificate if ($ret == 0) { unset($cmd_output); $cmd_output[] = "Creating DER format certificate."; exec(X509." -in '$usercert' -out '$userder' -inform PEM -outform DER 2>&1", $cmd_output, $ret); }; # Create a PKCS12 certificate file for download to Windows if ($ret == 0) { unset($cmd_output); $cmd_output[] = "Creating PKCS12 format certificate."; if (($_passwd) && ($_passwd != "''")) { $cmd_output[] = "infile: $usercert keyfile: $userkey outfile: $userpfx pass:'$_passwd'"; exec(PKCS12." -export -in '$usercert' -inkey '$userkey' -certfile '$configCacert_pem' -caname '$configOrganization' -out '$userpfx' -name $friendly_name -rand '$configRandom' -passin pass:'$_passwd' -passout pass:'$_passwd' 2>&1", $cmd_output, $ret); } else { $cmd_output[] = "infile: $usercert keyfile: $userkey outfile: $userpfx"; // reetp - this needs looking at exec(PKCS12." -export -in '$usercert' -inkey '$userkey' -certfile '$configCacert_pem' -caname '$configOrganization' -out '$userpfx' -name $friendly_name -nodes -passout pass: 2>&1", $cmd_output, $ret); //exec(PKCS12." -export -in '$usercert' -inkey '$userkey' -certfile '$config[cacert_pem]' -caname '$config[organization]' -out '$userpfx' -name $friendly_name -nodes 2>&1", $cmd_output, $ret); } }; #Unlock the CA database fclose($fd); // Why is this here? //# https://github.com/radicand/phpki/issues/14 - but ereg is deprecated if (preg_match('/E-mail Protection/', $certtext)) { $cert_type = 'email'; } if (preg_match('/E-mail Protection/', $certtext) && preg_match('/Code Signing/', $certtext)) { $cert_type = 'email_signing'; } #Remove temporary openssl config file. if (file_exists($cnf_file)) { unlink($cnf_file); } if ($ret == 0) { return array(true, $serial); } else { # Not successful, so clean up before exiting. CA_remove_cert($serial); if (preg_match_array('.*private key.*', $cmd_output)) { $cmd_output[] = 'This was likely caused by entering the wrong certificate password.'; } else { $cmd_output[] = 'Click on the "Help" link above for information on how to report this problem.'; } return array(false, implode('
', $cmd_output)); } } // // Creates a new Certificate Revocation List and copies it the the approriate // locations. Returns error messages from failed commands. // function CA_generate_crl() { global $config; $configOpenssl_cnf = $config['openssl_cnf']; $configCacrl_pem = $config['cacrl_pem']; $configCa_pwd = $config['ca_pwd']; $configCacrl_der = $config['cacrl_der']; $ret = 0; $cmd_output[] = "Generating Certificate Revocation List."; exec(CA. " -gencrl -config '$configOpenssl_cnf' -out '$configCacrl_pem' -passin pass:'$configCa_pwd' 2>&1", $cmd_output, $ret); if ($ret == 0) { unset($cmd_output); $cmd_output[] = "Creating DER format Certificate Revocation List."; exec(CRL." -in '$configCacrl_pem' -out '$configCacrl_der' -inform PEM -outform DER 2>&1", $cmd_output, $ret); } return array(($ret == 0 ? true : false), implode('
', $cmd_output)); } // // Removes a specified certificate from the certificate index, // and all traces of it from the file system. // function CA_remove_cert($serial) { global $config; $userreq = $config['req_dir'] . "/$serial-req.pem"; $userkey = $config['private_dir'] . "/$serial-key.pem"; $usercert = $config['new_certs_dir'] . "/$serial.pem"; $userder = $config['cert_dir'] . "/$serial.der"; $userpfx = $config['pfx_dir'] ."/$serial.pfx"; $configIndex = $config['index']; # Wait here if another user has the database locked. $fd = fopen($configIndex, 'a'); flock($fd, LOCK_EX); if (file_exists($userreq)) { unlink($userreq); } if (file_exists($userkey)) { unlink($userkey); } if (file_exists($usercert)) { unlink($usercert); } if (file_exists($userder)) { unlink($userder); } if (file_exists($userpfx)) { unlink($userpfx); } $tmpfile = $configIndex .'.tmp'; copy($configIndex, $tmpfile); $regexp = "^[VR]\t.*\t.*\t".$serial."\t.*\t.*$"; exec('egrep -v '.escshellarg($regexp)." $tmpfile > $configIndex 2>/dev/null"); unlink($tmpfile); fclose($fd); } // // Returns the likely intended use for a specified certificate // (email, server, vpn). // function CA_cert_type($serial) { $certtext = CA_cert_text($serial); if (preg_match('~OpenSSL.* (E.?mail|Personal) .*Certificate~', $certtext) && preg_match('~Code Signing~', $certtext)) { $cert_type = 'email_signing'; // Was 'codesigning' but can't see that anywhere } elseif (preg_match('~OpenSSL.* (E.?mail|Personal) .*Certificate~', $certtext)) { $cert_type = 'email'; } elseif (preg_match('~OpenSSL.* Server .*Certificate~', $certtext)) { $cert_type = 'server'; } elseif (preg_match('~timeStamping|Time Stamping~', $certtext)) { $cert_type = 'time_stamping'; } elseif (preg_match('~TLS Web Client Authentication~', $certtext) && preg_match('~TLS Web Server Authentication~', $certtext)) { $cert_type = 'vpn_client_server'; } elseif (preg_match('~TLS Web Client Authentication~', $certtext)) { $cert_type = 'vpn_client'; } elseif (preg_match('~TLS Web Server Authentication~', $certtext)) { $cert_type = 'vpn_server'; } else { $cert_type = 'vpn_client_server'; } return $cert_type; } function CA_get_root_pem() { global $config; return(file_get_contents($config['cacert_pem'])); }