#!/bin/bash
SSLDIR="$HOME/pki"
export PASS="wirbelwind"
export CAPASS="imbtbacb"
export COU="de"
export STA="rlp"
export CIT="zw"
export COM="xinux"
export UNI="it"
export MAI="technik@xinux.de"
export CAN="xin-ca"
export CRLWEB="URI:http://www.xinux.de/ca/$CAN.crl"


 
function openssl-cf()
{
cat <<HERE 
HOME                    = .
RANDFILE                = $SSLDIR/.rnd
/oid_section             = new_oids
[ new_oids ]
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            
[ CA_default ]
dir             = ./                     
certs           = \$dir/certs            
crl_dir         = \$dir/crl              
database        = \$dir/index.txt        
new_certs_dir   = \$dir/newcerts         
certificate     = \$dir/$CAN.crt           
serial          = \$dir/serial           
crlnumber       = \$dir/crlnumber         
crl             = \$dir/$CAN.crl      
private_key     = \$dir/$CAN.key            
#RANDFILE        = $SSLDIR/.rand    
x509_extensions = usr_cert              
copy_extensions	= copy  # add by xinux 
name_opt        = ca_default           
cert_opt        = ca_default           
default_days    = 3650  # change by xinux               
default_crl_days= 30                  
default_md      = default            
preserve        = no                
policy          = policy_match
[ policy_match ]
countryName             = match
stateOrProvinceName     = optional
localityName            = optional
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional
[ policy_anything ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional
[ req ]
default_bits            = 2048
default_keyfile         = privkey.pem
distinguished_name      = req_distinguished_name
attributes              = req_attributes
x509_extensions = v3_ca 
string_mask = utf8only
[ req_distinguished_name ]
countryName                     = Country Name (2 letter code)
countryName_default             = $COUNTRY
countryName_min                 = 2
countryName_max                 = 2
stateOrProvinceName             = State or Province Name (full name)
stateOrProvinceName_default     = $PROVINCE
localityName                    = Locality Name (eg, city)
localityName_default            = $CITY
0.organizationName              = Organization Name (eg, company)
0.organizationName_default      = $ORGANIZATION
organizationalUnitName          = Organizational Unit Name (eg, section)
organizationalUnitName_default  = $UNIT
commonName                      = Common Name (eg, YOUR name)
commonName_max                  = 64
commonName_default              = $COMMONNAME
#emailAddress                    = Email Address
#emailAddress_max                = 64
#emailAddress_default            = $MAILADDRESS
[ req_attributes ]
[ usr_cert ]
basicConstraints=CA:FALSE
nsComment                       = "OpenSSL Generated Certificate"
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
[ v3_ca ] # change by xinux
basicConstraints = CA:true
basicConstraints       = critical, CA:TRUE
keyUsage               = cRLSign, keyCertSign
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid, issuer:always
subjectAltName         = email:copy
issuerAltName          = issuer:copy
crlDistributionPoints  = $CRLWEB 
[ crl_ext ]
authorityKeyIdentifier=keyid:always
[ proxy_cert_ext ]
basicConstraints=CA:FALSE
nsComment                       = "OpenSSL Generated Certificate"
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
[ tsa ]
default_tsa = tsa_config1       
[ tsa_config1 ]
dir             = ./demoCA          
serial          = $dir/tsaserial     
crypto_device   = builtin             
signer_cert     = $dir/tsacert.pem     
certs           = $dir/cacert.pem      
signer_key      = $dir/private/tsakey.pem 
default_policy  = tsa_policy1          
other_policies  = tsa_policy2, tsa_policy3     
digests         = md5, sha256           
accuracy        = secs:1, millisecs:500, microsecs:100 
clock_precision_digits  = 0     
ordering                = yes   
tsa_name                = yes  
ess_cert_id_chain       = no    
HERE
}

function ask()
{
echo -ne "Country Name (2 letter code) [$COU]: "
read COUNTRY
test -z $COUNTRY && COUNTRY="$COU"
echo -ne "State or Province Name (full name) [$STA]: "
read PROVINCE
test -z $PROVINCE && PROVINCE="$STA"
echo -ne "Locality Name (eg, city) [$CIT]: "
read CITY
test -z $CITY && CITY="$CIT"
echo -ne "Organization Name (eg, company) [xinux] "
read ORGANIZATION
test -z $ORGANIZATION && ORGANIZATION="xinux"
echo -ne "Organizational Unit Name (eg, section) [$UNI]: "
read UNIT
test -z $UNIT && UNIT="$UNI"
case $1 in
ca)
echo -ne "Common Name (CA name) [$CON] : "
read COMMONNAME
test -z $COMMONNAME && COMMONNAME="$CON" 
;;
cert)
echo -ne "Common Name (e.g. server FQDN or YOUR name) [this is requiured] : "
read COMMONNAME
test -z $COMMONNAME && { echo COMMONNAME is required ; exit 1 ; }  
;;
esac
#echo -ne "Email Address [$MAI]: "
#read MAILADDRESS
#test -z $MAILADDRESS && MAILADDRESS="$MAI"
}



