Added support for true cert renewal, depends on recent upstream patch to
certutil targeted for nss 3.12.2, will patch downstream for now.
This commit is contained in:
parent
944ff68ec0
commit
054411e9e5
192
genkey.pl
192
genkey.pl
|
@ -70,9 +70,11 @@ sub usage
|
||||||
print STDERR <<EOH;
|
print STDERR <<EOH;
|
||||||
Usage: genkey [options] servername
|
Usage: genkey [options] servername
|
||||||
--test Test mode, faster seeding, overwrite existing key
|
--test Test mode, faster seeding, overwrite existing key
|
||||||
--genreq Just generate a CSR from an existing key
|
--genreq Generate a Certificate Signing Request (CSR)
|
||||||
--makeca Generate a private CA key instead
|
--makeca Generate a self-signed certificate for a CA
|
||||||
--days Days until expiry of self-signed certificate (default 30)
|
--days Days until expiry of self-signed certificate (default 30)
|
||||||
|
--renew CSR is for cert renewal, reusing existing key pair
|
||||||
|
--isca Renewal is for a CA certificate
|
||||||
--nss Use the nss database for keys and certificates
|
--nss Use the nss database for keys and certificates
|
||||||
EOH
|
EOH
|
||||||
exit 1;
|
exit 1;
|
||||||
|
@ -121,12 +123,16 @@ my $genreq_mode = '';
|
||||||
my $ca_mode = '';
|
my $ca_mode = '';
|
||||||
my $cert_days = 30;
|
my $cert_days = 30;
|
||||||
my $nss ='';
|
my $nss ='';
|
||||||
|
my $renew = '';
|
||||||
|
my $isca = '';
|
||||||
my $modNssDbDir = '';
|
my $modNssDbDir = '';
|
||||||
my $nssNickname = '';
|
my $nssNickname = '';
|
||||||
my $nssDBPrefix = '';
|
my $nssDBPrefix = '';
|
||||||
GetOptions('test|t' => \$test_mode,
|
GetOptions('test|t' => \$test_mode,
|
||||||
'genreq' => \$genreq_mode,
|
'genreq' => \$genreq_mode,
|
||||||
'days=i' => \$cert_days,
|
'days=i' => \$cert_days,
|
||||||
|
'renew' => \$renew,
|
||||||
|
'isca' => \$isca,
|
||||||
'nss|n' => \$nss,
|
'nss|n' => \$nss,
|
||||||
'makeca' => \$ca_mode) or usage();
|
'makeca' => \$ca_mode) or usage();
|
||||||
usage() unless @ARGV != 0;
|
usage() unless @ARGV != 0;
|
||||||
|
@ -176,16 +182,29 @@ if ($nss) {
|
||||||
#
|
#
|
||||||
|
|
||||||
if (!$nss) {
|
if (!$nss) {
|
||||||
if (!$genreq_mode && -f $keyfile && !$overwrite_key) {
|
if (!$genreq_mode && -f $keyfile && !$overwrite_key) {
|
||||||
Newt::newtWinMessage("Error", "Close",
|
Newt::newtWinMessage("Error", "Close",
|
||||||
"You already have a key file for this host in file:\n\n" .
|
"You already have a key file for this host in file:\n\n" .
|
||||||
$keyfile . "\n\n" .
|
$keyfile . "\n\n" .
|
||||||
"This script will not overwrite an existing key.\n" .
|
"This script will not overwrite an existing key.\n" .
|
||||||
"You will need to remove or rename this file in order to" .
|
"You will need to remove or rename this file in order to" .
|
||||||
"generate a new key for this host, then rerun the command");
|
"generate a new key for this host, then rerun the command");
|
||||||
Newt::Finished();
|
Newt::Finished();
|
||||||
exit 1;
|
exit 1;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
# check for the key in the database
|
||||||
|
if (!$genreq_mode && keyInDatabase($nssNickname,$modNssDbDir) &&
|
||||||
|
!$renew && !$overwrite_key) {
|
||||||
|
Newt::newtWinMessage("Error", "Close",
|
||||||
|
"You already have a key file for this host in the datatabase:\n\n" .
|
||||||
|
"$modNssDbDir" ." with nickname ". "$nssNickname" . "\n\n" .
|
||||||
|
"This script will not overwrite an existing key.\n" .
|
||||||
|
"You will need to remove or rename the database in order to" .
|
||||||
|
"generate a new key for this host, then rerun the command");
|
||||||
|
Newt::Finished();
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
@ -204,13 +223,14 @@ if (!$genreq_mode && -f $keyfile && !$overwrite_key) {
|
||||||
my @windows;
|
my @windows;
|
||||||
if ($genreq_mode) {
|
if ($genreq_mode) {
|
||||||
$useca = 1;
|
$useca = 1;
|
||||||
@windows = (
|
@windows = $renew
|
||||||
getkeysizeWindow,
|
? (passwordWindow,genReqWindow,)
|
||||||
|
: (getkeysizeWindow,
|
||||||
customKeySizeWindow,
|
customKeySizeWindow,
|
||||||
getRandomDataWindow,
|
getRandomDataWindow,
|
||||||
passwordWindow,
|
passwordWindow,
|
||||||
genReqWindow,
|
genReqWindow,
|
||||||
);
|
);
|
||||||
$doingwhat="CSR generation";
|
$doingwhat="CSR generation";
|
||||||
} elsif ($ca_mode) {
|
} elsif ($ca_mode) {
|
||||||
@windows = (CAwelcomeWindow,
|
@windows = (CAwelcomeWindow,
|
||||||
|
@ -393,6 +413,36 @@ sub clearSensitiveData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Remove a directory and its contents
|
||||||
|
sub removeDirectory {
|
||||||
|
my ($dir) = @_;
|
||||||
|
if (-f $dir) {
|
||||||
|
opendir(DOOMED, $dir) || die("Cannot open directory");
|
||||||
|
my @thefiles= readdir(DOOMED);
|
||||||
|
foreach my $file (@thefiles) {
|
||||||
|
unlink @file;
|
||||||
|
}
|
||||||
|
closedir(DOOMED);
|
||||||
|
rmdir $dir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Print error message
|
||||||
|
sub printError {
|
||||||
|
my ($msg) = @_;
|
||||||
|
Newt::Suspend();
|
||||||
|
print STDERR "$msg\n";
|
||||||
|
Newt::Resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
# Is the given key in the database?
|
||||||
|
sub keyInDatabase {
|
||||||
|
my ($nickname, $dbdir) = @_;
|
||||||
|
my $tmp = "tmp";
|
||||||
|
my $answer = `$bindir/certutil -L -d $dbdir | grep $nickname`;
|
||||||
|
return $answer;
|
||||||
|
}
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# The window functions
|
# The window functions
|
||||||
|
|
||||||
|
@ -735,7 +785,8 @@ EOT
|
||||||
# module acces password instead.
|
# module acces password instead.
|
||||||
sub passwordWindow
|
sub passwordWindow
|
||||||
{
|
{
|
||||||
return moduleAccesPasswordWindow() if $nss;
|
return moduleAccesPasswordWindow() if $nss;
|
||||||
|
return "Next" if $renew;
|
||||||
|
|
||||||
my $message = <<EOT;
|
my $message = <<EOT;
|
||||||
At this stage you can set the passphrase on your private key. If you
|
At this stage you can set the passphrase on your private key. If you
|
||||||
|
@ -869,7 +920,8 @@ sub makeCertNSS
|
||||||
# If no days specified it's a ca so use 2 years
|
# If no days specified it's a ca so use 2 years
|
||||||
use integer;
|
use integer;
|
||||||
my $months = $days / 30;
|
my $months = $days / 30;
|
||||||
my $trustargs = "\"" . "TCu,TCu,TCuw". "\"";
|
my $trustargs = $ca_mode ? "CT,," : "u,,";
|
||||||
|
$trustargs = "\"" . $trustargs. "\"";
|
||||||
|
|
||||||
my $args = "-S ";
|
my $args = "-S ";
|
||||||
$args .= "-n $nickname ";
|
$args .= "-n $nickname ";
|
||||||
|
@ -1032,6 +1084,69 @@ sub genRequestOpenSSL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Renew a certificate which is stored in the nss database
|
||||||
|
sub renewCertNSS
|
||||||
|
{
|
||||||
|
my ($csrfile, $dbdir, $dbprefix, $nickname, $days, $pwdfile) = @_;
|
||||||
|
|
||||||
|
use integer;
|
||||||
|
my $months = $days ? $days / 30 : 24;
|
||||||
|
|
||||||
|
# Build the arguments for a certificate renewal request
|
||||||
|
# This is a request where we reuse the existing key pair
|
||||||
|
|
||||||
|
my $args = "-R ";
|
||||||
|
$args .= "-d $dbdir ";
|
||||||
|
$args .= "-p $dbprefix " if $dbprefix;
|
||||||
|
$args .= "-a "; ## using ascii
|
||||||
|
$args .= "-k $nickname "; ## pass cert nickname as key id
|
||||||
|
$args .= "-f $pwdfile " if $pwdfile;
|
||||||
|
$args .= "-v $months ";
|
||||||
|
$args .= "-o $csrfile ";
|
||||||
|
|
||||||
|
nssUtilCmd("$bindir/certutil", $args);
|
||||||
|
|
||||||
|
if (!-f $csrfile) {
|
||||||
|
Newt::newtWinMessage("Error", "Close",
|
||||||
|
"Was not able to create a CSR for this ".
|
||||||
|
"host:\n\nPress return to exit");
|
||||||
|
Newt::Finished();
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Renew a certificate which is stored in a PEM file
|
||||||
|
sub renewCertOpenSSL
|
||||||
|
{
|
||||||
|
my ($csrfile, # output
|
||||||
|
$certfile,$keyfile,$days,$isca) = @_;
|
||||||
|
|
||||||
|
use integer;
|
||||||
|
my $months = $days ? $days / 30 : 24;
|
||||||
|
|
||||||
|
# Build the arguments for a certificate renewal request
|
||||||
|
# This is a request where we reuse the existing key pair
|
||||||
|
|
||||||
|
my $args = "--command genreq ";
|
||||||
|
$args .= "--renew $certfile ";
|
||||||
|
$args .= "--input $keyfile ";
|
||||||
|
$args .= "--validity $months ";
|
||||||
|
$args .= "--out $csrfile ";
|
||||||
|
|
||||||
|
nssUtilCmd("$bindir/keyutil", $args);
|
||||||
|
|
||||||
|
unlink($noisefile);
|
||||||
|
Newt::Resume();
|
||||||
|
|
||||||
|
if (!-f $csrfile) {
|
||||||
|
Newt::newtWinMessage("Error", "Close",
|
||||||
|
"Unable to create a cert signing request for this ".
|
||||||
|
"host:\n\nPress return to exit");
|
||||||
|
Newt::Finished();
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sub AddField
|
sub AddField
|
||||||
{
|
{
|
||||||
my ($panel, $row, $msg, $default, $width, $topspace, $flags) = (@_, 0, 0);
|
my ($panel, $row, $msg, $default, $width, $topspace, $flags) = (@_, 0, 0);
|
||||||
|
@ -1193,12 +1308,61 @@ EOT
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Cert signing request generation for renewal
|
||||||
|
sub renewCert
|
||||||
|
{
|
||||||
|
my ($csrfile) = @_;
|
||||||
|
|
||||||
|
my $tempDbDir = "/tmp/nss.".$$;
|
||||||
|
|
||||||
|
# Get a comfirmation
|
||||||
|
my $msg = "You are about to issue a certificate renewal";
|
||||||
|
my $panel = Newt::Panel(1, 2, "Certificate Renewal");
|
||||||
|
$panel->Add(0, 0,
|
||||||
|
Newt::TextboxReflowed(60, 10, 10, 0,
|
||||||
|
"Would you like to send a Certificate Request" .
|
||||||
|
"for\n\n$servername".
|
||||||
|
"\nto a Certificate Authority (CA)?"));
|
||||||
|
|
||||||
|
$panel->Add(0, 1, DoubleButton("Yes", "No"));
|
||||||
|
$ret = &RunForm($panel);
|
||||||
|
$panel->Hide();
|
||||||
|
undef $panel;
|
||||||
|
|
||||||
|
return "Cancel" if $ret eq "Cancel";
|
||||||
|
|
||||||
|
# Cert to renew could be in the nss database or in a pem file
|
||||||
|
|
||||||
|
if ($nss) {
|
||||||
|
# Renew cert in the nss database
|
||||||
|
renewCertNSS(
|
||||||
|
$csrfile,
|
||||||
|
$modNssDbDir,
|
||||||
|
$nssDBPrefix,
|
||||||
|
$nssNickname,
|
||||||
|
$days,
|
||||||
|
$tmpPasswordFile);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
# Renew cert in a PEM file
|
||||||
|
renewCertOpenSSL(
|
||||||
|
$csrfile,
|
||||||
|
$certfile, # contains cert to renew
|
||||||
|
$keyfile, # contains encrypted private key
|
||||||
|
$days,
|
||||||
|
$isca);
|
||||||
|
|
||||||
|
## FIXME don't harcode password - keypwdfile and I
|
||||||
|
## though it was the p12 file pwd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sub genReqWindow
|
sub genReqWindow
|
||||||
{
|
{
|
||||||
return "Skip" unless $useca;
|
return "Skip" unless $useca;
|
||||||
|
|
||||||
$keyfile = $ssltop."/private/".$servername.".key";
|
$keyfile = $ssltop."/private/".$servername.".key";
|
||||||
$certfile = $ssltop."/certs/".$servername.".cert";
|
$certfile = $ssltop."/certs/".$servername.".crt";
|
||||||
|
|
||||||
$num = 0;
|
$num = 0;
|
||||||
while (-f $ssltop."/certs/".$servername.".$num.csr") {
|
while (-f $ssltop."/certs/".$servername.".$num.csr") {
|
||||||
|
@ -1206,6 +1370,8 @@ sub genReqWindow
|
||||||
}
|
}
|
||||||
$csrfile = $ssltop."/certs/".$servername.".$num.csr";
|
$csrfile = $ssltop."/certs/".$servername.".$num.csr";
|
||||||
|
|
||||||
|
return renewCert($csrfile) if $renew;
|
||||||
|
|
||||||
my $msg = "You are about to be asked to enter information that will be ".
|
my $msg = "You are about to be asked to enter information that will be ".
|
||||||
"incorporated into your certificate request to a CA. What you are about to ".
|
"incorporated into your certificate request to a CA. What you are about to ".
|
||||||
"enter is what is called a Distinguished Name or a DN. There are ".
|
"enter is what is called a Distinguished Name or a DN. There are ".
|
||||||
|
|
Loading…
Reference in New Issue