#!/bin/sh
# Author: Alex Efros <powerman-asdf@yandex.ru>, 2002,2013
# License: Public Domain
#
# Certificate: Helper script to generate SSL certificates using openssl.

VERSION="2.01"

case x$1 in
    x|x-h|x--help)
	cat <<EOHELP
Generate SSL Certificate.

    -h or --help	this help
    -e or --examples	openssl usage examples
    ca			generate CA named "ca" with 2048-bit RSA key
    filename		generate 2048-bit RSA private key in filename.key,
			    certificate request in filename.csr,
			    self-signed certificate in filename.crt
    filename ca		generate 2048-bit RSA private key in filename.key,
			    certificate request in filename.csr,
			    CA "ca" signed certificate in filename.crt
    
    .csr file needed only if you will send it to other CA like VeriSign.
    If some software (like qpopper) need .key + self-signed .crt in single
    file you can simply run ``cat filename.key filename.crt > filename.pem''
    If you need encrypted .key see --examples.
EOHELP
	;;
    x-e|x--examples)
	cat <<EOEXAMPLES
## Generating RSA private key for CA or SERVER (2048 bit)
openssl genrsa -out ca_or_server.key 2048

## Generating X.509 certificate for CA or SERVER signed by itself without .csr
openssl req -new -x509 -key ca_or_server.key -out ca_or_server.crt
    
## Generating X.509 certificate signing request for CA or SERVER
openssl req -new -key ca_or_server.key -out ca_or_server.csr

## Generating X.509 certificate for CA or SERVER signed by itself
openssl x509 -days 365 \\
    -in ca_or_server.csr -req -out ca_or_server.crt \\
    -signkey ca_or_server.key

## Generating X.509 certificate signed by own CA
if [ ! -e ca.serial ] ; then  echo '01' >ca.serial ; fi
openssl x509 -days 365 \\
    -in server.csr -req -out server.crt \\
    -CAserial ca.serial -CA ca.crt -CAkey ca.key

## Enrypting RSA private key of CA or SERVER with a pass phrase for security
( umask 077
  openssl rsa -des3 -in ca_or_server.key -out ca_or_server.key.crypt
  mv -f ca_or_server.key.crypt ca_or_server.key )

## VIEW: Server X.509 Certificate
openssl x509 -noout -text -in server.crt

## VIEW: Server RSA Private Key
openssl rsa -noout -text -in server.key

## VIEW: Server Certificate Request
openssl req -noout -text -in server.csr

## VERIFY: Self-signed CA or SERVER Certificate
openssl verify ca_or_server.crt

## VERIFY: CA-signed SERVER Certificate
openssl verify -CAfile ca.crt server.crt

## RESULT: CA and Server Certification Files
## 
## [ca.key]
## The PEM-encoded RSA private key file of the CA which you can
## use to sign other servers or clients. KEEP THIS FILE PRIVATE!
## 
## [ca.crt]
## The PEM-encoded X.509 certificate file of the CA which you use to
## sign other servers or clients. When you sign clients with it (for
## SSL client authentication) you can configure this file with the
## 'SSLCACertificateFile' directive.
## 
## [server.key]
## The PEM-encoded RSA private key file of the server which you configure
## with the 'SSLCertificateKeyFile' directive. KEEP THIS FILE PRIVATE!
## 
## [server.crt]
## The PEM-encoded X.509 certificate file of the server which you configure
## with the 'SSLCertificateFile' directive.
## 
## [server.csr]
## The PEM-encoded X.509 certificate signing request of the server file which
## you can send to an official Certificate Authority (CA) in order
## to request a real server certificate (signed by this CA instead
## of our own CA) which later can replace the [server.crt] file.
EOEXAMPLES
	;;
    *)
	# check parameters
	cert=$1
	sign=$2
	days=2000
	if [ -e ${cert}.key -o -e ${cert}.csr -o -e ${cert}.crt ] ; then
	    echo ERROR: ${cert}.{key,csr,crt} already exists.
	    exit 1
	fi
	if [ $sign ]; then
	    if [ ! -e ${sign}.key -o ! -e ${sign}.crt ]; then
		echo ERROR: ${sign}.{key,crt} is not exists.
		exit 1
	    fi
	fi
	# generate optional template
	if [ $cert = "ca" ] ; then
	    unitname="Certificate Authority"
	    commonname=`hostname`" CA"
	else
	    unitname="Web server"
	    commonname=`hostname`
	fi
	email="root@"`hostname`
	cat >.Certificate.tmp <<EOT
[ req ]
default_bits                    = 2048
distinguished_name              = req_DN
[ req_DN ]
countryName                     = "1. Country Name             (2 letter code)"
countryName_default             = XY
countryName_min                 = 2
countryName_max                 = 2
stateOrProvinceName             = "2. State or Province Name   (full name)    "
stateOrProvinceName_default     = Snake Desert
localityName                    = "3. Locality Name            (eg, city)     "
localityName_default            = Snake Town
0.organizationName              = "4. Organization Name        (eg, company)  "
0.organizationName_default      = Snake Oil, Ltd
organizationalUnitName          = "5. Organizational Unit Name (eg, section)  "
organizationalUnitName_default  = ${unitname}
commonName                      = "6. Common Name              (eg, CA name)  "
commonName_max                  = 64
commonName_default              = ${commonname}
emailAddress                    = "7. Email Address            (eg, name@FQDN)"
emailAddress_max                = 40
emailAddress_default            = ${email}
EOT
	# generate PRIVATE KEY
	umask 077
	openssl genrsa -out ${cert}.key 2048
	# generate CERTIFICATE REQUEST
	openssl req -config .Certificate.tmp -new \
	    -key ${cert}.key -out ${cert}.csr
	rm -f .Certificate.tmp
	# generate CERTIFICATE (i.e. sign CERTIFICATE REQUEST)
	if [ $sign ] ; then
	    if [ ! -e ${sign}.serial ] ; then
		echo '01' >${sign}.serial
	    fi
	    openssl x509 -days $days \
		-in ${cert}.csr -req -out ${cert}.crt \
		-CAserial ${sign}.serial -CA ${sign}.crt -CAkey ${sign}.key
	else
	    openssl x509 -days $days \
		-in ${cert}.csr -req -out ${cert}.crt \
		-signkey ${cert}.key
	fi
	;;
esac

