# HG changeset patch # User Heiko Schlittermann # Date 1340227353 -7200 # Node ID 4f3be01b88b61a6e4c406886f4e444396d3183b7 works diff -r 000000000000 -r 4f3be01b88b6 .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Wed Jun 20 23:22:33 2012 +0200 @@ -0,0 +1,9 @@ +requests +ca/ca-csr.pem +ca/index.txt +ca/index.txt.attr +ca/index.txt.old +ca/ca-crt.pem +ca/private/ +ca/newcerts +ca/serial diff -r 000000000000 -r 4f3be01b88b6 bin/request --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bin/request Wed Jun 20 23:22:33 2012 +0200 @@ -0,0 +1,96 @@ +#! /usr/bin/perl + +use 5.010; +use strict; +use warnings; +use Pod::Usage; +use Getopt::Long; +use Template; +#use autodie; + +my $DIR = "requests"; + +my $opt_template = "request.cnf"; +my $opt_check; +my $opt_init; + +sub genpw($); + +MAIN: { + GetOptions( + "template=s" => \$opt_template, + "init" => \$opt_init, + "check" => \$opt_check, + "h|help" => sub { pod2usage(-exit => 0, -verbose => 1) }, + "m|man" => sub { pod2usage(-exit => 0, -verbose => 2, + -noperldoc => system("perldoc -V >/dev/null 2>&1")) } + ) or pod2usage; + + my $CN = shift; + mkdir($DIR), exit if $opt_init; + + pod2usage if not defined $CN; + + exit(-f "$DIR/$CN/csr.pem" ? 0 : 1) + if $opt_check; + + rmdir($_ = "$DIR/$CN"); # succeeds if empty + mkdir($_ = "$DIR/$CN") or die "directory $_: $!\n"; + + # create the config template + my $tt = Template->new( + INCLUDE_PATH => "ca/templates", + ) or die "$Template::ERROR\n"; + $tt->process($opt_template, { CN => $CN }, "$DIR/$CN/openssl.cnf") + or die $tt->error, "\n"; + $ENV{OPENSSL_CONF} = "$DIR/$CN/openssl.cnf"; + + # create the password file + open(my $pw, ">", $_ = "$DIR/$CN/secret") or die "$_: $!\n"; + say $pw genpw(10); + close($pw); + + system(openssl => "req", + qw(-new), + -keyout => "$DIR/$CN/key.pem", + -out => "$DIR/$CN/csr.pem", + -passout => "file:$DIR/$CN/secret"); +} + +sub genpw($) { + my $n = shift; + my @chars = (qw(_ . - /), "a".."z", "A".."Z", 0..9); + join "" => map { @chars[rand @chars + 1] } (1..$n); +} + + +__END__ + +=head1 NAME + + request - generate a ssl certificate request + +=head1 SYNOPSIS + + request [--init] + request [--template={file}] {CN} + +=head1 DESCRIPTION + +B generates a new SSL certificate signing request. The files +(CSR and KEY) are placed in F. The generated key is protected +by a passphrase. The passphrase is written to stdout and has to be saved +by the caller! + +=head1 OPTIONS + +=over + +=item B<--template> I + +The template file to be used for creating the request. The templates will be searched +unter F. The only substituted item is [%CN%]. (default: request.cnf) + +=cut + +# vim:sts=4 ts=4 sw=4 aw ai sm: diff -r 000000000000 -r 4f3be01b88b6 bin/sign --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bin/sign Wed Jun 20 23:22:33 2012 +0200 @@ -0,0 +1,123 @@ +#! /usr/bin/perl + +use 5.010; +use strict; +use warnings; +use Pod::Usage; +use Getopt::Long; +use Template; +use File::Copy; + +my $opt_template = "sign.cnf"; +my $opt_type = "client"; +my $opt_init; + +sub genpw($); +sub init($); + +MAIN: { + GetOptions( + "init" => \$opt_init, + "t|type=s" => \$opt_type, + "h|help" => sub { pod2usage(-exit => 0, -verbose => 1) }, + "m|man" => sub { pod2usage(-exit => 0, -verbose => 2, + -noperldoc => system("perldoc -V >/dev/null 2>&1")) } + ) and @ARGV or pod2usage; + my $CN = shift; + + if ($opt_init) { + init($CN); + exit 0; + } + + my $csr = "requests/$CN/csr.pem"; + if (not -f $csr) { + die "Can't find the request in $csr: $!\n"; + } + + $ENV{OPENSSL_CONF} = "ca/openssl.cnf"; + system openssl => "ca", + -in => $csr, + -out => "requests/$CN/crt.pem.tmp", + -extensions => $opt_type; + + if ($?) { + unlink "requests/$CN/crt.pem.tmp"; + exit 2; + } + + move "requests/$CN/crt.pem.tmp" => "requests/$CN/crt.pem"; + say "Certificate saved to requests/$CN/crt.pem"; + +} + +sub init($) { + my $cn = shift; + + mkdir "ca/newcerts"; + mkdir "ca/private"; + open(my $x, ">>ca/index.txt"); + close($x); + + return if -f "ca/ca-crt.pem"; + + if (not -f "ca/ca-csr.pem") { + system "bin/request", "--init"; + system "bin/request", "--check" => $cn; + $? and system "bin/request", "--template" => "ca-request.cnf", $cn; + { + local @ARGV = "requests/$cn/secret"; + chomp($_ = "REMEMBER(!) THE PASSPHRASE: " . <>); + unlink("requests/$cn/secret") or die "@ARGV: $!"; + $_ = join "\n", "-" x length, $_, "-" x length; + say; + } + copy "requests/$cn/csr.pem" => "ca/ca-csr.pem"; + move "requests/$cn/key.pem" => "ca/private/ca-key.pem"; + } + + + $ENV{OPENSSL_CONF} = "ca/openssl.cnf"; + system(openssl => qw( + ca -selfsign + -create_serial -out ca/ca-crt.pem -days 3650 + -extensions v3_ca + -in ca/ca-csr.pem)); +} + +__END__ + +=head1 NAME + + sign - sign a ssl certificate request + +=head1 SYNOPSIS + + sign --init {CN} + sign [--type=client|server] {CN} + +=head1 DESCRIPTION + +B signs a SSL certificate signing request. +The signing request is expected in FIF. +The resulting certificate will be written to +F/IF. + +=head1 OPTIONS + +=over + +=item B<--type> client|server + +Signs the certificate as client or server certificate (default: client) + +=item B<--init> + +Using the option a new CA will get initialized. It will create a CSR if +there is no CSR in FI/F already. For security +reasons the KEY file found in FI/F will be printed to +stdout and B. + +=cut + +# vim:sts=4 ts=4 sw=4 aw ai sm: diff -r 000000000000 -r 4f3be01b88b6 ca/openssl.cnf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ca/openssl.cnf Wed Jun 20 23:22:33 2012 +0200 @@ -0,0 +1,367 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca', 'req' and 'ts'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +# Policies used by the TSA examples. +tsa_policy1 = 1.2.3.4.1 +tsa_policy2 = 1.2.3.4.5.6 +tsa_policy3 = 1.2.3.4.5.7 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ca # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +unique_subject = no # Set to 'no' to allow creation of + # several ctificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/ca-crt.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/ca-key.pem# The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extentions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = default # use public key default MD +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_anything + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extentions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString (PKIX recommendation before 2004) +# utf8only: only UTF8Strings (PKIX recommendation after 2004). +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings. +string_mask = utf8only + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Saxony + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = Marktjagd + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = VPN + +commonName = Common Name (e.g. server FQDN or YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This is required for TSA certificates. +# extendedKeyUsage = critical,timeStamping + +[ ca_cert ] +basicConstraints = CA:TRUE +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +[ client ] +basicConstraints = CA:FALSE +nsComment = "OpenSSL generated certificate" +nsCertType = client +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +[ server ] +basicConstraints = CA:FALSE +nsComment = "OpenSSL CA generated certificate" +nsCertType = server +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +[ v3_ca ] + +# Extensions for a typical CA + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer + +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as an test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo + +#################################################################### +[ tsa ] + +default_tsa = tsa_config1 # the default TSA section + +[ tsa_config1 ] + +# These are used by the TSA reply generation only. +dir = ./demoCA # TSA root directory +serial = $dir/tsaserial # The current serial number (mandatory) +crypto_device = builtin # OpenSSL engine to use for signing +signer_cert = $dir/tsacert.pem # The TSA signing certificate + # (optional) +certs = $dir/cacert.pem # Certificate chain to include in reply + # (optional) +signer_key = $dir/private/tsakey.pem # The TSA private key (optional) + +default_policy = tsa_policy1 # Policy if request did not specify it + # (optional) +other_policies = tsa_policy2, tsa_policy3 # acceptable policies (optional) +digests = md5, sha1 # Acceptable message digests (mandatory) +accuracy = secs:1, millisecs:500, microsecs:100 # (optional) +clock_precision_digits = 0 # number of digits after dot. (optional) +ordering = yes # Is ordering defined for timestamps? + # (optional, default: no) +tsa_name = yes # Must the TSA name be included in the reply? + # (optional, default: no) +ess_cert_id_chain = no # Must the ESS cert id chain be included? + # (optional, default: no) diff -r 000000000000 -r 4f3be01b88b6 ca/templates/ca-request.cnf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ca/templates/ca-request.cnf Wed Jun 20 23:22:33 2012 +0200 @@ -0,0 +1,103 @@ +[ req ] +default_bits = [%RSABITS ? RSABITS : 2048%] +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString (PKIX recommendation before 2004) +# utf8only: only UTF8Strings (PKIX recommendation after 2004). +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings. +string_mask = utf8only + +#req_extensions = v3_ca # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Saxony + +localityName = Locality Name (eg, city) +localityName_default = Dresden + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = Marktjagd + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Certificate Authority + +commonName = Common Name (e.g. server FQDN or YOUR name) +commonName_max = 64 +commonName_default = [%CN%] + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer + +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as an test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + diff -r 000000000000 -r 4f3be01b88b6 ca/templates/request.cnf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ca/templates/request.cnf Wed Jun 20 23:22:33 2012 +0200 @@ -0,0 +1,103 @@ +[ req ] +default_bits = [%RSABITS ? RSABITS : 1024%] +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString (PKIX recommendation before 2004) +# utf8only: only UTF8Strings (PKIX recommendation after 2004). +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings. +string_mask = utf8only + +#req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Saxony + +localityName = Locality Name (eg, city) +localityName_default = Dresden + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = Marktjagd + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = VPN + +commonName = Common Name (e.g. server FQDN or YOUR name) +commonName_max = 64 +commonName_default = [%CN%] + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer + +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as an test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF +