3 # Generate a root CA cert for signing, and then a subject cert.
4 # Usage: make-certs.sh hostname [user[@domain]] [more ...]
5 # For testing only, probably still has some bugs in it.
18 # Cleanup temporary files at exit.
20 newcertdir
=`mktemp -d`
22 test -f openssl.cnf
&& rm -f openssl.cnf
23 test -f ca.txt
&& rm -f ca.txt
24 test -f ocsp.txt
&& rm -f ocsp.txt
25 test -n "$newcertdir" && rm -fr "$newcertdir"
29 # The first argument is either a common name value or a flag indicating that
30 # we're doing something other than issuing a cert.
35 if test "x$commonname" = "x-refresh-crl" ; then
39 if test "x$commonname" = "x-refresh_crl" ; then
43 if test "x$commonname" = "x-revoke" ; then
48 if test "x$commonname" = "x-ocsp" ; then
52 if test "x$commonname" = x
; then
53 echo Usage
: `basename $0` 'commonname' user
'[@domain]' '[more [...]]'
54 echo Usage
: `basename $0` -revoke 'commonname'
55 echo Usage
: `basename $0` -ocsp
56 echo Usage
: `basename $0` -refresh-crl
58 echo -e \\tKey usage
: "[sign|signing|encrypt|encryption|all]"
59 echo -e \\tAuthority Access Info OCSP responder
: "ocsp:URI"
60 echo -e \\tCRL distribution point
: "crl:URI"
61 echo -e \\tSubject Alternative Name
:
62 echo -e \\t
\\tHostname
: "*"
63 echo -e \\t
\\tIP address
: w.x.y.z
64 echo -e \\t
\\tEmail address
: "*@*.com/edu/net/org/local"
65 echo -e \\t
\\tKerberos principal name
: "*@*.COM/EDU/NET/ORG/LOCAL"
66 echo -e \\tExtended key usage
:
69 echo -e \\t
\\tid-kp-server-auth \| tls-server
70 echo -e \\t
\\tid-kp-client-auth \| tls-client
71 echo -e \\t
\\tid-kp-email-protection \| email
72 echo -e \\t
\\tid-ms-kp-sc-logon \| id-ms-sc-logon
73 echo -e \\t
\\tid-pkinit-kp-client-auth \| id-pkinit-client
74 echo -e \\t
\\tid-pkinit-kp-kdc \| id-pkinit-kdc
75 echo -e \\t
\\tca \| CA
79 # Choose a user name part for email attributes.
81 test x
"$GIVENUSER" = x
&& GIVENUSER
=$USER
82 echo "$GIVENUSER" |
grep -q @ || GIVENUSER
="$GIVENUSER"@
$DOMAIN
83 DOMAIN
=`echo "$GIVENUSER" | cut -f2- -d@`
94 openssl dsaparam
-out "$1".param
$KEYSIZE
95 openssl gendsa
"$1".param
98 #openssl genrsa $KEYSIZE -passout pass:qweqwe
99 openssl genrsa
$KEYSIZE
100 #openssl genrsa $KEYSIZE -nodes
107 if test -s ca.crldp.uri.txt
; then
108 crlval
="`cat ca.crldp.uri.txt`"
111 if test -s ca.ocsp.uri.txt
; then
112 aiaval
="`cat ca.ocsp.uri.txt`"
113 aia
="OCSP;URI:$aiaval"
115 if test -s ca.domain.txt
; then
116 domval
="`cat ca.domain.txt`"
117 if test -n "$domval" ; then
122 # Parse the arguments which indicate what sort of information we want.
123 while test $# -gt 0 ; do
134 aiaval
=`echo "$value" | cut -f2- -d:`
135 aia
="OCSP;URI:$aiaval"
138 crlval
=`echo "$value" | cut -f2- -d:`
142 keyusage
="${keyusage:+${keyusage},}nonRepudiation,digitalSignature"
145 keyusage
="${keyusage:+${keyusage},}keyEncipherment,dataEncipherment"
148 keyusage
="digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign,encipherOnly,decipherOnly"
152 keyusage
="${keyusage:+${keyusage},}nonRepudiation,digitalSignature,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign"
154 1.
*|
2.
*|id-
*|tls-
*|email|
mail|codesign
)
155 ekuval
=`echo "$value" | tr '[A-Z]' '[a-z]' | sed 's,\-,,g'`
157 idkpserverauth|tlsserver
) ekuval
=1.3.6.1.5.5.7.3.1;;
158 idkpclientauth|tlsclient
) ekuval
=1.3.6.1.5.5.7.3.2;;
159 idkpemailprotection|email|
mail) ekuval
=1.3.6.1.5.5.7.3.4;;
160 idkpcodesign|codesign
) ekuval
=1.3.6.1.5.5.7.3.3;;
161 idmskpsclogon|idmssclogon
) ekuval
=1.3.6.1.4.1.311.20.2.2;;
162 idpkinitkpclientauth|idpkinitclient
) ekuval
=1.3.6.1.5.2.3.4;;
163 idpkinitkpkdc|idpkinitkdc
) ekuval
=1.3.6.1.5.2.3.5;;
165 if test -z "$eku" ; then
171 *@
*.COM|
*@
*.EDU|
*@
*.NET|
*@
*.ORG|
*@
*.LOCAL
)
172 luser
=`echo "$value" | tr '[A-Z]' '[a-z]'`
173 if test "$luser" = "$value" ; then
176 type="otherName:1.3.6.1.5.2.2;SEQUENCE:$value,${luser:+otherName:1.3.6.1.4.1.311.20.2.3;UTF8:${luser},}otherName:1.3.6.1.4.1.311.20.2.3;UTF8"
178 principals
="$principals $value"
180 *@
*.com|
*@
*.edu|
*@
*.net|
*@
*.org|
*@
*.
local) type=email
;;
181 [0-9]*.
[0-9]*.
[0-9]*.
[0-9]*) type=IP
;;
184 if test -n "$type" ; then
185 newvalue
="${type}:$value"
186 if test -z "$altnames" ; then
187 altnames
="${newvalue}"
189 altnames
="${altnames},${newvalue}"
195 # Build the configuration file, including bits on how to construct the CA
196 # certificate, an OCSP responder certificate, and the issued certificate.
197 cat > openssl.cnf
<<- EOF
202 private_key = `pwd`/ca.key
203 certificate = `pwd`/ca.crt
204 database = `pwd`/ca.db
205 serial = `pwd`/ca.srl
207 new_certs_dir = $newcertdir
213 domainComponent = 0.9.2342.19200300.100.1.25
217 oid_section = req_oids
218 distinguished_name = req_ca_name
220 subjectKeyIdentifier=hash
224 #stateOrProvinceName=SomeState
225 localityName=SomeCity
228 #echo $DOMAIN | awk 'BEGIN {FS="."}{for(i=NF;i>0;i--){print NF-i ".domainComponent="$i;}}' >> openssl.cnf
229 cat >> openssl.cnf
<<- EOF
230 #commonName = Test Certifying CA
233 subjectKeyIdentifier=hash
234 authorityKeyIdentifier=keyid:always
235 #authorityKeyIdentifier=keyid:always,issuer:always
236 keyUsage=nonRepudiation,digitalSignature,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign
237 basicConstraints=critical,CA:TRUE
238 nsComment="Testing CA Certificate"
240 if test -n "$aia" ; then
241 echo "authorityInfoAccess = ${aia}" >> openssl.cnf
242 echo -n "$aiaval" > ca.ocsp.uri.txt
244 if test -n "$crl" ; then
245 echo "crlDistributionPoints = ${crl}" >> openssl.cnf
246 echo -n "$crlval" > ca.crldp.uri.txt
248 echo "$DOMAIN" > ca.domain.txt
249 cat >> openssl.cnf
<<- EOF
253 oid_section = req_oids
254 distinguished_name = req_ocsp_name
259 #stateOrProvinceName=SomeState
263 #echo $DOMAIN | awk 'BEGIN {FS="."}{for(i=NF;i>0;i--){print NF-i ".domainComponent="$i;}}' >> openssl.cnf
264 cat >> openssl.cnf
<<- EOF
265 #commonName = OCSP Signer for Test Certifying CA
268 subjectKeyIdentifier=hash
269 #authorityKeyIdentifier=keyid:always,issuer:always
270 authorityKeyIdentifier=keyid:always
271 keyUsage=digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign
272 extendedKeyUsage=1.3.6.1.5.5.7.3.9
273 #basicConstraints=CA:FALSE
274 basicConstraints=CA:TRUE
275 nsComment="Testing OCSP Certificate"
276 1.3.6.1.5.5.7.48.1.5=ASN1:NULL
278 if test -n "$aia" ; then
279 echo "authorityInfoAccess = ${aia}" >> openssl.cnf
281 if test -n "$crl" ; then
282 echo "crlDistributionPoints = ${crl}" >> openssl.cnf
284 cat >> openssl.cnf
<<- EOF
288 oid_section = req_oids
289 distinguished_name = req_issued_name
294 #stateOrProvinceName=SomeState
295 localityName=SomeCity
298 #echo $DOMAIN | awk 'BEGIN {FS="."}{for(i=NF;i>0;i--){print NF-i ".domainComponent="$i;}}' >> openssl.cnf
300 cat >> openssl.cnf
<<- EOF
301 commonName = $commonname
304 #certificatePolicies=2.5.29.32.0${eku:+,${eku}}
305 subjectKeyIdentifier=hash
306 authorityKeyIdentifier=keyid:always
307 #authorityKeyIdentifier=keyid:always,issuer:always
309 if test -n "$aia" ; then
310 echo "authorityInfoAccess = ${aia}" >> openssl.cnf
312 if test -n "$crl" ; then
313 echo "crlDistributionPoints = ${crl}" >> openssl.cnf
315 if test -n "$keyusage" ; then
316 echo "keyUsage = critical,${keyusage}" >> openssl.cnf
318 if test -n "$altnames" ; then
319 echo "subjectAltName = ${altnames}" >> openssl.cnf
321 if test -n "$eku" ; then
322 echo "extendedKeyUsage = ${eku}" >> openssl.cnf
325 if test "x$CA" = xTRUE
; then
326 echo "basicConstraints=critical,CA:TRUE" >> openssl.cnf
327 echo 'nsComment="Testing CA Certificate for '"$commonname"'"' >> openssl.cnf
329 echo "basicConstraints=CA:FALSE" >> openssl.cnf
330 echo 'nsComment="Testing Certificate for '"$commonname"'"' >> openssl.cnf
332 for value
in $principals; do
333 user
=`echo "$value" | cut -f1 -d@`
334 realm
=`echo "$value" | cut -f2- -d@`
335 echo "" >> openssl.cnf
336 echo "[$value]" >> openssl.cnf
337 echo "realm=EXPLICIT:0,GeneralString:$realm" >> openssl.cnf
338 echo "kerberosname=EXPLICIT:1,SEQUENCE:krb5$user" >> openssl.cnf
340 echo "" >> openssl.cnf
341 echo "[krb5$user]" >> openssl.cnf
342 echo "nametype=EXPLICIT:0,INTEGER:1" >> openssl.cnf
343 echo "namelist=EXPLICIT:1,SEQUENCE:krb5basic$user" >> openssl.cnf
345 echo "[krb5basic$user]" >> openssl.cnf
347 for part
in `echo "$user" | sed 's,/, ,g'` ; do
348 echo "$count.part=GeneralString:$part" >> openssl.cnf
349 count
=`expr "$count" + 1`
353 # Create the data files for a new CA.
354 if ! test -s ca.srl
; then
355 (dd if=/dev
/urandom bs
=8 count
=1 2> /dev
/null
) |
od -t x1c |
head -n 1 |
awk '{$1="00";OFS="";print}' > ca.srl
357 echo "You already have a ca.srl file; not replacing."
359 if ! test -s ca.db
; then
362 echo "You already have a ca.db file; not replacing."
364 if ! test -s ca.db.attr
; then
367 echo "You already have a ca.db.attr file; not replacing."
370 # If we need a CA key, generate one.
371 if ! test -s ca.key
; then
374 keygen ca
> ca.key
2> /dev
/null
377 echo "You already have a ca.key file; not replacing."
381 # If we need a CA certificate, generate one.
382 if ! test -s ca.crt
; then
383 sed -i -e 's,^\[req_ca\]$,\[req\],g' `pwd`/openssl.cnf
384 openssl req
-config `pwd`/openssl.cnf
-new -key ca.key
> ca.csr
2> /dev
/null
-passin pass
:shim
385 sed -i -e 's,^\[req\]$,\[req_ca\],g' `pwd`/openssl.cnf
386 openssl x509
-extfile `pwd`/openssl.cnf
-CAserial ca.srl
-signkey ca.key
-extensions v3_ca
-req -in ca.csr
-days $DAYS -out ca.crt
; : 2> /dev
/null
387 openssl x509
-noout -text -in ca.crt
> ca.txt
391 cat ca.crt
> ca.chain.crt
393 echo "You already have a ca.crt file; not replacing."
397 # If we need an OCSP key, generate one.
398 if ! test -s ocsp.key
; then
401 keygen ocsp
> ocsp.key
2> /dev
/null
404 echo "You already have an ocsp.key file; not replacing."
408 # Generate the OCSP signing cert. Set the X.509v3 basic constraints and EKU.
409 if ! test -s ocsp.crt
; then
410 sed -i -e 's,^\[req_ocsp\]$,\[req\],g' `pwd`/openssl.cnf
411 openssl req
-config `pwd`/openssl.cnf
-new -key ocsp.key
> ocsp.csr
2> /dev
/null
412 sed -i -e 's,^\[req\]$,\[req_ocsp\],g' `pwd`/openssl.cnf
413 openssl ca
-batch -config `pwd`/openssl.cnf
-extensions v3_ocsp
-preserveDN -in ocsp.csr
-days $DAYS -out ocsp.crt
2> /dev
/null
414 openssl x509
-noout -text -in ocsp.crt
> ocsp.txt
415 cat ocsp.crt
>> ocsp.txt
416 cat ocsp.txt
> ocsp.crt
419 echo "You already have an ocsp.crt file; not replacing."
423 # If we were told to revoke the certificate with the specified common name,
425 if $revoke_cert ; then
426 openssl ca
-config `pwd`/openssl.cnf
-revoke "$commonname".crt
429 # Always refresh the CRL.
430 openssl ca
-config `pwd`/openssl.cnf
-gencrl ${CRLHOURS:+-crlhours ${CRLHOURS}} ${CRLDAYS:+-crldays ${CRLDAYS}} -out ca.crl.pem
431 openssl crl
-in ca.crl.pem
-outform der
-out ca.crl
432 openssl crl
-in ca.crl
-inform der
-noout -text > ca.crl.pem
433 openssl crl
-in ca.crl
-inform der
>> ca.crl.pem
435 # If we were told to start up the mini OCSP server, do so.
436 if $ocsp_serve ; then
437 openssl ocsp
-text -index `pwd`/ca.db
-CA `pwd`/ca.crt
-rsigner `pwd`/ocsp.crt
-rkey `pwd`/ocsp.key
-rother `pwd`/ocsp.crt
-port "`cut -f3 -d/ ca.ocsp.uri.txt | sed -r 's,(^[^:]*),0.0.0.0,g'`"
441 # If we're just here to do a revocation or refresh the CRL, we're done.
442 if $revoke_cert ||
$refresh_crl ; then
446 # Create a new serial number and whatnot if this is a new sub-CA.
447 if test "x$CA" = xTRUE
; then
448 if ! test -d "$commonname" ; then
451 if ! test -s "$commonname/ca.srl" ; then
452 (dd if=/dev
/urandom bs
=8 count
=1 2> /dev
/null
) |
od -t x1c |
head -n 1 |
awk '{$1="00";OFS="";print}' > "$commonname/ca.srl"
454 echo "You already have a $commonname/ca.srl file; not replacing."
456 if test -n "$aia" ; then
457 echo -n "$aiaval" > "$commonname/ca.ocsp.uri.txt"
459 if test -n "$crl" ; then
460 echo -n "$crlval" > "$commonname/ca.crldp.uri.txt"
462 echo "$DOMAIN" > "$commonname/ca.domain.txt"
463 touch "$commonname/ca.db" "$commonname/ca.db.attr"
464 cert
="$commonname/ca.crt"
465 csr
="$commonname/ca.csr"
466 key
="$commonname/ca.key"
467 pem
="$commonname/ca.pem"
468 pfx
="$commonname/ca.p12"
469 ln -s ..
/`basename $0` "$commonname"/
471 cert
="$commonname.crt"
472 csr
="$commonname.csr"
473 key
="$commonname.key"
474 pem
="$commonname.pem"
475 pfx
="$commonname.p12"
478 # Generate the subject's certificate. Set the X.509v3 basic constraints.
479 if ! test -s "$cert" ; then
480 # Generate another key, unless we have a key or CSR.
481 if ! test -s "$key" && ! test -s "$csr" ; then
484 keygen
"$commonname" > "$key" 2> /dev
/null
487 echo "You already have a $key or $csr file; not replacing."
491 if ! test -s "$csr" ; then
492 sed -i -e 's,^\[req_issued\]$,\[req\],g' `pwd`/openssl.cnf
493 openssl req
-config `pwd`/openssl.cnf
-new -key "$key" > "$csr" 2> /dev
/null
494 sed -i -e 's,^\[req\]$,\[req_issued\],g' `pwd`/openssl.cnf
496 openssl ca
-batch -config `pwd`/openssl.cnf
-extensions v3_issued
-preserveDN -in "$csr" -days $DAYS -out "$cert" 2> /dev
/null
497 openssl x509
-noout -text -in "$cert" > "$cert.txt"
498 cat "$cert" >> "$cert.txt"
499 cat "$cert.txt" > "$cert"
502 echo "You already have a $cert file; not replacing."
506 if test -s ca.chain.crt
; then
511 if test "x$CA" = xTRUE
; then
512 cat "$chain" "$cert" > "$commonname/ca.chain.crt"
515 # Create ca.pem and the subject's name.pem for the benefit of applications
516 # which expect both the private key and the certificate in one file.
519 if ! test -s ca.pem
; then
520 cat ca.key ca.crt
> ca.pem
522 echo "You already have a ca.pem file; not replacing."
525 if ! test -s "$pem" ; then
526 cat "$key" "$cert" > "$pem"
528 echo "You already have a $pem file; not replacing."
531 if ! test -s "$pfx" ; then
532 #openssl pkcs12 -export -inkey "$key" -in "$cert" -name "$commonname" -out "$pfx" -nodes -passout pass:qweqwe
533 openssl pkcs12
-export -inkey "$key" -in "$cert" -name "$commonname" -out "$pfx" -nodes -passout pass
:
535 echo "You already have a $pfx file; not replacing."
542 openssl x509
-noout -issuer -in ca.crt |
sed s
,=\
,\
,g
543 openssl x509
-noout -subject -in ca.crt |
sed s
,=\
,\
,g
545 echo End entity certificate
:
546 openssl x509
-noout -issuer -in "$cert" |
sed s
,=\
,\
,g
547 openssl x509
-noout -subject -in "$cert" |
sed s
,=\
,\
,g
548 openssl x509
-noout -serial -in "$cert" |
sed s
,=,\
,g
551 openssl pkcs12
-in "$pfx" -nodes -nokeys -nocerts -info -passin pass
:
552 #openssl pkcs12 -in "$pfx" -nodes -nokeys -nocerts -info -passin pass:qweqwe
555 echo + openssl verify
-CAfile "$chain" "$cert"
556 openssl verify
-CAfile "$chain" "$cert"