File: grid-ca-create.in

package info (click to toggle)
globus-simple-ca 5.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster
  • size: 544 kB
  • sloc: sh: 5,231; perl: 267; makefile: 98
file content (926 lines) | stat: -rwxr-xr-x 26,273 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
#! /bin/sh 

# This script creates a new CA certificate and the configuration files so that
# the grid-cert-request and grid-ca-sign tools can be used with the CA.
# Unlike GT 2-5, this version of the simple CA tool does not create a setup package

set -e

openssl="@OPENSSL@"

# catch the kill signal (ctrl-c) and do cleanup
trap do_trap 1 2 3 6 9 13 15

CYGPATH_W="@CYGPATH_W@"
host_os="@host_os@"

alias construct_path=echo
if test x"$CYGPATH_W" != x; then
    case $host_os in
        *mingw32*)
            alias construct_path="$CYGPATH_W"
            ;;
    esac
fi

bits=4096

##
# create_ca_directory:
# Creates the directory tree needed for a grid CA. The tree contains:
# $GRID_CA_DIR
# +- serial
# +- index.txt
# +- certs/
# +- crl/
# +- newcerts/
# +- private/
#
# On error, this function exits the shell.
#
# @param DIRECTORY
#     Path to the new CA directory
#
create_ca_directory()
{
    _ca_directory="$1"
    _ca_dir_perms="0700"

    if [ -d "${_ca_directory}/." ]; then
        if test -z "${force}"; then
            echo ""
            echo "It looks like a CA has already been setup at this location."
            printf "Do you want to overwrite this CA? (y/n) [n]: "
            read tmp_answer
            if ! expr "${tmp_answer:-n}" : '[Yy]' > /dev/null; then
                exit 1
            fi
        fi
        rm -rf "${_ca_directory}"
    fi

    mkdir -m ${_ca_dir_perms} -p "${_ca_directory}"

    if [ $? -ne 0 -o ! -d "${_ca_directory}/." ]; then
        echo "ERROR: Couldn't create directory: ${_ca_directory}"
        echo "       make sure you have valid permissions set."
        exit 1;
    fi

    # from the CA.sh script - setup the CA directory 
    for directory in certs crl newcerts private ; do
        mkdir -m ${_ca_dir_perms} "${_ca_directory}/${directory}"
        if test $? -ne 0; then
            exec 1>&2
            echo ""
            echo "ERROR: Failed to make directory: ${1}"
            echo "Check permissions of base dir"
            echo ""
            exit 1
        fi
    done

    echo "01" > ${_ca_directory}/serial
    if test $? -ne 0; then
        exec 1>&2
        echo ""
        echo "ERROR: Could not write to ${_ca_directory}/serial"
        echo "Check permissions on the dir"
        echo ""
        exit 1
    fi

    touch ${_ca_directory}/index.txt
    if test $? -ne 0; then
        exec 1>&2
        echo ""
        echo "ERROR: Could not write to ${_ca_directory}/index.txt"
        echo "Check the permissions on the dir"
        echo ""
        exit 1
    fi
}

##
# generate_unique_name: finds a unique name for the CA
#                       based on the hostname
generate_unique_name()
{
    tmp_hostname="$globus_hostname"

    if test -z "${tmp_hostname}"; then
        if [ -n "${noint}" ]; then
            exec 1>&2
        fi
        echo "" 
        echo "Cannot determine this machine's hostname for the CA name."
        echo ""



        if [ -n "${noint}" ]; then
            exit 1
        fi
    fi

    echo "simpleCA-${tmp_hostname}"
    return 0
}

