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

Contents 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 - (show annotations) (download) (as text)
Tue Sep 22 09:59:24 2020 UTC (19 months, 4 weeks ago) by davidg
File MIME type: application/x-shellscript
File size: 12909 byte(s)
increased compatibility with BSD

1 #! /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 # 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 #
27 #
28 destdir=${HOME}/.globus
29 DATE=`date +%Y%m%d-%H%M%S`
30 progname=`basename "$0"`
31 bckprefix=backup
32 makecsr=0
33 newpass=0
34 nameformat=
35 certfn=
36 AWK=${AWK:-awk}
37
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 --newpass ) newpass=1 ; shift ;;
83 -* ) 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 echo -n "Passphrase (existing) for your secret key: "
116 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 if [ $newpass -ne 0 ]; then
123 while [ x"$NPW" = x"" ]; do
124 echo -n "NEW Passphrase for your secret key and PKCS#12 package: "
125 stty -echo ; read NPW ; stty echo
126 echo ""
127 done
128 else
129 NPW="$PW"
130 fi
131
132 export PW NPW
133
134 # ############################################################################
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 -passout env:NPW -out "$tempdir/crap-$credbase.pem"
146
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 $AWK '
173 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 cfname = "'$tempdir/cert-'" icert "'-$credbase.pem'";
184 print $0 > cfname;
185 do {
186 getline ln;
187 print ln > cfname;
188 } 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 $AWK '/ Not Before:/ { print $4,$3,$6; }'`
209 certisca=`openssl x509 -noout -text -in "$i" | \
210 $AWK 'BEGIN { ca=0; }
211 /CA:FALSE/ { ca=0; } /CA:TRUE/ { ca=1; }
212 END {print ca;}'`
213
214 if [ "$certcn" = "$issuercn" -o "$issuercn" = "AddTrust External CA Root" -o "$issuercn" = "AAA Certificate Services" ]
215 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 -passin env:NPW -inkey "$tempdir/key-$credbase.pem" \
284 -certfile "$destdir/chain-$credbase.pem" \
285 -name "$friendlyname" -in "$pkcs12eec" \
286 -passout env:NPW -out "$destdir/package-$credbase.p12"
287
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 -key "$destdir/key-$certfn.pem" -passin env:NPW \
348 -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 echo -n " " ; ls -l1a "$destdir/cert-$certfn.pem"
357 echo -n " " ; ls -l1a "$destdir/chain-$certfn.pem"
358 [ -f "$destdir/request-$certfn.pem" ] && \
359 ( 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
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 ln -sfn "key-$certfn.pem" "$destdir/userkey.pem"
373 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 ln -sfn "cert-$certfn.pem" "$destdir/usercert.pem"
379 ;;
380 esac
381
382 #
383 #
384 # ############################################################################

Properties

Name Value
svn:executable *

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