#!/bin/sh
# bg_acad_ca-cert-request.sh: Certificate Signing Request Generator
# Copyright(c) 2007, 2008 Luchesar V. ILIEV (BG.ACAD CA) <iliev@acad.bg>
# Copyright(c) 2005 Evaldo Gardenali <evaldo@gardenali.biz>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "ASIS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

# be safe about permissions
LASTUMASK=`umask`
umask 077

# OpenSSL for HPUX needs a random file
RANDOMFILE=$HOME/.rnd

# create a config file for openssl
CONFIG=`mktemp -q /tmp/openssl-conf.XXXXXXXX`
if [ ! $? -eq 0 ]; then
    echo "Error: Could not create temporary config file."
    exit 1
fi

echo "Private Key and Certificate Signing Request Generator, v 1.01"
echo "This script was designed to suit the request format needed by"
echo "the BG.ACAD CA Certificate Authority: http://www.ca.acad.bg/"

echo
echo

cat <<EOF
This script will guide you through all the steps necessary to generate
your certificate request. Before continuing, make sure that you have
read carefully the latest CP/CPS document, published by BG.ACAD CA
(always available from http://www.ca.acad.bg/policy.html), and that
you are comfortable with the policies and procedures described in it.
You will need to sign a statement that you accept to adhere to them,
when providing your request to the RA. Now type 'continue' to go on
(this is to make certain that you are indeed reading this text). Once
you begin going through the steps in this script, read all information
provided on the screen carefully before answering the questions. If
you have any doubts, contact your chosen RA or BG.ACAD CA directly.
EOF
while [ ! "$CONTINUE" = "continue" ]; do
    echo
    printf ">> "
    read CONTINUE
    if [ "$CONTINUE" = "continue" ]; then break; fi
    echo
    echo "Did you read the above text carefully?"
done

echo
echo
echo

echo "STEP 1 (of 5): Certificate purpose."
echo
cat <<EOF
Indicate whether the certificate you request is intended to be used in
the context of a Globus based Grid infrastructure, or ONLY outside of it.

Select:
1. This certificate WILL be used in Grid infrastructure.
2. This certificate will NOT be used in Grid infrastructure.

Hint: All LCG/gLite/SEE-GRID/EGEE users should choose (1) here.

EOF
until [ "$GRIDUSAGE" = "1" -o "$GRIDUSAGE" = "2" ]; do
    printf "Please type '1' or '2' (without the quotes) end press Enter: "
    read GRIDUSAGE
done

echo
echo
echo

echo "STEP 2 (of 5): Certificate class."
echo
cat <<EOF
Please choose the desired certificate class:

PEOPLE
Individuals working for organizations formally based in and/or having offices
inside the Republic of Bulgaria that exclusively operate in the research
and/or education field (e.g. universities, schools, research institutes of the
Bulgarian Academy of Sciences, their subordinates and divisions, etc.).
Employees of other organizations, not directly involved in the research
and/or education field, qualify under this Policy if the said organization
operates for non-commercial purposes on a not-for-profit basis.

HOSTS
Computer entities (that is, digital information processing devices, capable of
performing cryptographic operations) used in the operational activities of the
aforementioned organizations. Computer entities that are not directly related
to the organization's operations are not eligible for certification.

SERVICES
Services or host applications running on the abovementioned computer entities.
However, a host certificate shall be preferred to a service one in all cases
where the latter is not strictly required.
EOF
echo
PRECLASS=""
until [ "$PRECLASS" = "p" -o "$PRECLASS" = "h" -o "$PRECLASS" = "s" ]; do
    printf "Please type 'p', 'h', or 's' (without the quotes) end press Enter: "
    read PRECLASS
done

echo
echo
echo

echo "STEP 3 (of 5): Organization name."
echo
cat <<EOF
Here you need to type in the name of the organization you are affiliated
with. If you have been advised by BG.ACAD CA to omit this field, just press
Enter here. Otherwise, please consult the CA's website for the appropriate
abbreviation of your organization's name. If your organization is not on the
list, or you are in doubt, please contact your RA or the CA directly. Please
note that your organization must be one of the allowed organizational end-
entities, mentioned in the previous question.

Examples:
IICT-BAS
UNI-SOFIA
EOF
echo
printf "Please type the organization's name: "
read ORGNAME

if [ ! "$ORGNAME" = "" ]; then
    echo
    echo
    echo
    echo "STEP 3a (of 5): Organizational unit."
    echo
cat <<EOF
Now we need the name of your organizational unit within your organization.
If this question is not relevant to you (e.g. you don't have departments,
divisions, offices, etc. in your organization), you may omit it (by pressing
the Enter key), however you MUST advise the CA of your decision. Otherwise,
please consult again the CA's website for the appropriate abbreviation.

Examples:
GTA
FMI
EOF
    echo
    printf "Please type the organizational unit's name: "
    read ORGUNIT
fi

case $PRECLASS in
    p)
        CLASS="people"
        echo
        echo
        echo
        echo "STEP 4 (of 5): Personal name."
        echo