#
# get_ca_subject: gets the CA subject name from the user if not in command-line options
#
get_ca_subject()
{
    varname="${1}"
    _casubject="${request_subject:-cn=Globus Simple CA, ou=$(generate_unique_name), ou=GlobusTest, o=Grid}"

    _got_subject="no"

    while [ "${_got_subject}" = "no" ] ; do
        echo ""
        echo "The unique subject name for this CA is:"
        echo ""
        echo "${_casubject}"
        echo ""

        if [ -n "${noint}" -o -n "${request_subject}" ]; then
            _got_subject="yes"
        else
            printf "Do you want to keep this as the CA subject (y/n) [y]: "
            
            while [ "${_got_subject}" = "no" ]; do
                read _answer

                case "${_answer:-y}" in
                [Nn]*)
                    echo ""

                    while [ "$_got_subject" = "no" ]; do
                        printf "Enter a unique subject name for this CA: "
                        read _casubject
                        echo ""
                        if expr "${_casubject}" : "[Cc][Nn]=.*,.*=.*"  > /dev/null; then
                            _got_subject="yes"
                        else
                            echo "Invalid CA subject name. Please include a common name and at least one"
                            echo "other name component (e.g. CN=Globus, O=Test)"
                        fi
                    done
                    ;;
                [Yy]*)
                    _got_subject="yes"
                    ;;
                *)
                    echo ""
                    echo "Please answer 'y' or 'n'"
                    echo ""
                    ;;
                esac
            done
        fi
    done
    eval "$varname=\"${_casubject}\""
}

get_ca_email()
{
    _varname="${1}"
    _caemail=""
    _defaultemail="${request_email:-${globus_username}@$globus_hostname}"

    if [ -n "${request_email}" -o -n "${noint}" ]; then
        _caemail="${_defaultemail}"
    fi

    while [ -z "${_caemail}" ]; do
        echo ""
        echo "Enter the email of the CA (this is the email where certificate"
        printf "requests will be sent to be signed by the CA) [${_defaultemail}]: "
        read _caemail
        _caemail="${_caemail:-${_defaultemail}}"
    done

    eval "${_varname}=\"${_caemail}\""
}

get_ca_lifetime()
{
    _varname="${1}"

    if [ -z "${noint}" -a -z "${request_days}" ]; then
        cat <<-EOF
	    The CA certificate has an expiration date. Keep in mind that 
       	    once the CA certificate has expired, all the certificates 
       	    signed by that CA become invalid.  A CA should regenerate 
       	    the CA certificate and start re-issuing ca-setup packages 
       	    before the actual CA certificate expires.  This can be done 
       	    by re-running this setup script.  Enter the number of DAYS 
       	    the CA certificate should last before it expires.
	EOF

        printf "[default: 5 years $((365 * 5)) days]: "
        read _ca_cert_days
        _ca_cert_days="${_ca_cert_days:-$((365 * 5))}"
        echo
    else
        _ca_cert_days="${request_days:-$((365 * 5))}"
    fi

    eval "${_varname}=\"${_ca_cert_days}\""
}

grid_security_conf_template()
{
    cat <<'EOF'
@grid_security_conf_tmpl@
EOF
}

##
# save_ca_settings: save the settings determined from this
#                   script to grid-security.conf for this CA
#
save_ca_settings()
{
    _dest="$1"
    _subj="$2"
    _addr="$3"

    # Save stdin and stdout
    exec 3<&0
    exec 4>&1

    # Translate template to configuration file
    exec 1> "${_dest}/grid-security.conf" 

    # Template variables
    domain="$(globus-domainname)"
    GSI_CA_BASE_DN="$(expr "${_subj}" : "[Cc][Nn]=[^,]*, *\(.*\)")"
    GSI_CA_NAME="$(expr "${_subj}" : "[Cc][Nn]= *\([^,]*\)")"
    GSI_CA_EMAIL="${_addr}"

    # Replace template variables in the configuration file
    grid_security_conf_template | while read line; do
        case "$line" in
            "#"*)
                echo "$line"
                ;;
            *)
                eval echo "$line"
                ;;
        esac
    done

    # Restore stdin and stdout
    exec 0<&3
    exec 1>&4

    exec 3<&-
    exec 4>&-
}

