<?php CA_remove_cert($serial);
function CA_renew_cert($old_serial, $expiry, $passwd) { global $config; # Don't 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); # 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:"******" -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) { $cmd_output[] = "infile: {$usercert} keyfile: {$userkey} outfile: {$userpfx} pass: {$_passwd}"; exec(PKCS12 . " -export -in '{$usercert}' -inkey '{$userkey}' -certfile " . $config['cacert_pem'] . " -caname " . $config['organization'] . " -out '{$userpfx}' -name {$friendly_name} -rand " . $config['random'] . " -passin pass:{$_passwd} -passout pass:{$_passwd} 2>&1", $cmd_output, $ret); } else { $cmd_output[] = "infile: {$usercert} keyfile: {$userkey} outfile: {$userpfx}"; #exec(PKCS12." -export -in '$usercert' -inkey '$userkey' -certfile '$config[cacert_pem]' -caname '$config[organization]' -out '$userpfx' -name $friendly_name -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) { return array(true, $serial); } else { # Not successful, so clean up before exiting. CA_remove_cert($serial); if (eregi_array('/.*private key.*/', $cmd_output)) { $cmd_output[] = '<strong>This was likely caused by entering the wrong certificate password.</strong>'; } else { $cmd_output[] = '<strong>Click on the "Help" link above for information on how to report this problem.</strong>'; } return array(false, implode('<br>', $cmd_output)); } }