/[pdpsoft]/nl.nikhef.pdp.tcs/nl.nikhef.pdp.tcs.tcsg4-tools/trunk/tcsg4-install-credential.sh
ViewVC logotype

Annotation of /nl.nikhef.pdp.tcs/nl.nikhef.pdp.tcs.tcsg4-tools/trunk/tcsg4-install-credential.sh

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3304 - (hide annotations) (download) (as text)
Tue Sep 22 09:59:24 2020 UTC (20 months ago) by davidg
File MIME type: application/x-shellscript
File size: 12909 byte(s)
increased compatibility with BSD

1 davidg 3283 #! /bin/sh
2     #
3     # @(#)$Id$
4     # rev 2
5     #
6     # TCS G4 client certificate format management tool for POSIX systems
7     # including installation to Grid Community Toolkit (formerly Globus)
8     # user credential directory formats
9     #
10     # Requirements: sh, awk, sed, openssl, date, mktemp, ls,
11     # mkdir, rmdir, mv, basename, grep, chmod
12     #
13 davidg 3293 # Copyright 2020 David Groep, Nikhef, Amsterdam
14     #
15     # Licensed under the Apache License, Version 2.0 (the "License");
16     # you may not use this file except in compliance with the License.
17     # You may obtain a copy of the License at
18     #
19     # http://www.apache.org/licenses/LICENSE-2.0
20     #
21     # Unless required by applicable law or agreed to in writing, software
22     # distributed under the License is distributed on an "AS IS" BASIS,
23     # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24     # See the License for the specific language governing permissions and
25     # limitations under the License.
26 davidg 3283 #
27 davidg 3293 #
28 davidg 3283 destdir=${HOME}/.globus
29     DATE=`date +%Y%m%d-%H%M%S`
30     progname=`basename "$0"`
31     bckprefix=backup
32     makecsr=0
33 davidg 3299 newpass=0
34 davidg 3283 nameformat=
35     certfn=
36 davidg 3303 AWK=${AWK:-awk}
37 davidg 3283
38     # ############################################################################
39     # usage help and instructions
40     #
41     help() { cat <<EOF
42     Usage: tcsg4-install-credential.sh [-d destdir] [-p passfile] [-r|-R] [-f]
43     [-n name] [-b backupprefix] <PKCS12.p12>
44    
45     -d destdir write result files to <destdir>
46     if <destdir> contains "globus", also make the
47     symlinks userkey.pem and usercert.pem for GCT tools
48     -p passfile file with the password to use (same for input
49     and for output PKCS#12 and private keys)
50     -r use EEC commonName as basis for new filenames
51     -R use EEC commonName and date as basis for filenames
52     -f do not make backups of existing files
53     -n name set friendly name of the credential in corrected
54     PKCS#12 (.p12) file produced. If unset, is taken
55     from the commonName of the EEC and issuance date
56     -b bckprefix prefix of the filename to use when making backups
57     --csr generate a CSR request file for future use in destdir
58    
59     <PKCS12.p12> filename of the blob produced by Sectigo
60    
61     Notice: do NOT import the blob from Sectigo directly into
62     anything, since it will corrupt your key chain. Always use
63     the "package-<name>.p12" file created by this script
64    
65     EOF
66     return;
67     }
68    
69     # ############################################################################
70     #
71     while [ $# -gt 0 ]; do
72     case "$1" in
73     -r | --rename ) nameformat="friendly"; shift 1 ;;
74     -R | --rename-with-date ) nameformat="dated"; shift 1 ;;
75     --csr ) makecsr=1; shift 1 ;;
76     -f | --force ) bckprefix=""; shift 1 ;;
77     -h | --help ) help ; exit 0 ;;
78     -b | --backupprefix ) bckprefix="$2"; shift 2 ;;
79     -n | --name ) friendlyname="$2"; shift 2 ;;
80     -d | --destination ) destdir="$2"; shift 2 ;;
81     -p | --passfile ) passfile="$2" ; shift 2 ;;
82 davidg 3299 --newpass ) newpass=1 ; shift ;;
83 davidg 3283 -* ) echo "Unknown option $1, exiting" >&2 ; exit 1 ;;
84     * ) break ;;
85     esac
86     done
87    
88     case $# in
89     0 ) help ; exit 0 ;;
90     1 ) pkfile="$1"; break ;;
91     * ) echo "Too many arguments." >&2 ; exit 1 ;;
92     esac
93    
94     # ############################################################################
95     # input validation
96     #
97     if [ ! -r "$pkfile" ]; then echo "Cannot read $pkfile" >&2; exit 1; fi
98    
99     case "$pkfile" in
100     *.p12 ) credbase=`basename "$pkfile" .p12` ;;
101     *.pfx ) credbase=`basename "$pkfile" .pfx` ;;
102     * ) echo "Unlikely PKCS#12 file: $pkfile" >&2 ; exit 2 ;;
103     esac
104    
105     # ############################################################################
106     # obtain password from somewhere
107     #
108     if [ -n "$passfile" ]; then
109     if [ ! -r "$passfile" ]; then
110     echo "Error: cannot read password from $passfile" >&2 ; exit 1
111     fi
112     PW=`head -1 "$passfile"`
113     else
114     while [ x"$PW" = x"" ]; do
115 davidg 3304 echo -n "Passphrase (existing) for your secret key: "
116 davidg 3283 stty -echo ; read PW ; stty echo
117     echo ""
118     done
119     fi
120     if [ -z "$PW" ]; then echo "Empty password is not allowed" >&2; exit 2; fi
121    
122 davidg 3299 if [ $newpass -ne 0 ]; then
123     while [ x"$NPW" = x"" ]; do
124 davidg 3304 echo -n "NEW Passphrase for your secret key and PKCS#12 package: "
125 davidg 3299 stty -echo ; read NPW ; stty echo
126     echo ""
127     done
128     else
129     NPW="$PW"
130     fi
131    
132     export PW NPW
133    
134 davidg 3283 # ############################################################################
135     # extraction of Sectigo blob of crap
136     #
137     tempdir=`mktemp -d tcsg4unpack.XXXXXX`
138    
139     if [ ! -d "$tempdir" ]; then
140     echo "Error creating temporary working directory here" >&2
141     exit 1
142     fi
143    
144     openssl pkcs12 -nomacver -password env:PW -in "$pkfile" \
145 davidg 3299 -passout env:NPW -out "$tempdir/crap-$credbase.pem"
146 davidg 3283
147     if [ $? -ne 0 ]; then
148     echo "Error: cannot extract data from PKCS12 file $pkfile" >&2
149     echo " PASSPHRASE INCORRECT?" >&2
150     exit 3
151     fi
152    
153     if [ ! -s "$tempdir/crap-$credbase.pem" ]; then
154     echo "Error: cannot extract data from PKCS12 file $pkfile" >&2
155     echo " resulting direct-rendered crap file not found" >&2
156     exit 4
157     fi
158    
159     if [ `grep -c PRIVATE "$tempdir/crap-$credbase.pem"` -eq 0 ]; then
160     echo "Error: cannot extract data from PKCS12 file $pkfile" >&2
161     echo " resulting crap file has no key material" >&2
162     exit 4
163     fi
164    
165     if [ `grep -c CERTIFICATE "$tempdir/crap-$credbase.pem"` -eq 0 ]; then
166     echo "Error: cannot extract data from PKCS12 file $pkfile" >&2
167     echo " resulting crap file has no certificate material" >&2
168     exit 4
169     fi
170    
171     # extract
172 davidg 3303 $AWK '
173 davidg 3283 BEGIN { icert = 0; }
174     /^-----BEGIN ENCRYPTED PRIVATE KEY-----$/ {
175     print $0 > "'$tempdir/key-$credbase.pem'";
176     do {
177     getline ln;
178     print ln > "'$tempdir/key-$credbase.pem'";
179     } while ( ln != "-----END ENCRYPTED PRIVATE KEY-----" );
180     }
181     /^-----BEGIN CERTIFICATE-----$/ {
182     icert++;
183 davidg 3304 cfname = "'$tempdir/cert-'" icert "'-$credbase.pem'";
184     print $0 > cfname;
185 davidg 3283 do {
186     getline ln;
187 davidg 3304 print ln > cfname;
188 davidg 3283 } while ( ln != "-----END CERTIFICATE-----" );
189     }
190     ' "$tempdir/crap-$credbase.pem"
191    
192     # ############################################################################
193     # generate per-certificate and key output files
194     #
195     [ -d "$destdir" ] || mkdir -p "$destdir"
196    
197     havewrittenchain=0
198     for i in "$tempdir"/cert-*-"$credbase".pem
199     do
200     certcn=`openssl x509 -noout -subject -nameopt oneline,sep_comma_plus \
201     -in "$i" | \
202     sed -e 's/.*CN = \([a-zA-Z0-9\._][- a-zA-Z0-9:\._@]*\).*/\1/'`
203     issuercn=`openssl x509 -noout -issuer -nameopt oneline,sep_comma_plus \
204     -in "$i" | \
205     sed -e 's/.*CN = \([a-zA-Z0-9\._][- a-zA-Z0-9:\._@]*\).*/\1/'`
206    
207     certdate=`openssl x509 -noout -text -in "$i" | \
208 davidg 3303 $AWK '/ Not Before:/ { print $4,$3,$6; }'`
209 davidg 3283 certisca=`openssl x509 -noout -text -in "$i" | \
210 davidg 3303 $AWK 'BEGIN { ca=0; }
211 davidg 3283 /CA:FALSE/ { ca=0; } /CA:TRUE/ { ca=1; }
212     END {print ca;}'`
213    
214 davidg 3302 if [ "$certcn" = "$issuercn" -o "$issuercn" = "AddTrust External CA Root" -o "$issuercn" = "AAA Certificate Services" ]
215 davidg 3283 then
216     continue
217     fi
218    
219     if [ $certisca -eq 0 ]; then
220     certfn=`echo "$certcn" | sed -e 's/[^-a-zA-Z0-9_]/_/g'`
221     certfndated=`echo "$certcn issued $certdate" | \
222     sed -e 's/[^-a-zA-Z0-9_]/_/g'`
223     echo "Processing EEC certificate: $certcn"
224     friendlyname="${friendlyname:-$certcn issued $certdate}"
225     echo " (friendly name: $friendlyname)"
226     fi
227    
228     if [ $certisca -eq 1 ]; then
229     echo "Processing CA certificate: $certcn"
230     if [ $havewrittenchain -eq 0 ]; then
231     if [ -f "$destdir/chain-$credbase.pem" -a -n "$bckprefix" ]; then
232     mv "$destdir/chain-$credbase.pem" \
233     "$destdir/$bckprefix.$DATE.chain-$credbase.pem"
234     fi
235     havewrittenchain=1
236     echo "" > "$destdir/chain-$credbase.pem"
237     fi
238     cat $i >> "$destdir/chain-$credbase.pem"
239     fi
240    
241     if [ $certisca -eq 0 ]; then
242     if [ -n "$pkcs12eec" ]; then
243     echo "Error: there are multiple EEC certificates in the blob" >&2
244     echo " this script cannot handle this case, sorry!" >&2
245     exit 2
246     fi
247     pkcs12eec="$i"
248     if [ -f "$destdir/cert-$credbase.pem" ]; then
249     mv "$destdir/cert-$credbase.pem" "$destdir/$bckprefix.$DATE.cert-$credbase.pem"
250     fi
251     cat $i > "$destdir/cert-$credbase.pem"
252     fi
253    
254     done
255    
256     echo "Processing EEC secret key"
257     if [ ! -s "$tempdir/key-$credbase.pem" ]; then
258     echo "Error: cannot find secret key file which should have been there" >&2
259     echo " internal error in AWK section (P1)" >&2
260     exit 5
261     fi
262     if [ `grep -c PRIVATE "$tempdir/key-$credbase.pem"` -eq 0 ]; then
263     echo "Error: cannot find key in keyfile which should have been there" >&2
264     echo " internal error in AWK section (P2)" >&2
265     exit 5
266     fi
267    
268     if [ -f "$destdir/key-$credbase.pem" -a -n "$bckprefix" ]; then
269     mv "$destdir/key-$credbase.pem" "$destdir/$bckprefix.$DATE.key-$credbase.pem"
270     fi
271     cat "$tempdir/key-$credbase.pem" > "$destdir/key-$credbase.pem"
272    
273     # not all filesystems support perms, so ignore errors
274     chmod go-rwx "$destdir/key-$credbase.pem" 2>/dev/null
275     chmod go-rwx "$destdir/cert-$credbase.pem" 2>/dev/null
276    
277     echo "Repackaging $friendlyname as PKCS12"
278     if [ -f "$destdir/package-$credbase.p12" -a -n "$bckprefix" ]; then
279     mv "$destdir/package-$credbase.p12" \
280     "$destdir/$bckprefix.$DATE.package-$credbase.p12"
281     fi
282     openssl pkcs12 -export \
283 davidg 3299 -passin env:NPW -inkey "$tempdir/key-$credbase.pem" \
284 davidg 3283 -certfile "$destdir/chain-$credbase.pem" \
285     -name "$friendlyname" -in "$pkcs12eec" \
286 davidg 3299 -passout env:NPW -out "$destdir/package-$credbase.p12"
287 davidg 3283
288     if [ $? -ne 0 ]; then
289     echo "Error: something went wrong creating the normalised package" >&2
290     echo " non-zero return code from openssl in PKCS12 export (X1)" >&2
291     exit 5
292     fi
293     if [ ! -s "$destdir/package-$credbase.p12" ]; then
294     echo "Error: something went wrong creating the normalised package" >&2
295     echo " internal error in PKCS12 export (X2)" >&2
296     exit 5
297     fi
298    
299     # not all filesystems support perms, so ignore errors
300     chmod go-rwx "$destdir/package-$credbase.p12" 2>/dev/null
301    
302     # ############################################################################
303     # cleanup intermate files and name output properly
304     #
305     rm "$tempdir"/cert-*-$credbase.pem
306     rm "$tempdir"/crap-$credbase.pem
307     rm "$tempdir"/key-$credbase.pem
308     rmdir "$tempdir"
309     if [ $? -ne 0 ]; then
310     echo "Error: cannot remove working directory $tempdir" >&2
311     echo " internal inconsistency or prior error encountered" >&2
312     fi
313    
314     # rename, if so required
315     if [ -n "$nameformat" ]; then
316     if [ "$nameformat" = "friendly" ]; then
317     certfn="${certfn:-$credbase}"
318     elif [ "$nameformat" = "dated" ]; then
319     certfn="${certfndated:-$credbase}"
320     else
321     echo "Unknown filename format, error" >&2
322     exit 2
323     fi
324     mv "$destdir/cert-$credbase.pem" "$destdir/cert-$certfn.pem"
325     mv "$destdir/chain-$credbase.pem" "$destdir/chain-$certfn.pem"
326     mv "$destdir/key-$credbase.pem" "$destdir/key-$certfn.pem"
327     mv "$destdir/package-$credbase.p12" "$destdir/package-$certfn.p12"
328     else
329     certfn="$credbase"
330     fi
331    
332     # make CSR for future use if requested
333     if [ "$makecsr" -ne 0 ]; then
334     echo "Generating CSR file for future use and renewal"
335     if [ -f "$destdir/request-$credbase.pem" -a -n "$bckprefix" ]; then
336     mv "$destdir/request-$credbase.pem" \
337     "$destdir/$bckprefix.$DATE.request-$credbase.pem"
338     fi
339    
340     certsubject=/`openssl x509 -noout -subject -nameopt oneline,sep_comma_plus \
341     -in "$destdir/cert-$certfn.pem" | \
342     sed -e 's/^subject= *//;s/,/\//g;s/ = /=/g'`
343    
344     echo " subject: $certsubject"
345    
346     openssl req -new \
347 davidg 3299 -key "$destdir/key-$certfn.pem" -passin env:NPW \
348 davidg 3283 -subj "$certsubject" \
349     -out "$destdir/request-$certfn.pem"
350     fi
351    
352     # ############################################################################
353     # inform user of result and of globus compatibility
354     #
355     echo "The following files have been created for you:"
356 davidg 3304 echo -n " " ; ls -l1a "$destdir/cert-$certfn.pem"
357     echo -n " " ; ls -l1a "$destdir/chain-$certfn.pem"
358 davidg 3283 [ -f "$destdir/request-$certfn.pem" ] && \
359 davidg 3304 ( echo -n " " ; ls -l1a "$destdir/request-$certfn.pem" )
360     echo -n " " ; ls -l1a "$destdir/key-$certfn.pem"
361     echo -n " " ; ls -l1a "$destdir/package-$certfn.p12"
362 davidg 3283
363     # globus-ify pertinent dest directories
364     case "$destdir" in
365     *globus* )
366     echo "Making Grid Community Toolkit compatible link in $destdir"
367     if [ -f "$destdir/userkey.pem" -a -n "$bckprefix" ]; then
368     echo " backing up userkey.pem to ""$bckprefix.$DATE.userkey.pem"
369     mv "$destdir/userkey.pem" "$destdir/$bckprefix.$DATE.userkey.pem"
370     fi
371     echo " userkey.pem"
372 davidg 3304 ln -sfn "key-$certfn.pem" "$destdir/userkey.pem"
373 davidg 3283 if [ -f "$destdir/usercert.pem" -a -n "$bckprefix" ]; then
374     echo " backing up usercert.pem to $bckprefix.$DATE.usercert.pem"
375     mv "$destdir/usercert.pem" "$destdir/$bckprefix.$DATE.usercert.pem"
376     fi
377     echo " usercert.pem"
378 davidg 3304 ln -sfn "cert-$certfn.pem" "$destdir/usercert.pem"
379 davidg 3283 ;;
380     esac
381    
382     #
383     #
384     # ############################################################################

Properties

Name Value
svn:executable *

grid.support@nikhef.nl
ViewVC Help
Powered by ViewVC 1.1.28