############################################################
# create_input_file: generate the input file to be passed as
#                    stdin to the openssl req utility.
############################################################
create_input_file ()
{
    _common_name="$1"
    _config_file="$2"

    # Parse the ssleay configuration file, to determine the
    # correct default 
    exec 3<&0
    exec 0< "${_config_file}" || {
        rc=$?;
        echo 1>&2 "Error opening ${_config_file}";
        exit $rc
    }
    _skip=1

    while read _line; do
        if [ "$_line" = "# BEGIN CONFIG" ]; then
            _skip=0
            continue
        elif [ "$_line" = "# END CONFIG" ]; then
            break
        fi
        if [ "$_skip" -eq 0 ]; then
            _attr="$(expr "$_line" : "\(.*[^ ]\) *=")"
            _value="$(expr "$_line" : "[^=]*= *\(.*\)")"
            if expr "${_attr}" : ".*_default\$" > /dev/null; then
                echo "${_value}"
            fi
        fi
    done
    echo "$_common_name"

    exec 0<&3
    exec 3<&-
}

rfc2253_to_ssl_config()
{
    _type="${1}"
    _name="${2}"

    OLDIFS="$IFS"
    IFS=","
    oucount=0
    ocount=0
    dccount=0

    _reversei=""
    for i in ${_name}; do
        _reversei="${i}${_reversei:+,${_reversei}}"
    done

    for i in ${_reversei}; do
        i="${i# }"
        _component="$(echo ${i%%=*} | tr 'A-Z' 'a-z')"
        _value="${i#*=}"

        case "$_component" in
            c|countryname)
                printf "%-40s= %s\n" countryName "Country Name (2 letter code)"
                printf "%-40s= %s\n" countryName_default "${_value}"
                printf "%-40s= %s\n" countryName_min "2"
                printf "%-40s= %s\n" countryName_max "2"
                ;;
            o|organizationname)
                printf "%-40s= %s\n" "$ocount.organizationName" "Level $ocount Organization"
                printf "%-40s= %s\n" "$ocount.organizationName_default" "${_value}"
                ocount=$(($ocount+1))
                ;;
            ou|organizationalunitname)
                printf "%-40s= %s\n" "$oucount.organizationalUnitName" "Level $oucount Organizational Unit"
                printf "%-40s= %s\n" "$oucount.organizationalUnitName_default" "${_value}"
                oucount=$(($oucount+1))
                ;;
            postalcode)
                printf "%-40s= %s\n" "postalCode" "Postal Code"
                printf "%-40s= %s\n" "postalCode_default" "${_value}"
                ;;
            cn|commonname)
                if [ "$_type" = "-user" ]; then
                    printf "%-40s= %s\n" "$oucount.organizationalUnitName" "Level $oucount Organizational Unit"
                    printf "%-40s= %s\n" "$oucount.organizationalUnitName_default" "${_value}"
                fi
                printf "%-40s= %s\n" "commonName" "Name (E.g., John M. Smith)"
                printf "%-40s= %s\n" "commonName_max" "64"
                ;;
            l|localityname)
                printf "%-40s= %s\n" "localityName" "Locality Name"
                printf "%-40s= %s\n" "localityName_default" "${_value}"
                ;;
            st|stateorprovincename )
                printf "%-40s= %s\n" "stateOrProvinceName" "State or Province Name"
                printf "%-40s= %s\n" "stateOrProvinceName_default" "${_value}"
                ;;
             street|streetaddress)
                printf "%-40s= %s\n" "streetAddress" "Street Address"
                printf "%-40s= %s\n" "streetAddress_default" "${_value}"
                ;;
             dc|domaincomponent )
                printf "%-40s= %s\n" "$dccount.DC" "Domain Component"
                printf "%-40s= %s\n" "$dccount.DC_default" "${_value}"
                dccount=$(($dccount + 1))
                ;;
             uid|userid)
                printf "%-40s= %s\n" "UID" "UserId"
                printf "%-40s= %s\n" "UID_default" "${_value}"
                ;;
            *)
                echo 1>&2 "Unknown subject name component"
                exit 1
                ;;
        esac
    done
    IFS="$OLDIFS"
}