function ca()
{
CON=$CAN
ask ca
export COUNTRY PROVINCE CITY COMMONNAME UNIT MAILADDRESS
if [ -d $SSLDIR ]; then
 echo "CA exist!"
 exit 1
else
 echo mkdir -p $SSLDIR/newcerts
 mkdir -p $SSLDIR/newcerts
 test -f $SSLDIR/.rnd || openssl rand -writerand  $SSLDIR/.rnd 
 test -f $SSLDIR/.rand || openssl rand -writerand $SSLDIR/.rand
 cd $SSLDIR
 touch index.txt
 echo 01 > serial
 echo 01 > crlnumber
fi
openssl-cf > openssl.cnf
openssl genrsa -passout env:CAPASS -des3 -out $CAN.key 2048
openssl req -passin env:CAPASS -new -batch -config openssl.cnf -key $CAN.key -x509 -sha1 -days 3650 -out $CAN.crt
echo -e "\nCA created!\n"
}

function cert()
{
test "$1" = "server" && { shift ; EXT="server"; }
test "$1" = "client" && { shift ; EXT="client"; }
if test -d $SSLDIR 
then 
cd $SSLDIR
else
echo "$SSLDIR not found" 
exit 1 
fi 
if test "$#" -eq 1
then
 if test "$(echo $1 | cut  -c 1)" = "*"
  then 
   CNF=star"$(echo $1 | cut  -c 2-)"
   CN=$1
  else
   CN=$1
   CNF=$1
  fi
test -f $CNF.key && { echo "$CNF exists" ; exit 1; } 
sed -e "s/commonName_default.\+/commonName_default\t\t= $CN/" openssl.cnf > $CNF.cnf
else
unset CNF
ask cert
test -f $CNF.key && { echo "$CNF exists" ; exit 1; } 
openssl-cf > $CNF.cnf
fi
openssl genrsa -out $CNF.key 2048
case $EXT in
server)
cat<<HERE >> $CNF.cnf
[ server-ext ]
extendedKeyUsage = serverAuth, 1.3.6.1.5.5.8.2.2
subjectAltName = DNS:$CN
HERE
openssl req -new   -sha256   -batch -config $CNF.cnf -key $CNF.key  -out $CNF.csr -reqexts server-ext 
;;
client)
cat<<HERE >> $CNF.cnf
[ client-ext ]
extendedKeyUsage = clientAuth
HERE
openssl req  -new   -sha256     -batch -config $CNF.cnf -key $CNF.key  -out $CNF.csr -reqexts client-ext 
;;
*)
openssl req  -new  -sha256     -batch -config $CNF.cnf -key $CNF.key  -out $CNF.csr
;;
esac 
openssl ca  -passin env:CAPASS -config openssl.cnf -batch -cert $CAN.crt -days 3650 -md sha256 -keyfile $CAN.key   -in $CNF.csr  -out $CNF.crt
openssl ca -passin env:CAPASS -batch -gencrl -config openssl.cnf -out $CAN.crl
openssl  crl -in $CAN.crl -outform der -out crl-der.crl
openssl pkcs12  -passout env:PASS  -export -in $CNF.crt -inkey $CNF.key -certfile $CAN.crt -out $CNF.p12
echo -e "\ncert created\n"
tar -cvzf $CNF.tgz  $CNF.key $CNF.crt $CNF.p12 $CAN.crt $CAN.crl
}






function crl()
{
openssl ca -passin env:CAPASS -batch -gencrl -config openssl.cnf -out $CAN.crl
openssl  crl -in $CAN.crl -outform der -out crl-der.crl
}


function revoke()
{
cd $SSLDIR
COMMONNAME=$1
openssl ca -passin env:CAPASS -config openssl.cnf -revoke $COMMONNAME.crt
echo -e "\ncert $COMMONNAME revoke\n"
}


function dh()
{
cd $SSLDIR
openssl gendh 1024 > dh1024.pem:
echo -e "\ndh generated\n"
}

function list()
{
cd $SSLDIR
cat index.txt
}
function help()
{

cat<<HERE
"$0" 

ca "generate a CA"

cert "interactive"

cert server "interaktiv serverext"

cert client "interaktiv clientext"

cert <COMMONNAME> "automatic" 

cert server <COMMONNAME> "automatic serverext" 

cert client <COMMONNAME> "automatic clientext" 

revoke <COMMONNAME> "revoke a cert"

crl "generate a crl"

dh "generate diffie-hellmann" 

list "list certs"

show req  <COMMONNAME> "show request"

show cert <COMMONNAME> "show cert"

help "this help"

HERE

}

function show()
{
cd $SSLDIR
case $1 in
cert) 
test -f $2.crt ||  { echo "$2.crt not found"; exit 1;}
openssl x509 -noout -text -in $2.crt
;;
req)
test -f $2.csr || { echo "$2.csr not found"; exit 1 ;}
openssl req -noout -text -in $2.csr
;;
*)
echo "second arg must be req odr cert"
;;
esac 
}



echo -e "working directory: $SSLDIR\n"
test -d $SSLDIR || { echo "first create CA" ; DF=1 ; }

case $1 in 
ca) ca ;;
cert) cert $2 $3 ;;
revoke) revoke $2 ;;
dh) dh ;;
crl) crl ;;
show) show $2 $3 ;;
list) list ;;
help) help ;;
*) 
echo "$0 ca | cert [server|client] <COMMONNAME>  | crl | revoke <COMMONNAME> | dh | list | show <cert|req> COMMMON_NAME | help";; 
esac