cat <<EOF
Here you must enter your personal name EXACTLY as written on your ID documents.
Obey the rules set in the last CP/CPS document issued by BG.ACAD CA. Generally,
you must write your FULL name, but it's permissable to abbreviate the middle
parts of the name to a single letter. Double names must be written completely.

Examples:
Aleko I. Konstantinov
John R. R. Tolkien
Anna-Maria J. Petrova-Dimitrova
EOF
        echo
        while [ "$COMMONNAME" = "" ]; do
            printf "Please type your name: "
            read COMMONNAME
        done

        echo
        echo
        echo "STEP 5 (of 5): E-mail address(es)."
        echo
cat <<EOF
Finally you may provide e-mail address(es) to be included in the certificate.
This step is optional, although it is generally a good idea to include at least
one e-mail address here. If you still don't want an e-mail address in your
certificate, just press Enter. Otherwise, type in the addresses (as many as you
like) one at a line and finish with pressing Enter on a blank line. Please have
in mind that any e-mail address you enter SHALL be verified by the CA before
the certificate is issued.

Examples:
ivanov@acad.bg
ivan.ivanov@gmail.com
EOF
        echo
        SAN=1
        SANS=""
        while [ ! "$SAN" = "" ]; do
            if [ "$SAN" = "1" ]; then
                printf "Please type your e-mail: "
            else
                printf "Please type your next e-mail: "
            fi
            read SAN
            if [ "$SAN" = "" ]; then break; fi
            if [ "$SANS" = "" ]; then
                SANS="email:$SAN"
            else
                SANS="$SANS, email:$SAN"
            fi
        done
        ENCRYPT=""
        ;;
    h)
        CLASS="hosts"
        echo
        echo
        echo "STEP 5 (of 5): Fully qualified domain names."
        echo
cat <<EOF
Finally we need the FQDN(s) of the host to be certified. Enter one FQDN at a line
and finish with pressing Enter on a blank line. When entering multiple FQDNs,
begin with the A record for the host and then continue with the CNAMEs. If there
are multiple A records, begin with the one that you consider primary. Please have
in mind that you MUST prove your authority over these FQDNs.

Examples:
ce01.grid.acad.bg
www.uni-sofia.bg
EOF
        echo
        while [ "$SAN" = "" ]; do
            printf "Please type the FQDN: "
            read SAN
            COMMONNAME="$SAN"
            SANS="DNS:$SAN"
        done
        while [ ! "$SAN" = "" ]; do
            printf "Please type the next FQDN: "
            read SAN
            if [ "$SAN" = "" ]; then
                 break
            else
                SANS="$SANS, DNS:$SAN"
            fi
        done
        ENCRYPT="-nodes"
        ;;
    s)
        CLASS="services"
        echo
        echo
        echo "STEP 5 (of 5): Service name."
        echo
        echo "Example: https"
        while [ "$SERVICENAME" = "" ]; do
            printf "Please type the service name: "
            read SERVICENAME
        done

        echo
        echo
        echo "STEP 5a (of 5): Host FQDN."
        echo
        echo "Example: ce01.grid.acad.bg"
        echo
        while [ "$FQDN" = "" ]; do
            printf "Please type the FQDN: "
            read FQDN
        done
        COMMONNAME=$SERVICENAME/$FQDN
        ENCRYPT="-nodes"
        ;;
esac

# Config File Generation