rfc2253_to_oneline()
{
    _name="${1}"

    OLDIFS="$IFS"
    IFS=","
    _oneline=""

    for i in ${_name}; do
        i="${i# }"
        _component="$(echo ${i%%=*} | tr 'A-Z' 'a-z')"
        _value="${i#*=}"

        case "$_component" in
            c)
                _oneline="/C=${_value}${_oneline}"
                ;;
            o)
                _oneline="/O=${_value}${_oneline}"
                ;;
            ou)
                _oneline="/OU=${_value}${_oneline}"
                ;;
            cn)
                _oneline="/CN=${_value}${_oneline}"
                ;;
            l)
                _oneline="/L=${_value}${_oneline}"
                ;;
            postalcode)
                _oneline="/POSTALCODE=${_value}${_oneline}"
                ;;
            st)
                _oneline="/ST=${_value}${_oneline}"
                ;;
            street)
                _oneline="/STREET=${_value}${_oneline}"
                ;;
            dc)
                _oneline="/DC=${_value}${_oneline}"
                ;;
            uid)
                _oneline="/UID=${_value}${_oneline}"
                ;;
            *)
                echo 1>&2 "Unknown subject name component"
                exit 1
                ;;
        esac
    done
    IFS="$OLDIFS"
    echo "$_oneline"
}

ca_signing_policy_tmpl()
{
    cat <<'EOF'
@ca_signing_policy_tmpl@
EOF
}

generate_signing_policy()
{
    _cadir="${1}"
    _caname="${2}"

    GRID_CA_SUBJECT="$(rfc2253_to_oneline "${_caname}")"
    rc=$?
    if [ $rc -ne 0 ]; then
        exit $rc
    fi

    GRID_CA_COND_SUBJECT="\"${GRID_CA_SUBJECT%%/CN=*}/*\""

    exec 3<&0
    exec 4>&1

    exec 1> "${_cadir}/signing-policy"

    ca_signing_policy_tmpl | while read line; do
        if expr "${line}" : ".*#" > /dev/null; then
            comment="#${line#*#}"
        else
            comment=""
        fi
        precomment="${line%%${comment}}"

        eval lineval="\"${precomment}\""
        echo "${lineval}${comment}"
    done


    exec 0<&3
    exec 1>&4

    exec 3<&-
    exec 4>&-
}

setup_grid_security_dir()
{
    _cadir="${1}"
    _destdir="${2}"
    _cahash="$("$openssl" x509 -in "$(construct_path ${_cadir}/cacert.pem)" -noout -hash)"

    printf "Installing new CA files to ${_destdir}... "

    if [ ! -d "${_destdir}" ]; then
        mkdir -m 0755 -p "${_destdir}"
    fi

    cp "${_cadir}/cacert.pem" "${_destdir}/${_cahash}.0"
    cp "${_cadir}/signing-policy" "${_destdir}/${_cahash}.signing_policy"
    cp "${_cadir}/grid-security.conf" "${_destdir}/grid-security.conf.${_cahash}"
    cp "${_cadir}/globus-user-ssl.conf" "${_destdir}/globus-user-ssl.conf.${_cahash}"
    cp "${_cadir}/globus-host-ssl.conf" "${_destdir}/globus-host-ssl.conf.${_cahash}"

    echo "done"
}

grid_ca_ssl_conf_tmpl()
{
    cat <<'EOF'
@grid_ca_ssl_conf_tmpl@
EOF
}

create_ssl_config()
{
(
    _type="${1}"
    _caname="${2}"
    _cadir="${3}"

    . "${_cadir}/grid-security.conf"

    exec 3<&0

    _skip=0

    GRID_CA_DIR="${_cadir}"
    grid_ca_ssl_conf_tmpl | while read line; do
        if expr "${line}" : ".*#" > /dev/null; then
            comment="#${line#*#}"
        else
            comment=""
        fi
        precomment="${line%%${comment}}"

        if [ "$comment" = "# BEGIN CONFIG" ]; then
            _skip=1
            echo "${comment}"
            rfc2253_to_ssl_config "${_type}" "${_caname}"
        elif [ "$comment" = "# END CONFIG" ]; then
            _skip=0
        fi
        if [ $_skip -eq 1 ]; then
            continue
        fi
        case "$precomment" in
            \[* )
                echo "${precomment}${comment}"
                ;;
            *)
                eval printf "%s" "\"${precomment}\""
                echo "${comment}"
                ;;
        esac
    done

    exec 0<&3
    exec 3<&-
)
}

