simple functionality now
authorHeiko Schlittermann <hs@schlittermann.de>
Tue, 26 Jan 2010 23:26:08 +0100
changeset 0 730be7994b86
child 1 f44419b55cf0
simple functionality now
.hgignore
.perltidyrc
bin/ca
templates/ca
templates/openssl.cnf
templates/req
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Tue Jan 26 23:26:08 2010 +0100
@@ -0,0 +1,3 @@
+style: glob
+var/
+CA/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.perltidyrc	Tue Jan 26 23:26:08 2010 +0100
@@ -0,0 +1,2 @@
+--paren-tightness=2
+--square-bracket-tightness=2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/ca	Tue Jan 26 23:26:08 2010 +0100
@@ -0,0 +1,206 @@
+#! /usr/bin/perl
+use strict;
+use warnings;
+use Template;
+use IO::File;
+use File::Path;
+use File::Temp qw(tempdir);
+use File::Basename;
+use Getopt::Long qw(GetOptionsFromArray);
+use Pod::Usage;
+
+my $CA_CRT   = "CA/ca-crt.pem";
+my $CA_KEY   = "CA/private/ca-key.pem";
+my $CA_DIR   = "./var";
+
+my %TEMPLATE = (
+    ca => "templates/ca",
+    req => "templates/req",
+);
+
+my $TMP      = tempdir("/tmp/$ENV{USER}.ca.XXXXXX", CLEANUP => 1);
+
+my $opt_days    = undef;    # see the templates/ca for a default
+my $opt_type    = undef;    # see the templates/ca for a default
+my $opt_policy  = "de";     # see the templates/ca for a default
+my $opt_outfile = undef;
+my $opt_force = undef;
+
+sub init_ca();
+sub ask_pass($);
+
+MAIN: {
+    my $csrfile;
+
+    GetOptions(
+        "d|days=i"    => \$opt_days,
+        "t|type=s"    => \$opt_type,
+        "p|policy=s"  => \$opt_policy,
+        "o|outfile=s" => \$opt_outfile,
+	"force"	      => \$opt_force,
+	"init"	      => sub { init_ca(); exit 0; },
+        "h|help"      => sub { pod2usage(-verbose => 1, -exit => 0) },
+        "m|man"       => sub { pod2usage(-verbose => 2, -exit => 0) },
+    ) or pod2usage;
+
+    pod2usage if @ARGV > 1;
+    $csrfile = $ARGV[0];    # don't shift, we'll need it later!
+
+    my $csr = new IO::File "$TMP/csr" => "w+"
+      or die "Can't open +>$TMP/csr: $!\n";
+    my $cnf = new IO::File "$TMP/cnf" => "w"
+      or die "Can't open >$TMP/cnf: $!\n";
+    my $crt = new IO::File "$TMP/crt" => "w+"
+      or die "Can't open +>$TMP/crt: $!\n";
+    my $tt2 = new Template or die $Template::ERROR;
+
+    # get a private copy of the request
+    print { IO::File->new("|openssl req -out $TMP/csr") } <>;
+    open(STDIN, "</dev/tty") if not defined $csrfile;
+
+    die "CSR is empty" if not -s $csr;
+
+    $tt2->process(
+        $TEMPLATE{ca},
+        {
+            type   => $opt_type,
+            days   => $opt_days,
+            policy => "policy_$opt_policy",
+            cacrt  => $CA_CRT,
+	    cakey  => $CA_KEY,
+	    cadir  => $CA_DIR,
+        } => "$TMP/cnf"
+    ) or die $tt2->error, "\n";
+
+    system( "openssl ca -config $TMP/cnf -in $TMP/csr -out $TMP/crt"
+          . " -utf8 \${CA_PASS:+-passin env:CA_PASS}");
+
+    die "ERR: Cert is zero size\n" if not -s $crt;
+
+    # get the name of the output crt file
+    my $outfile = $opt_outfile;
+    if (not defined $outfile and defined($_ = $csrfile)) {
+        if    (/(.*[\W_])(?:req|csr).pem$/) { $outfile = "$1crt.pem" }
+        elsif (/(.*[\W_])req$/)             { $outfile = "$1crt" }
+        else                                { $outfile .= ".crt.pem" }
+    }
+
+    # to be sure not to have an invalid/dangerous file name
+    fork() or do {
+        open(STDOUT, ">$outfile")
+          if defined $outfile
+              or die "Can't open >$outfile: $!\n";
+        exec "openssl x509 -in $TMP/crt";
+        die "Can't exec openssl x509: $!\n";
+    };
+    wait;
+    exit;
+}
+
+sub verbose($) {
+    warn $_[0], " \n ";
+}
+
+sub ask_pass($) {
+    my $prompt = shift;
+    my @keys = ("x", "y");
+
+    while (1) {
+	print $prompt;
+	my $stty = `stty -g`;
+	system("stty -echo");
+	chomp($keys[0] = IO::File->new("/dev/tty")->getline());
+	print "\n";
+	system("stty $stty");
+	print "please again for verification: ";
+	system("stty -echo");
+	chomp($keys[1] = IO::File->new("/dev/tty")->getline());
+	print "\n";
+	system("stty $stty");
+	return $keys[0] if $keys[0] eq $keys[1];
+	print "keys mismatch, again\n";
+    }
+}
+
+sub init_ca() {
+    # initialize the CA directory structure. This should
+    # correspond to the values found in templates/ca
+    die "$CA_DIR already exists" if -d $CA_DIR and not $opt_force;
+    mkpath(map { "$CA_DIR/$_" } qw(newcerts));
+    mkpath(map { dirname $_ } $CA_CRT, $CA_KEY);
+    (new IO::File ">$CA_DIR/index");
+    (new IO::File ">$CA_DIR/serial")-> print("01\n");
+
+    # now 
+    my $tt2 = new Template or die $Template::ERROR;
+    $tt2->process($TEMPLATE{req},
+    {
+	# not used yet
+    } => "$TMP/cnf") or die $tt2->error;
+
+    $ENV{CA_PASS} = ask_pass("passphrase for CA key: ");
+    system("openssl req -config $TMP/cnf -x509 -days 3650 -new -passout env:CA_PASS -keyout $TMP/ca-key.pem -out $TMP/ca-crt.pem")
+    and exit;
+
+    system("openssl x509 -in $TMP/ca-crt.pem -out $CA_CRT") and exit;
+    $_ = umask(077);
+    system("openssl rsa -in $TMP/ca-key.pem -des3 -passin env:CA_PASS -passout env:CA_PASS -out $CA_KEY") and exit;
+    umask($_);
+
+
+}
+
+__END__
+
+=head1 NAME
+
+    ca - the ultimative CA tool
+
+=head1 SYNOPSIS
+
+    ca [--force] --init
+    ca --type=TYPE --days=DAYS [request.pem]
+
+    (not yet: request c=COUNTRY ST=STATE l=LOCATION o=ORGANIZATION OU=ORG-UNIT cn=COMMON-NAME)
+
+=head1 DESCRIPTION
+
+This B<ca> tool signs the request file. If no file is given, it
+expects the request on STDIN
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-d>|B<--days> I<days>
+
+The number of days the certificate should be valid. (default: 365)
+
+=item B<-h>|B<--help>
+
+Print the reference help and exit. (default: off)
+
+=item B<-i>|B<--init>
+
+Initialize the CA (keys, directories). This may be enforce with
+B<--force>. (default: off)
+
+=item B<-m>|B<--man>
+
+Open the reference manual and exit. (default: off)
+
+=item B<-o>|B<--out> I<outfile>
+
+The name of the output file. If not set (the default), the output goes
+to I<stdout> if the CSR came from stdin and it goes to a file named
+similar to the CSR, if the request came from a file.
+
+=item B<-t>|B<--type> I<type>
+
+The (NSCertType) type of the certificate. Should be client or server.
+(default: none)
+
+=back
+
+=cut
+## Please see file perltidy.ERR
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/ca	Tue Jan 26 23:26:08 2010 +0100
@@ -0,0 +1,128 @@
+#
+# 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
+
+
+####################################################################
+[ ca ]
+default_ca	= CA_default		# The default ca section
+
+####################################################################
+[ CA_default ]
+
+[% IF not cadir %]
+[% THROW param "missing ca dir" %]
+[% END %]
+
+dir		= [% cadir %]
+certs		= $dir/certs		# Where the issued certs are kept
+crl_dir		= $dir/crl		# Where the issued crl are kept
+database	= $dir/index	# 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.
+
+[% IF not cacrt %]
+[% THROW param "missing ca crt" %]
+[% END %]
+
+certificate	= [% cacrt %]           # 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
+
+[% IF not cakey %]
+[% THROW param "missing ca key" %]
+[% END %]
+
+private_key	= [% cakey %]           # The private key
+
+RANDFILE	= $dir/.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 %]
+default_days	= [% days %]		# how long to certify for
+default_crl_days= 30			# how long before next CRL
+default_md	= sha1			# which md to use.
+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 :-)
+[% DEFAULT policy = de %]
+policy		= [% policy %]
+
+# For the CA policy
+[ policy_de ]
+countryName		= match
+stateOrProvinceName	= supplied
+organizationName	= supplied
+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
+
+####################################################################
+
+[ 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.
+
+[% IF type %]
+# This is OK for an SSL server.
+nsCertType			= [% type %]
+[% END %]
+
+# 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
+
+nsCaRevocationUrl		= https://ssl.schlittermann.de/ca/ca-crl.pem
+nsRevocationUrl			= https://ssl.schlittermann.de/ca/crt-crl.pem
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/openssl.cnf	Tue Jan 26 23:26:08 2010 +0100
@@ -0,0 +1,313 @@
+#
+# 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' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca	= CA_default		# The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir		= ./demoCA		# 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/cacert.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/cakey.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	= sha1			# which md to use.
+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_match
+
+# 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.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName			= Country Name (2 letter code)
+countryName_default		= AU
+countryName_min			= 2
+countryName_max			= 2
+
+stateOrProvinceName		= State or Province Name (full name)
+stateOrProvinceName_default	= Some-State
+
+localityName			= Locality Name (eg, city)
+
+0.organizationName		= Organization Name (eg, company)
+0.organizationName_default	= Internet Widgits Pty Ltd
+
+# 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	=
+
+commonName			= Common Name (eg, 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
+
+[ 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:always
+
+# 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,issuer: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:always
+
+# 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/req	Tue Jan 26 23:26:08 2010 +0100
@@ -0,0 +1,102 @@
+# 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
+
+[ 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.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# 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)
+
+organizationalUnitName		= Organizational Unit Name (eg, section)
+
+commonName			= Common Name (eg, 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
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+# 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
+