From c08dacb1499202cf0bcb1200429b5eb3e6141750 Mon Sep 17 00:00:00 2001 From: Daniel De Graaf Date: Sun, 8 Aug 2010 18:45:19 -0400 Subject: [PATCH] Add gnutls-ca.pl for generating a simple CA chain using certtool --- .gitignore | 2 + extras/gnutls-ca.pl | 189 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100755 extras/gnutls-ca.pl diff --git a/.gitignore b/.gitignore index ca3ce3cc8..98a6ade6a 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ /inspircd /org.inspircd.plist /run +/ssl +/extras/ssl /include/inspircd_config.h /include/inspircd_version.h diff --git a/extras/gnutls-ca.pl b/extras/gnutls-ca.pl new file mode 100755 index 000000000..21af9c974 --- /dev/null +++ b/extras/gnutls-ca.pl @@ -0,0 +1,189 @@ +#!/usr/bin/perl +use strict; +use warnings; + +sub gen_key; +sub gen_ca; +sub gen_server; +sub ca_sign; +sub gen_templates; +sub key_info;; + +mkdir "ssl"; +chdir "ssl" or die $!; +mkdir "keys" and chmod 0700, "keys"; +mkdir "certs"; +gen_templates; + +my $what = shift || ''; +if ($what eq 'sign') { + gen_ca; + for my $req (@ARGV) { + my $out = $req; + $out =~ s/request/ca-sign/ or ($out .= '.sign'); + ca_sign $req, $out; + } +} elsif ($what eq 'server') { + gen_ca; + gen_server; + ca_sign 'server-request.pem', 'server-ca-sign.pem'; + print < to sign them with the single CA. +The file ssl/ca.pem can be used by clients to verify your servers. +END +} else { + print "Use: \n"; + print " $0 server Generate server certificates for one server\n"; + print " $0 sign cert Sign another server's request with the local CA\n"; + exit (@ARGV != 0); +} + +sub gen_key { + my $key = shift; + return if -e $key; + print "[\e[32m*\e[0m] Generating private key $key\n"; + + system "certtool --generate-privkey --outfile keys/tmp.pem 2>>log" and die; + my $fp; + open my $info, '-|', 'certtool --key-info < keys/tmp.pem' or die; + while (<$info>) { + m#Public Key ID: ([0-9A-F:]+)# and $fp = $1; + } + $fp or die "Cannot read key ID of the key we just made"; + $fp =~ s/://g; + $fp = lc $fp; + rename 'keys/tmp.pem', "keys/$fp.pem"; + unlink $key; + symlink "keys/$fp.pem", $key; +} + +sub gen_ca { + gen_key 'ca-key.pem'; + my @ca = stat 'ca.pem'; + my @ca_t = stat 'ca.info'; + if (!@ca || $ca[9] < $ca_t[9]) { + print "[\e[32m*\e[0m] Creating certificate authority (ca.pem)\n"; + system "certtool --generate-self-signed --template ca.info --load-privkey ca-key.pem --outfile tmp.pem 2>>log" and die; + my($fn, $certfp, $keyfp) = key_info; + + unlink "ca.pem"; + symlink $fn, "ca.pem"; + @ca = stat 'ca.pem'; + } +} + +sub gen_server { + gen_key 'server-key.pem'; + + my @server_t = stat 'server.info'; + my @server_req = stat 'server-request.pem'; + my @server_ss = stat 'server-selfsign.pem'; + + if (!@server_req || $server_req[9] < $server_t[9]) { + print "[\e[32m*\e[0m] Creating server certificate request (server-request.pem)\n"; + system "certtool --generate-request --template server.info --load-privkey server-key.pem --outfile server-request.pem 2>>log" and die; + @server_req = stat 'server-request.pem'; + } + + if (!@server_ss || $server_ss[9] < $server_t[9]) { + print "[\e[32m*\e[0m] Creating self-signed server certificate (server-selfsign.pem)\n"; + system "certtool --generate-self-signed --template server.info --load-privkey server-key.pem --outfile tmp.pem 2>>log" and die; + my($fn, $certfp, $keyfp) = key_info; + + unlink "server-selfsign.pem"; + symlink $fn, "server-selfsign.pem"; + } +} + +sub ca_sign { + my($in, $out) = @_; + my @ca = stat 'ca.pem'; + my @server_req = stat $in; + my @server_cs = stat $out; + if (!@server_cs || $server_cs[9] < $server_req[9] || $server_cs[9] < $ca[9]) { + print "[\e[32m*\e[0m] Signing $in with ca.pem ($out)\n"; + system "certtool --generate-certificate --load-request '$in' --load-ca-certificate ca.pem --load-ca-privkey ca-key.pem --template ca-signing.info --outfile tmp.pem 2>>log" and die; + my($fn, $certfp, $keyfp) = key_info; + + system "cat ca.pem $fn > certs/$certfp-full.pem"; + unlink $out; + symlink "certs/$certfp-full.pem", $out; + } +} + +sub gen_templates { + if (!-e 'server.info') { + open F, '>', 'server.info'; + print F <', 'ca.info'; + print F <', 'ca-signing.info'; + print F <) { + if (m#SHA-1 fingerprint:#) { + $certfp = <$info>; + } elsif (m#Public Key Id:#) { + $keyfp = <$info>; + } + } + chomp($certfp, $keyfp); + $certfp =~ s/^\t+//; + $keyfp =~ s/^\t+//; + my $fn = "certs/$certfp.pem"; + rename 'tmp.pem', $fn; + return($fn, $certfp, $keyfp); +}