############################################################
# generate_ca_certificate: the meat & potatoes - calls the 
#                          openssl req utility that creates
#                          the CA certificate
############################################################
generate_ca_certificate() 
{
    _cadir="${1}"
    _caname="${2}"
    _privatedir="${_cadir}/private"
    _ca_ssl_conf="${_cadir}/grid-ca-ssl.conf"
    _user_ssl_conf="${_cadir}/globus-user-ssl.conf"
    _host_ssl_conf="${_cadir}/globus-host-ssl.conf"


    create_ssl_config -ca "${_caname}" "${_cadir}" > "${_ca_ssl_conf}"
    create_ssl_config -user "${_caname}" "${_cadir}" > "${_user_ssl_conf}"
    create_ssl_config -host "${_caname}" "${_cadir}" > "${_host_ssl_conf}"

    CA_REQ_INPUT=${_privatedir}/tmp_openssl_input.conf

    create_input_file "${GSI_CA_NAME}" "${_ca_ssl_conf}" > ${CA_REQ_INPUT}

    if test -n "${request_password}"; then
        password_option="-passout pass:${request_password} "
    elif test -n "${noint}"; then
        password_option="-passout pass:globus "
    else
        password_option=""
    fi

    # create CA certificate
    if [ -n "${verbose}" ]; then
        "$openssl" req ${openssl_options} ${password_option} -config "$(construct_path ${_ca_ssl_conf})" \
            -x509 -days ${CA_CERT_DAYS} \
            -newkey rsa:${bits} -keyout $(construct_path ${CA_KEY_FILE}) \
            -out $(construct_path ${CA_CERT_FILE}) < ${CA_REQ_INPUT}
        RET=$?
    else
        "$openssl" req ${openssl_options} ${password_option} -config "$(construct_path ${_ca_ssl_conf})" \
            -x509 -days ${CA_CERT_DAYS} \
            -newkey rsa:${bits} -keyout $(construct_path ${CA_KEY_FILE}) \
            -out $(construct_path ${CA_CERT_FILE}) < ${CA_REQ_INPUT} > openssl_req.log 2>&1
        RET=$?
    fi


    if [ "${RET}" -eq 0 -a -n "${verbose}" ]; then
        tput clear
    elif [ "${RET}" -ne 0 ]; then
        echo "Error number ${RET} was returned by openssl" 1>&2
        exit ${RET}
    fi
}


############################################################
# do_trap:  catches any abortive signals and does cleanup
############################################################
do_trap() {

    echo ""
    echo ""
    echo "Normal program execution interrupted.  You will"
    echo "need to rerun the script:"
    echo ""
    echo "\${GLOBUS_LOCATION}/setup/globus/setup-simple-ca"
    echo ""
    echo "to setup the simple CA."
    echo ""

    exit 1
}


############################################################
# main code section
############################################################

prefix="${GLOBUS_LOCATION-@prefix@}"
exec_prefix="@exec_prefix@"
sbindir="@sbindir@"
bindir="@bindir@"
includedir="@includedir@"
datarootdir="@datarootdir@"
datadir="@datadir@"
libexecdir="@libexecdir@"
sysconfdir="@sysconfdir@"
sharedstatedir="@sharedstatedir@"
localstatedir="@localstatedir@"

PROGRAM_NAME="${0##*/}"
PROGRAM_VERSION="@VERSION@"
PACKAGE="@PACKAGE@"
VERSION="@VERSION@"
DIRT_TIMESTAMP="@DIRT_TIMESTAMP@"
DIRT_BRANCH_ID="@DIRT_BRANCH_ID@"

short_usage="$PROGRAM_NAME [-help] [ options ...] [ openssl options ...]"

printhelp() {
    option="${1}"
    helpstr="${2}"
    optwidth="${optwidth:-$((${COLUMNS:-80} / 3))}"
    if [ "$optwidth" -gt 30 ]; then
        optwidth=30
    fi
    helpwidth="${helpwidth:-$((${COLUMNS:-80} - $optwidth - 6))}"
    helpstrformatted="$(echo "${helpstr}" | tr -sd '\n\t' ' ' | \
            fold -sw ${helpwidth})"

    OLDIFS="$IFS"
    IFS="
"
    first=1

    for x in $helpstrformatted; do
        printf "    %-${optwidth}s %-${helpwidth}s\n" "${first:+$option}" "$x"
        first=""
    done
    IFS="$OLDIFS"
}