cat <<EOF > $CONFIG
######### BEGIN BG.ACAD CA CUSTOM OPENSSL.CNF #########
HOME                    = $HOME
EOF

if [ "`uname -s`" = "HP-UX" ]; then
    echo " RANDFILE                = $RANDOMFILE" >> $CONFIG
fi

cat <<EOF >> $CONFIG
[ req ]
default_bits            = 2048
default_md              = sha256
distinguished_name      = user-distinguished_name
attributes              = user-attributes
EOF

if [ ! "$SANS" = "" ]; then
    echo "req_extensions         = user-req_extenstions" >> $CONFIG
fi

cat <<EOF >> $CONFIG
string_mask             = nombstr
prompt                  = no

[ user-distinguished_name ]
0.domainComponent       = bg
1.domainComponent       = acad
0.organizationName      = $CLASS
EOF

if [ ! "$ORGNAME" = "" ]; then
    echo "1.organizationName      = $ORGNAME" >> $CONFIG
fi

if [ ! "$ORGUNIT" = "" ]; then
    echo "organizationalUnitName  = $ORGUNIT" >> $CONFIG
fi

cat <<EOF >> $CONFIG
commonName              = $COMMONNAME

[ user-attributes ]

[ user-req_extenstions ]
EOF

if [ ! "$SANS" = "" ]; then
    echo "subjectAltName          = $SANS" >> $CONFIG
fi

cat <<EOF >> $CONFIG

########## END BG.ACAD CA CUSTOM OPENSSL.CNF ##########
EOF

cat <<EOF


OK, now we have all the information. Before producing the request,
please make a final check of the information you've provided:

Certificate class:      $CLASS
Organization name:      $ORGNAME
Organizational unit:    $ORGUNIT
Common name:            $COMMONNAME
E-mails/FQDNs:          $SANS

If everything is correct, press Enter here. Otherwise, stop the script
by pressing CTRL-C, and then start over again.
EOF
read ENTER

FILENAME=$CLASS-`echo $COMMONNAME | sed -e 's/ /_/g' | sed -e 's/\//-/g'`-`date -u +%Y%m%d-%H%M%S`

echo
echo "Running OpenSSL..."
openssl req -config $CONFIG \
            -newkey rsa:2048 \
            -out $HOME/$FILENAME-req.pem \
            -keyout $HOME/$FILENAME-key.pem \
            $ENCRYPT

if [ "$GRIDUSAGE" = "1" -a "$CLASS" = "people" ]; then
    if [ -d $HOME/.globus ]; then
        mv $HOME/.globus $HOME/.globus-`date -u +%Y%m%d-%H%M%S`.bak
    fi
    mkdir $HOME/.globus
    chmod 755 $HOME/.globus
    if [ -f $HOME/$FILENAME-req.pem -a -f $HOME/$FILENAME-key.pem ]; then
        cp -p $HOME/$FILENAME-req.pem $HOME/.globus/usercert_request.pem
        mv $HOME/$FILENAME-key.pem $HOME/.globus/userkey.pem
    else
        rmdir $HOME/.globus
    fi
fi

cat <<EOF

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you don't see error messages above, your CERTIFICATE REQUEST is ready.
It's available in the following file:
$HOME/$FILENAME-req.pem

You must now provide this file to your registration authority, as
described in the latest CP/CPS document of BG.ACAD CA.

EOF

if [ "$GRIDUSAGE" = "1" -a "$CLASS" = "people" ]; then
    echo "Note: The request was also written to $HOME/.globus/usercert_request.pem"
    echo "If you have had a ~/.globus directory beforehand, it has been backed up"
    echo "to ~/.globus-<date>-<UTCtime>.bak."
    echo
fi

echo "The PRIVATE KEY is stored in the following file:"
if [ "$GRIDUSAGE" = "1" -a "$CLASS" = "people" ]; then
    echo "$HOME/.globus/userkey.pem"
else
    echo "$HOME/$FILENAME-key.pem"
fi
echo
echo "IMPORTANT: KEEP THIS FILE AS SECURE AS POSSIBLE!"

cat <<EOF

If there have been problems with the certificate request generation,
please contact your RA or BG.ACAD CA directly. Be sure to have all
error messages and other useful information on hand.

EOF

rm $CONFIG

#restore umask
umask $LASTUMASK
