summaryrefslogtreecommitdiffstats
path: root/migrate.pl
diff options
context:
space:
mode:
authorrcritten <>2005-05-23 20:44:19 +0000
committerrcritten <>2005-05-23 20:44:19 +0000
commit49fe77804874ace94237aee6ff9a54d9cf82433f (patch)
tree5ed78799069fc3fd68503e3cc450a4d0817914d8 /migrate.pl
parente001ab8ebcd2566c73e12acf00060c780d95d6e0 (diff)
downloadmod_nss-49fe77804874ace94237aee6ff9a54d9cf82433f.tar.gz
mod_nss-49fe77804874ace94237aee6ff9a54d9cf82433f.tar.xz
mod_nss-49fe77804874ace94237aee6ff9a54d9cf82433f.zip
First crack at migrating an existing ssl.conf to nss.conf.
Diffstat (limited to 'migrate.pl')
-rwxr-xr-xmigrate.pl306
1 files changed, 306 insertions, 0 deletions
diff --git a/migrate.pl b/migrate.pl
new file mode 100755
index 0000000..fd0d990
--- /dev/null
+++ b/migrate.pl
@@ -0,0 +1,306 @@
+#!/usr/bin/perl
+#
+# Migrate configuration from OpenSSL to NSS
+
+use Cwd;
+use Getopt::Std;
+
+BEGIN {
+ $NSSDir = cwd();
+
+ $CACertificatePath = "";
+ $CACertificateFile = "";
+ $SSLCertificateFile = "";
+ $SSLCertificateKeyFile = "";
+ $passphrase = 0;
+}
+
+%skip = ( "SSLRandomSeed" => "",
+ "SSLSessionCache" => "",
+ "SSLMutex" => "",
+ "SSLCertificateChainFile" => "",
+ "SSLCARevocationPath" => "",
+ "SSLCARevocationFile" => "",
+ "SSLVerifyDepth" => "" ,
+ "SSLCryptoDevice" => "" ,
+ "LoadModule" => "" ,
+ );
+
+%insert = ( "SSLSessionCacheTimeout", "SSLSessionCacheSize 10000\nSSL3SessionCacheTimeout 86400\n",);
+
+getopts('ch');
+
+if ($opt_h) {
+ print "Usage: migrate.pl -c\n";
+ print "\t-c convert the certificates\n";
+ exit();
+}
+
+open (NSS, "> nss.conf") or die "Unable to open nss.conf: $!.\n";
+open (SSL, "< ssl.conf") or die "Unable to open ssl.conf: $!.\n";
+
+while (<SSL>) {
+ my $comment = 0;
+
+ # skip blank lines and comments
+ if (/^#/ || /^\s*$/) {
+ print NSS $_;
+ next;
+ }
+
+ m/(\w+)\s+(.+)/;
+ $stmt = $1;
+ $value = $2;
+
+ # Handle the special cases
+ if ($stmt eq "SSLVerifyClient" && $value eq "optional_no_ca") {
+ print NSS "# Replaced optional_no_ca with optional\n";
+ print NSS "SSLVerifyClient optional\n";
+ next;
+ }
+
+ if ($stmt eq "SSLCipherSuite") {
+ print NSS "SSLCipherSuite ", get_ciphers($val), "\n";
+ print NSS "SSLProtocol SSLv3,TLSv1\n";
+ $comment = 1;
+ } elsif ($stmt eq "SSLCACertificatePath") {
+ $CACertificatePath = $value;
+ $comment = 1;
+ } elsif ($stmt eq "SSLCACertificateFile") {
+ $CACertificateFile = $value;
+ $comment = 1;
+ } elsif ($stmt eq "SSLCertificateFile") {
+ print NSS "SSLCertificateDatabase $NSSDir\n";
+ print NSS "SSLNickName Server-Cert\n";
+ $SSLCertificateFile = $value;
+ $comment = 1;
+ } elsif ($stmt eq "SSLCertificateKeyFile") {
+ $SSLCertificateKeyFile = $value;
+ $comment = 1;
+ } elsif ($stmt eq "SSLPassPhraseDialog") {
+ print NSS "SSLPassPhraseHelper /usr/local/bin/nss_pcache\n";
+ $passphrase = 1;
+ $comment = 1;
+ }
+
+ if (exists($skip{$stmt})) {
+ print NSS "# Skipping, not applicable in mod_nss\n";
+ print NSS "##$_";
+ next;
+ }
+
+ if (exists($insert{$stmt})) {
+ print NSS "$_";
+ print NSS $insert{$stmt};
+ next;
+ }
+
+ # Fall-through to print whatever is left
+ if ($comment) {
+ print NSS "##$_";
+ $comment = 0;
+ } else {
+ print NSS $_;
+ }
+
+}
+
+if ($passphrase == 0) {
+ print NSS "SSLPassPhraseHelper /usr/sbin/nss_pcache\n";
+}
+
+close(NSS);
+close(SSL);
+
+#
+# Create NSS certificate database and import any existing certificates
+#
+
+if ($opt_c) {
+ print "Creating NSS certificate database.\n";
+ run_command("certutil -N -d $NSSDir");
+
+ # Convert the certificate into pkcs12 format
+ if ($SSLCertificateFile ne "" && $SSLCertificateKeyFile ne "") {
+ my $subject = get_cert_subject($SSLCertificateFile);
+ print "Importing certificate $subject as \"Server-Cert\".\n";
+ run_command("openssl pkcs12 -export -in $SSLCertificateFile -inkey $SSLCertificateKeyFile -out server.p12 -name \"Server-Cert\" -passout pass:foo");
+ run_command("pk12util -i server.p12 -d $NSSDir -W foo");
+ }
+
+ if ($CACertificateFile ne "") {
+ my $subject = get_cert_subject($CACertificateFile);
+ if ($subject ne "") {
+ print "Importing CA certificate $subject\n";
+ run_command("certutil -A -n \"$subject\" -t \"CT,,\" -d $NSSDir -a -i $CACertificateFile");
+ }
+ }
+
+ if ($CACertificatePath ne "") {
+ opendir(DIR, $CACertificatePath) or die "can't opendir $CACertificatePath: $!";
+ while (defined($file = readdir(DIR))) {
+ next if -d $file;
+
+ # we can operate directly on the hash files so don't have to worry
+ # about any SKIPME's.
+ if ($file =~ /hash.*/) {
+ my $subject = get_cert_subject("$CACertificatePath/$file");
+ if ($subject ne "") {
+ print "Importing CA certificate $subject\n";
+ run_command("certutil -A -n \"$subject\" -t \"CT,,\" -d $NSSDir -a -i $CACertificatePath/$file");
+ }
+ }
+ }
+ closedir(DIR);
+ }
+}
+
+print "Conversion complete.\n";
+print "You will need to:\n";
+print " - rename/remove ssl.conf or Apache will not start.\n";
+print " - verify the location of nss_pcache. It is set as /usr/local/bin/nss_pcache\n";
+
+exit(0);
+
+
+# Migrate configuration from OpenSSL to NSS
+sub get_ciphers {
+ my $str = shift;
+
+ %cipher_list = (
+ "rc4" => ":ALL:SSLv2:RSA:MD5:MEDIUM:RC4:",
+ "rc4export" => ":ALL:SSLv2:RSA:EXP:EXPORT40:MD5:RC4:",
+ "rc2" => ":ALL:SSLv2:RSA:MD5:MEDIUM:RC2:",
+ "rc2export" => ":ALL:SSLv2:RSA:EXP:EXPORT40:MD5:RC2:",
+ "des" => ":ALL:SSLv2:RSA:EXP:EXPORT56:MD5:DES:LOW:",
+ "desede3" => ":ALL:SSLv2:RSA:MD5:3DES:HIGH:",
+ "rsa_rc4_128_md5" => ":ALL:SSLv3:TLSv1:RSA:MD5:RC4:MEDIUM:",
+ "rsa_rc4_128_sha" => ":ALL:SSLv3:TLSv1:RSA:SHA:RC4:MEDIUM:",
+ "rsa_3des_sha" => ":ALL:SSLv3:TLSv1:RSA:SHA:3DES:HIGH:",
+ "rsa_des_sha" => ":ALL:SSLv3:TLSv1:RSA:SHA:DES:LOW:",
+ "rsa_rc4_40_md5" => ":ALL:SSLv3:TLSv1:RSA:EXP:EXPORT40:RC4:",
+ "rsa_rc2_40_md5" => ":ALL:SSLv3:TLSv1:RSA:EXP:EXPORT40:RC2:",
+ "rsa_null_md5" => ":SSLv3:TLSv1:RSA:MD5:NULL:",
+ "rsa_null_sha" => ":SSLv3:TLSv1:RSA:SHA:NULL:",
+ "rsa_des_56_sha" => ":ALL:SSLv3:TLSv1:RSA:DES:SHA:EXP:EXPORT56:",
+ "rsa_rc4_56_sha" => ":ALL:SSLv3:TLSv1:RSA:RC4:SHA:EXP:EXPORT56:",
+ );
+
+ $NUM_CIPHERS = 16;
+
+ for ($i = 0; $i < $NUM_CIPHERS; $i++) {
+ $selected[$i] = 0;
+ }
+
+ # Don't need to worry about the ordering properties of "+" because
+ # NSS always chooses the "best" cipher anyway. You can't specify
+ # preferred order.
+
+ # -1: this cipher is completely out
+ # 0: this cipher is currently unselected, but maybe added later
+ # 1: this cipher is selected
+
+ @s = split(/:/, $str);
+
+ for ($i = 0; $i <= $#s; $i++) {
+ $j = 0;
+ $val = 1;
+
+ # ! means this cipher is disabled forever
+ if ($s[$i] =~ /^!/) {
+ $val = -1;
+ ($s[$i] =~ s/^!//);
+ } elsif ($s[$i] =~ /^-/) {
+ $val = 0;
+ ($s[$i] =~ s/^-//);
+ } elsif ($s[$i] =~ /^+/) {
+ ($s[$i] =~ s/^+//);
+ }
+
+ for $cipher (sort keys %cipher_list) {
+ $match = 0;
+
+ # For embedded + we do an AND for all options
+ if ($s[$i] =~ m/(\w+\+)+/) {
+ @sub = split(/^\+/, $s[$i]);
+ $match = 1;
+ for ($k = 0; $k <=$#sub; $k++) {
+ if ($cipher_list{$cipher} !=~ m/:$sub[$k]:/) {
+ $match = 0;
+ }
+ }
+ } else { # straightforward match
+ if ($cipher_list{$cipher} =~ m/:$s[$i]:/) {
+ $match = 1;
+ }
+ }
+
+ if ($match && $selected[$j] != -1) {
+ $selected[$j] = $val;
+ }
+ $j++;
+ }
+ }
+
+ # NSS doesn't honor the order of a cipher list, it uses the "strongest"
+ # cipher available. So we'll print out the ciphers as SSLv2, SSLv3 and
+ # the NSS ciphers not available in OpenSSL.
+ $str = "SSLv2:SSLv3";
+ @s = split(/:/, $str);
+
+ $ciphersuite = "";
+
+ for ($i = 0; $i <= $#s; $i++) {
+ $j = 0;
+ for $cipher (sort keys %cipher_list) {
+ if ($cipher_list{$cipher} =~ m/:$s[$i]:/) {
+ if ($selected[$j]) {
+ $ciphersuite .= "+";
+ } else {
+ $ciphersuite .= "-";
+ }
+ $ciphersuite .= $cipher . ",";
+ }
+ $j++;
+ }
+ }
+
+ $ciphersuite .= "-fortezza,-fortezza_rc4_128_sha,-fortezza_null,-fips_des_sha,+fips_3des_sha,-rsa_aes_128_sha,-rsa_aes_256_sha";
+
+ return $ciphersuite;
+}
+
+# Given the filename of a PEM file, use openssl to fetch the certificate
+# subject
+sub get_cert_subject {
+ my $file = shift;
+ my $subject = "";
+
+ return "" if ! -T $file;
+
+ $subject = `openssl x509 -subject < $file | head -1`;
+ $subject =~ s/subject= \///; # Remove leading subject= \
+ $subject =~ s/\//,/g; # Replace / with , as separator
+ $subject =~ s/Email=.*(,){0,1}//; # Remove Email attribute
+ $subject =~ s/,$//; # Remove any trailing commas
+
+ chomp($subject);
+
+ return $subject;
+}
+
+#
+# Wrapper around the system() command
+
+sub run_command {
+ my @args = shift;
+ my $status = 0;
+
+ $status = 0xffff & system(@args);
+
+ return if ($status == 0);
+
+ print "Command '@args' failed: $!\n";
+
+ exit;
+}