globus_hostname="$(globus-hostname)"
globus_username="$(id -un)"

long_usage () {
    cat <<EOF

${short_usage}

  Note: Many of the following options can be used instead of allowing
        the script to interactively request configration info.  If
        its not clear what to do, let the interactive prompts guide you.

  Options:
EOF
    printhelp "-help, -?, -h, -usage" "shows this help message"
    printhelp "-verbose" "Show verbose output [unset]"
    printhelp "-force" "Overwite existing CA if one exists [unset]"
    printhelp "-noint" "Run in non-interactive mode. This will choose
            defaults for parameters or those specified on the command line
            without prompting. This option also implies -force. [unset]"
    printhelp "-dir DIRECTORY" "Create the SimpleCA in DIRECTORY.
            [$( ([ -w "${localstatedir}/lib/." ] &&  \
                    echo \${localstatedir}/lib/globus/simple_ca ) \
                    || echo \${HOME}/.globus/simpleCA)]"
    printhelp "-subject SUBJECT" "Create CA with the subject name SUBJECT 
           [cn=Globus Simple CA, ou=$(generate_unique_name),
           ou=GlobusTest, o=Grid]"
    printhelp "-email ADDRESS" "Include instructions to send certificate
            requests to ADDRESS [${globus_username}@${globus_hostname}]"
    printhelp "-days DAYS" "Create a CA certificate that lasts for DAYS days
            [$((365 * 5))]"
    printhelp "-bits BITS" "Create a CA certificate with a BITS long RSA key [4096]"
    printhelp "-pass PASSWORD" "Set the password for the CA's private key
            to PASSWORD.  Since the password is visible to utilities, this
            should only be used where security is not important. [globus]"
    printhelp "-nobuild" "Don't create a package for distributing
            configuration files for this CA. These can be created later by
            using the grid-ca-package utility [unset]"
    printhelp "-g" "Create a GPT binary package containing the CA and
            configuration files [unset]"
    printhelp "-b" "Create a GPT binary package containing the CA and
            configuration files compatible with GPT 3.2 and GT 4 and 5 [unset]"
    printhelp "-openssl-help" "Show help text for openssl"
    printhelp "[OPENSSL-OPTIONS]" "Specify additional options to pass to the 
            openssl command.  Use with caution, some options will conflict 
            with this script."
}

