#!/bin/sh ## ## x509-util.sh -- X.509 Certificate Generation Utility ## Copyright (c) 2007-2014 Ralf S. Engelschall ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, ## USA, or contact Ralf S. Engelschall . ## # sane run-time environment umask 022 # parameter defaults prefix="@l_prefix@" tag="snakeoil" password="snakeoil" domain="snakeoil.invalid" organization="Snakeoil Corporation" lifetime="3650" num_server="2" num_client="4" num_object="4" tmpdir="${TMPDIR-/tmp}" outdir="`pwd`" # parse command line options while [ $# -gt 0 ]; do case "$1" in --prefix=* ) prefix=`echo "$1" | sed -e 's;^--[^=]*=;;'`; shift ;; --tag=* ) tag=`echo "$1" | sed -e 's;^--[^=]*=;;'`; shift ;; --password=* ) password=`echo "$1" | sed -e 's;^--[^=]*=;;'`; shift ;; --domain=* ) domain=`echo "$1" | sed -e 's;^--[^=]*=;;'`; shift ;; --organization=* ) organization=`echo "$1" | sed -e 's;^--[^=]*=;;'`; shift ;; --lifetime=* ) lifetime=`echo "$1" | sed -e 's;^--[^=]*=;;'`; shift ;; --num-server=* ) num_server=`echo "$1" | sed -e 's;^--[^=]*=;;'`; shift ;; --num-client=* ) num_client=`echo "$1" | sed -e 's;^--[^=]*=;;'`; shift ;; --num-object=* ) num_object=`echo "$1" | sed -e 's;^--[^=]*=;;'`; shift ;; --tmpdir=* ) tmpdir=`echo "$1" | sed -e 's;^--[^=]*=;;'`; shift ;; --outdir=* ) outdir=`echo "$1" | sed -e 's;^--[^=]*=;;'`; shift ;; --help ) echo "Usage: x509-util [--prefix=] [--tag=] [--password=]" echo " [--domain=] [--organization=] [--lifetime=]" echo " [--num-server=] [--num-client=] [--num-object=]" echo " [--tmpdir=] [--outdir=] [--help]" exit 0 ;; * ) break ;; esac done # display information about parameters echo "++ generating X.509 certificate/key set with configuration:" echo "-- OpenPKG prefix (--prefix): $prefix" echo "-- Short-hand tag (--tag): $tag" echo "-- Encryption Password (--password): $password" echo "-- DNS Domain (--domain): $domain" echo "-- Organization Name (--organization): $organization" echo "-- Certificate Lifetimes (--lifetime): $lifetime" echo "-- Number of Server Certificates (--num-server): $num_server" echo "-- Number of Client Certificates (--num-client): $num_client" echo "-- Number of Object Certificates (--num-object): $num_object" echo "-- Temporary Directory (--tmpdir): $tmpdir" echo "-- Output Directory (--outdir): $outdir" # sanity check environment if [ ! -x "$prefix/bin/shtool" ]; then echo "ERROR: $prefix/bin/shtool (OpenPKG \"shtool\" package) required" 1>&2 exit 1 fi if [ ! -x "$prefix/bin/csp" ]; then echo "ERROR: $prefix/bin/csp (OpenPKG \"csp\" package) required" 1>&2 exit 1 fi if [ ! -x "$prefix/bin/perl" ]; then echo "ERROR: $prefix/bin/perl (OpenPKG \"perl\" package) required" 1>&2 exit 1 fi # ensure out directory exists test -d $outdir || mkdir $outdir 2>/dev/null || true # create temporary location echo "++ creating temporary location" if [ ! -d $tmpdir ]; then echo "$0: ERROR: temporary directory not existing: $tmpdir" 1>&2 exit 1 fi tmpdir="$tmpdir/x509-util.$$.tmp" test -d $tmpdir && rm -rf $tmpdir >/dev/null 2>&1 || true mkdir $tmpdir || exit $? cd $tmpdir || exit $? # display processing information echo "++ creating CSP environment" # create CSP environment rm -rf etc csp ln -s $prefix/etc/csp etc mkdir csp $prefix/bin/csp $tag create # optionally adjust configuration $prefix/bin/shtool subst -q \ -e "s;example\\.com;$domain;g" \ csp/$tag/extensions.conf rm -f csp/$tag/extensions.conf.orig # display processing information echo "++ generate CA private key and certificate" # generate CA private key and certificate $prefix/bin/csp $tag init \ --keysize=4096 --keypass="$password" --type=ca --days=$lifetime \ "CN=Certificate Authority (CA), OU=Certification Department, O=$organization" idx=0 # make all files available under common path echo "-- $tag-ca.key.pem" cp csp/$tag/private/ca.key $outdir/$tag-ca.key.pem echo "-- $tag-ca.crt.pem" cp csp/$tag/ca.crt $outdir/$tag-ca.crt.pem # provide textual presentations echo "-- $tag-ca.key.txt" $prefix/bin/openssl rsa \ -in $outdir/$tag-ca.key.pem -passin "pass:$password" \ -noout -text \ >$outdir/$tag-ca.key.txt echo "-- $tag-ca.crt.txt" $prefix/bin/openssl x509 \ -in $outdir/$tag-ca.crt.pem \ -noout -text \ >$outdir/$tag-ca.crt.txt # generate regular private keys and certificates for type in server client object; do eval "max=\$num_$type" i=1 while [ $i -le $max ]; do # determine name name="$type" if [ $max -gt 1 ]; then name="$name$i" fi i=`expr $i + 1` echo "++ generate $type private key and certificate" # generate private key and certificate request echo "-- $tag-$name.key.pem" department=`$prefix/bin/perl -e 'printf("%s%s", uc(substr($ARGV[0], 0, 1)), substr($ARGV[0], 1));' $type` keysize=1024 if [ ".$type" = .server ]; then keysize=2048 fi $prefix/bin/csp $tag request \ --csrfile=$outdir/$tag-$name.csr.pem \ --keyfile=$outdir/$tag-$name.key.pem \ --keysize=$keysize --keypass="$password" \ "CN=$name.$domain, OU=$department, O=$organization" # generate server certificate echo "-- $tag-$name.crt.pem" echo "y" | $prefix/bin/csp $tag sign \ --csrfile=$outdir/$tag-$name.csr.pem \ --type=$type --days=$lifetime --capass="$password" >/dev/null # cleanup by removing certificate request rm -f $outdir/$tag-$name.csr.pem # make all files available under common path idx=`expr $idx + 1` cp csp/$tag/certs/`echo . | awk '{ printf("%02X", idx); }' idx=$idx`.pem \ $outdir/$tag-$name.crt.pem # provide textual presentations echo "-- $tag-$name.key.txt" $prefix/bin/openssl rsa \ -in $outdir/$tag-$name.key.pem -passin "pass:$password" \ -noout -text \ >$outdir/$tag-$name.key.txt echo "-- $tag-$name.crt.txt" $prefix/bin/openssl x509 \ -in $outdir/$tag-$name.crt.pem \ -noout -text \ >$outdir/$tag-$name.crt.txt # make server private key insecure but necessarily unprotected # for unattended use by a server daemon if [ ".$type" = .server ]; then $prefix/bin/openssl rsa \ -in $outdir/$tag-$name.key.pem -passin "pass:$password" \ -out $outdir/$tag-$name.key.pem.new 2>/dev/null mv $outdir/$tag-$name.key.pem.new \ $outdir/$tag-$name.key.pem fi done done # cleanup echo "++ deleting temporary location" cd / || exit $? rm -rf $tmpdir >/dev/null 2>&1 || true