readCommandLine () {
  # Expects $@ from the shell invocation

  while test -n "$1"; do
    case $1 in
      -\?|-h|-help|-usage|--help|--usage)
         long_usage
         exit 0
         ;;
     -g)
         gpt_package=1
         shift
         ;;
     -b)
         gpt_package=1
         backward_compatible=1
         shift
         ;;
     -bits|--bits)
        shift
        bits="$1"
        shift
        ;;
     -dir|--dir)
         tmp_ca_dir="$2"
         if test -z "${tmp_ca_dir}"; then
            echo "ERROR: the -dir option expects a directory."
            exit 1;
         fi
         if test "${tmp_ca_dir##/*}" = ""; then
             GRID_CA_DIR="${tmp_ca_dir}"
         else
             GRID_CA_DIR="$PWD/${tmp_ca_dir}"
         fi
         
         shift ; shift
         ;;
     -force|--force)
         force="yes"
         shift
         ;;
     -subject|--subject)
         shift
         request_subject="${1}"
         shift
         if ! expr "${request_subject}" : "[Cc][Nn]=.*,.*=.*"  > /dev/null; then
             exec 1>&2
             echo "Invalid CA subject name. Please include a common name and at least one"
             echo "other name component (e.g. CN=Globus, O=Test)"
             exit 1
         fi
         ;;
     -email|--email)
         request_email="${2}"
         shift ; shift
         ;;
     -days|--days)
         request_days="${2}"
         shift ; shift
         ;;
     -pass|--pass)
         request_password="${2}"
         shift ; shift
         ;;
     -nobuild|--nobuild)
         nobuild="yes"
         shift
         ;;
     -noint|--noint)
         noint="yes"
         force="yes"
         shift
         ;;
     -verbose|--verbose)
         verbose="yes"
         shift
         ;;
     -openssl-help)
         shift;
         "$openssl" req -help;
         exit;
         ;;
     -version|--version)
        if [ "X${PROGRAM_NAME}" != "X" -a \
              "X${PROGRAM_VERSION}" != "X" ]; then
            echo "${PROGRAM_NAME}: ${PROGRAM_VERSION}"
        elif [ "X${PACKAGE}" != "X" -a \
               "X${VERSION}" != "X" ]; then
            echo "${PACKAGE}: ${VERSION}"
        else
            echo "No version information available."
        fi
        exit 0
        ;;
     -versions|--versions)
        __AT='@'
        if [ -n "${PACKAGE}" -a -n "${VERSION}" -a \
             -n "${DIRT_TIMESTAMP}" -a -n "${DIRT_BRANCH_ID}" -a \
             "X${DIRT_TIMESTAMP}" != "X${__AT}DIRT_TIMESTAMP${__AT}" -a \
             "X${DIRT_BRANCH_ID}" != "X${__AT}DIRT_BRANCH_ID${__AT}" ];
        then
            echo "${PACKAGE}: ${VERSION} (${DIRT_TIMESTAMP}-${DIRT_BRANCH_ID})"
        else
            echo "No DiRT information available."
        fi
        exit 0;
        ;;

     *)
         openssl_options="$openssl_options $1"
         shift;
         ;;
    esac
  done
}

# MAIN
readCommandLine "$@"

# setup variables used by the script
if test -z "${GRID_CA_DIR}"; then
    if [ -d "${localstatedir}/lib/." -a -w "${localstatedir}/lib/." ]; then
        GRID_CA_DIR="$localstatedir/lib/globus/simple_ca"
        default_loc="yes"
    else
        GRID_CA_DIR="${HOME}/.globus/simpleCA"
        default_loc="yes"
    fi
fi


CA_KEY_FILE="${GRID_CA_DIR}/private/cakey.pem"
CA_CERT_FILE="${GRID_CA_DIR}/cacert.pem"

cat <<EOF
 

    C e r t i f i c a t e    A u t h o r i t y    S e t u p

This script will setup a Certificate Authority for signing Globus
users certificates.  It will also generate a simple CA package
that can be distributed to the users of the CA.

The CA information about the certificates it distributes will
be kept in:

${GRID_CA_DIR}
EOF

create_ca_directory "${GRID_CA_DIR}"

# These functions assign a value to the variable named by their first parameter so that
# they can prompt for input
get_ca_subject grid_ca_subject
get_ca_email grid_ca_email
get_ca_lifetime CA_CERT_DAYS

save_ca_settings "${GRID_CA_DIR}" "$grid_ca_subject" "$grid_ca_email"
generate_ca_certificate "${GRID_CA_DIR}" "${grid_ca_subject}"
generate_signing_policy "${GRID_CA_DIR}" "${grid_ca_subject}"
mkdir -m 0755 -p "${sysconfdir}/grid-security/certificates/" 2> /dev/null || :
if [ -w "${sysconfdir}/grid-security/certificates/." ]; then
    setup_grid_security_dir "${GRID_CA_DIR}" "${sysconfdir}/grid-security/certificates"
elif [ -w "${datadir}/certificates" ]; then
    setup_grid_security_dir "${GRID_CA_DIR}" "${datadir}/certificates"
else
    echo "Insufficient permissions to install CA into the trusted certifiicate"
    echo "directory (tried \${sysconfdir}/grid-security/certificates and"
    echo "\${datadir}/certificates)"
fi

cahash="$("$openssl" x509 -in "$(construct_path ${_cadir}/cacert.pem)" -noout -hash)"

if [ -z "$nobuild" ]; then
    grid-ca-package ${backward_compatible:+-b} ${gpt_package:+-g} -cadir "${GRID_CA_DIR}"
fi

exit 0