xref: /titanic_44/usr/src/cmd/cmd-crypto/pktool/pktool.c (revision 99ebb4ca412cb0a19d77a3899a87c055b9c30fa8)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*99ebb4caSwyllys  * Common Development and Distribution License (the "License").
6*99ebb4caSwyllys  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*99ebb4caSwyllys  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate  * This file comprises the main driver for this tool.
307711facfSdinak  * Upon parsing the command verbs from user input, it
317711facfSdinak  * branches to the appropriate modules to perform the
327711facfSdinak  * requested task.
337c478bd9Sstevel@tonic-gate  */
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #include <stdio.h>
367c478bd9Sstevel@tonic-gate #include <string.h>
377c478bd9Sstevel@tonic-gate #include <ctype.h>
387c478bd9Sstevel@tonic-gate #include <malloc.h>
397c478bd9Sstevel@tonic-gate #include <libgen.h>
407c478bd9Sstevel@tonic-gate #include <errno.h>
417c478bd9Sstevel@tonic-gate #include <cryptoutil.h>
427c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
437c478bd9Sstevel@tonic-gate #include "common.h"
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate /*
467c478bd9Sstevel@tonic-gate  * The verbcmd construct allows genericizing information about a verb so
477c478bd9Sstevel@tonic-gate  * that it is easier to manipulate.  Makes parsing code easier to read,
487c478bd9Sstevel@tonic-gate  * fix, and extend with new verbs.
497c478bd9Sstevel@tonic-gate  */
507c478bd9Sstevel@tonic-gate typedef struct verbcmd_s {
517c478bd9Sstevel@tonic-gate 	char	*verb;
527c478bd9Sstevel@tonic-gate 	int	(*action)(int, char *[]);
537711facfSdinak 	int	mode;
547711facfSdinak 	char	*synopsis;
557c478bd9Sstevel@tonic-gate } verbcmd;
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate /* External declarations for supported verb actions. */
587c478bd9Sstevel@tonic-gate extern int	pk_setpin(int argc, char *argv[]);
597711facfSdinak extern int	pk_list(int argc, char *argv[]);
607711facfSdinak extern int	pk_delete(int argc, char *argv[]);
617711facfSdinak extern int	pk_import(int argc, char *argv[]);
627711facfSdinak extern int	pk_export(int argc, char *argv[]);
637711facfSdinak extern int	pk_tokens(int argc, char *argv[]);
64*99ebb4caSwyllys extern int	pk_gencert(int argc, char *argv[]);
65*99ebb4caSwyllys extern int	pk_gencsr(int argc, char *argv[]);
66*99ebb4caSwyllys extern int	pk_download(int argc, char *argv[]);
67*99ebb4caSwyllys extern int	pk_genkey(int argc, char *argv[]);
687711facfSdinak 
697711facfSdinak /* Forward declarations for "built-in" verb actions. */
707711facfSdinak static int	pk_help(int argc, char *argv[]);
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate /* Command structure for verbs and their actions.  Do NOT i18n/l10n. */
737c478bd9Sstevel@tonic-gate static verbcmd	cmds[] = {
747711facfSdinak 	{ "tokens",	pk_tokens,	0,	"tokens" },
7549e21299Sdinak 	{ "setpin",	pk_setpin,	0,
76*99ebb4caSwyllys 		"setpin [ keystore=pkcs11 ]\n\t\t"
77*99ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t"
78*99ebb4caSwyllys 
79*99ebb4caSwyllys 		"setpin keystore=nss\n\t\t"
80*99ebb4caSwyllys 		"[ token=token ]\n\t\t"
81*99ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
82*99ebb4caSwyllys 		"[ prefix=DBprefix ]\n\t"
83*99ebb4caSwyllys 	},
8449e21299Sdinak 	{ "list",	pk_list,	0,
85*99ebb4caSwyllys 
86*99ebb4caSwyllys 	"list [ token=token[:manuf[:serial]]]\n\t\t"
87*99ebb4caSwyllys 		"[ objtype=private|public|both ]\n\t\t"
88*99ebb4caSwyllys 		"[ label=label ]\n\t"
89*99ebb4caSwyllys 
90*99ebb4caSwyllys 	"list objtype=cert[:[public | private | both ]]\n\t\t"
91*99ebb4caSwyllys 		"[ subject=subject-DN ]\n\t\t"
92*99ebb4caSwyllys 		"[ keystore=pkcs11 ]\n\t\t"
93*99ebb4caSwyllys 		"[ issuer=issuer-DN ]\n\t\t"
94*99ebb4caSwyllys 		"[ serial=serial number]\n\t\t"
95*99ebb4caSwyllys 		"[ label=cert-label ]\n\t\t"
96*99ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
97*99ebb4caSwyllys 		"[ criteria=valid|expired|both ]\n\t"
98*99ebb4caSwyllys 
99*99ebb4caSwyllys 	"list objtype=key[:[public | private | both ]]\n\t\t"
100*99ebb4caSwyllys 		"[ keystore=pkcs11 ]\n\t\t"
101*99ebb4caSwyllys 		"[ subject=subject-DN ]\n\t\t"
102*99ebb4caSwyllys 		"[ label=key-label ]\n\t\t"
103*99ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t"
104*99ebb4caSwyllys 
105*99ebb4caSwyllys 	"list keystore=pkcs11 objtype=crl\n\t\t"
106*99ebb4caSwyllys 		"infile=crl-fn\n\t\t"
107*99ebb4caSwyllys 		"[ dir=directory-path ]\n\t"
108*99ebb4caSwyllys 
109*99ebb4caSwyllys 	"list keystore=nss objtype=cert\n\t\t"
110*99ebb4caSwyllys 		"[ subject=subject-DN ]\n\t\t"
111*99ebb4caSwyllys 		"[ issuer=issuer-DN ]\n\t\t"
112*99ebb4caSwyllys 		"[ serial=serial number]\n\t\t"
113*99ebb4caSwyllys 		"[ nickname=cert-nickname ]\n\t\t"
114*99ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
115*99ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
116*99ebb4caSwyllys 		"[ prefix=DBprefix ]\n\t\t"
117*99ebb4caSwyllys 		"[ criteria=valid|expired|both ]\n\t"
118*99ebb4caSwyllys 
119*99ebb4caSwyllys 	"list keystore=nss objtype=key\n\t\t"
120*99ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
121*99ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
122*99ebb4caSwyllys 		"[ prefix=DBprefix ]\n\t\t"
123*99ebb4caSwyllys 		"[ nickname=key-nickname ]\n\t"
124*99ebb4caSwyllys 
125*99ebb4caSwyllys 	"list keystore=file objtype=cert\n\t\t"
126*99ebb4caSwyllys 		"[ subject=subject-DN ]\n\t\t"
127*99ebb4caSwyllys 		"[ issuer=issuer-DN ]\n\t\t"
128*99ebb4caSwyllys 		"[ serial=serial number]\n\t\t"
129*99ebb4caSwyllys 		"[ infile=cert-fn ]\n\t\t"
130*99ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
131*99ebb4caSwyllys 		"[ criteria=valid|expired|both ]\n\t"
132*99ebb4caSwyllys 
133*99ebb4caSwyllys 	"list keystore=file objtype=key\n\t\t"
134*99ebb4caSwyllys 		"[ infile=key-fn ]\n\t\t"
135*99ebb4caSwyllys 		"[ dir=directory-path ]\n\t"
136*99ebb4caSwyllys 
137*99ebb4caSwyllys 	"list keystore=file objtype=crl\n\t\t"
138*99ebb4caSwyllys 		"infile=crl-fn\n\t\t"
139*99ebb4caSwyllys 		"[ dir=directory-path ]\n\t"
140*99ebb4caSwyllys 	},
141*99ebb4caSwyllys 
1427711facfSdinak 	{ "delete",	pk_delete,	0,
143*99ebb4caSwyllys 
144*99ebb4caSwyllys 	"delete [ token=token[:manuf[:serial]]]\n\t\t"
145*99ebb4caSwyllys 		"[ objtype=private|public|both ]\n\t\t"
146*99ebb4caSwyllys 		"[ label=object-label ]\n\t"
147*99ebb4caSwyllys 
148*99ebb4caSwyllys 	"delete keystore=nss objtype=cert\n\t\t"
149*99ebb4caSwyllys 		"[ subject=subject-DN ]\n\t\t"
150*99ebb4caSwyllys 		"[ issuer=issuer-DN ]\n\t\t"
151*99ebb4caSwyllys 		"[ serial=serial number]\n\t\t"
152*99ebb4caSwyllys 		"[ nickname=cert-nickname ]\n\t\t"
153*99ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
154*99ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
155*99ebb4caSwyllys 		"[ prefix=DBprefix ]\n\t\t"
156*99ebb4caSwyllys 		"[ criteria=valid|expired|both ]\n\t"
157*99ebb4caSwyllys 
158*99ebb4caSwyllys 	"delete keystore=nss objtype=key\n\t\t"
159*99ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
160*99ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
161*99ebb4caSwyllys 		"[ prefix=DBprefix ]\n\t\t"
162*99ebb4caSwyllys 		"[ nickname=key-nickname ]\n\t\t"
163*99ebb4caSwyllys 
164*99ebb4caSwyllys 	"delete keystore=nss objtype=crl\n\t\t"
165*99ebb4caSwyllys 		"[ nickname=issuer-nickname ]\n\t\t"
166*99ebb4caSwyllys 		"[ subject=subject-DN ]\n\t\t"
167*99ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
168*99ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
169*99ebb4caSwyllys 		"[ prefix=DBprefix ]\n\t"
170*99ebb4caSwyllys 
171*99ebb4caSwyllys 	"delete keystore=pkcs11 objtype=cert[:[public | private | both]]\n\t\t"
172*99ebb4caSwyllys 		"[ subject=subject-DN ]\n\t\t"
173*99ebb4caSwyllys 		"[ issuer=issuer-DN ]\n\t\t"
174*99ebb4caSwyllys 		"[ serial=serial number]\n\t\t"
175*99ebb4caSwyllys 		"[ label=cert-label ]\n\t\t"
176*99ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
177*99ebb4caSwyllys 		"[ criteria=valid|expired|both ]\n\t"
178*99ebb4caSwyllys 
179*99ebb4caSwyllys 	"delete keystore=pkcs11 objtype=key[:[public | private | both]]\n\t\t"
180*99ebb4caSwyllys 		"[ subject=subject-DN ]\n\t\t"
181*99ebb4caSwyllys 		"[ label=key-label ]\n\t\t"
182*99ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t"
183*99ebb4caSwyllys 
184*99ebb4caSwyllys 	"delete keystore=pkcs11 objtype=crl\n\t\t"
185*99ebb4caSwyllys 		"infile=crl-fn\n\t\t"
186*99ebb4caSwyllys 		"[ dir=directory-path ]\n\t"
187*99ebb4caSwyllys 
188*99ebb4caSwyllys 	"delete keystore=file objtype=cert\n\t\t"
189*99ebb4caSwyllys 		"[ subject=subject-DN ]\n\t\t"
190*99ebb4caSwyllys 		"[ issuer=issuer-DN ]\n\t\t"
191*99ebb4caSwyllys 		"[ serial=serial number]\n\t\t"
192*99ebb4caSwyllys 		"[ infile=cert-fn ]\n\t\t"
193*99ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
194*99ebb4caSwyllys 		"[ criteria=valid|expired|both ]\n\t"
195*99ebb4caSwyllys 
196*99ebb4caSwyllys 	"delete keystore=file objtype=key\n\t\t"
197*99ebb4caSwyllys 		"[ infile=key-fn ]\n\t\t"
198*99ebb4caSwyllys 		"[ dir=directory-path ]\n\t"
199*99ebb4caSwyllys 
200*99ebb4caSwyllys 	"delete keystore=file objtype=crl\n\t\t"
201*99ebb4caSwyllys 		"infile=crl-fn\n\t\t"
202*99ebb4caSwyllys 		"[ dir=directory-path ]\n\t"
203*99ebb4caSwyllys 	},
20449e21299Sdinak 	{ "import",	pk_import,	0,
205*99ebb4caSwyllys 
206*99ebb4caSwyllys 	"import [token=token[:manuf[:serial]]]\n\t\t"
207*99ebb4caSwyllys 	"infile=input-fn\n\t"
208*99ebb4caSwyllys 
209*99ebb4caSwyllys 	"import keystore=nss objtype=cert\n\t\t"
210*99ebb4caSwyllys 		"infile=input-fn\n\t\t"
211*99ebb4caSwyllys 		"nickname=cert-nickname\n\t\t"
212*99ebb4caSwyllys 		"[ trust=trust-value ]\n\t\t"
213*99ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
214*99ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
215*99ebb4caSwyllys 		"[ prefix=DBprefix ]\n\t"
216*99ebb4caSwyllys 
217*99ebb4caSwyllys 	"import keystore=nss objtype=crl\n\t\t"
218*99ebb4caSwyllys 		"infile=input-fn\n\t\t"
219*99ebb4caSwyllys 		"[ verifycrl=y|n ]\n\t\t"
220*99ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
221*99ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
222*99ebb4caSwyllys 		"[ prefix=DBprefix ]\n\t"
223*99ebb4caSwyllys 
224*99ebb4caSwyllys 	"import keystore=pkcs11\n\t\t"
225*99ebb4caSwyllys 		"infile=input-fn\n\t\t"
226*99ebb4caSwyllys 		"label=cert-label\n\t\t"
227*99ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t"
228*99ebb4caSwyllys 
229*99ebb4caSwyllys 	"import keystore=pkcs11 objtype=crl\n\t\t"
230*99ebb4caSwyllys 		"infile=input-crl-fn\n\t\t"
231*99ebb4caSwyllys 		"outcrl=output-crl-fn\n\t\t"
232*99ebb4caSwyllys 		"outformat=pem|der\n\t\t"
233*99ebb4caSwyllys 		"[ dir=output-crl-directory-path ]\n\t"
234*99ebb4caSwyllys 
235*99ebb4caSwyllys 	"import keystore=file\n\t\t"
236*99ebb4caSwyllys 		"infile=input-fn\n\t\t"
237*99ebb4caSwyllys 		"outkey=output-key-fn\n\t\t"
238*99ebb4caSwyllys 		"outcert=output-cert-fn\n\t\t"
239*99ebb4caSwyllys 		"[ dir=output-cert-dir-path ]\n\t\t"
240*99ebb4caSwyllys 		"[ keydir=output-key-dir-path ]\n\t\t"
241*99ebb4caSwyllys 		"[ outformat=pem|der|pkcs12 ]\n\t"
242*99ebb4caSwyllys 
243*99ebb4caSwyllys 	"import keystore=file objtype=crl\n\t\t"
244*99ebb4caSwyllys 		"infile=input-crl-fn\n\t\t"
245*99ebb4caSwyllys 		"outcrl=output-crl-fn\n\t\t"
246*99ebb4caSwyllys 		"outformat=pem|der\n\t\t"
247*99ebb4caSwyllys 		"[ dir=output-crl-directory-path ]\n\t"
248*99ebb4caSwyllys 	},
249*99ebb4caSwyllys 
25049e21299Sdinak 	{ "export",	pk_export,	0,
251*99ebb4caSwyllys 
252*99ebb4caSwyllys 	"export [token=token[:manuf[:serial]]]\n\t\t"
253*99ebb4caSwyllys 	"outfile=output-fn\n\t"
254*99ebb4caSwyllys 
255*99ebb4caSwyllys 	"export keystore=nss\n\t\t"
256*99ebb4caSwyllys 		"outfile=output-fn\n\t\t"
257*99ebb4caSwyllys 		"[ objtype=cert|key ]\n\t\t"
258*99ebb4caSwyllys 		"[ subject=subject-DN ]\n\t\t"
259*99ebb4caSwyllys 		"[ issuer=issuer-DN ]\n\t\t"
260*99ebb4caSwyllys 		"[ serial=serial number]\n\t\t"
261*99ebb4caSwyllys 		"[ nickname=cert-nickname]\n\t\t"
262*99ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
263*99ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
264*99ebb4caSwyllys 		"[ prefix=DBPrefix ]\n\t\t"
265*99ebb4caSwyllys 		"[ outformat=pem|der|pkcs12 ]\n\t"
266*99ebb4caSwyllys 
267*99ebb4caSwyllys 	"export keystore=pkcs11\n\t\t"
268*99ebb4caSwyllys 		"outfile=output-fn\n\t\t"
269*99ebb4caSwyllys 		"[ label=cert-label]\n\t\t"
270*99ebb4caSwyllys 		"[ subject=subject-DN ]\n\t\t"
271*99ebb4caSwyllys 		"[ issuer=issuer-DN ]\n\t\t"
272*99ebb4caSwyllys 		"[ serial=serial number]\n\t\t"
273*99ebb4caSwyllys 		"[ outformat=pem|der|pkcs12]\n\t\t"
274*99ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t"
275*99ebb4caSwyllys 
276*99ebb4caSwyllys 	"export keystore=file\n\t\t"
277*99ebb4caSwyllys 		"certfile=cert-input-fn\n\t\t"
278*99ebb4caSwyllys 		"keyfile=key-input-fn\n\t\t"
279*99ebb4caSwyllys 		"outfile=output-pkcs12-fn\n\t\t"
280*99ebb4caSwyllys 		"[ dir=directory-path ]\n\t"
281*99ebb4caSwyllys 	},
282*99ebb4caSwyllys 
283*99ebb4caSwyllys 	{ "gencert",	pk_gencert,	0,
284*99ebb4caSwyllys 	"gencert [-i] keystore=nss\n\t\t"
285*99ebb4caSwyllys 		"label=cert-nickname\n\t\t"
286*99ebb4caSwyllys 		"serial=serial number hex string]\n\t\t"
287*99ebb4caSwyllys 		"subject=subject-DN\n\t\t"
288*99ebb4caSwyllys 		"[ altname=[critical:]SubjectAltName ]\n\t\t"
289*99ebb4caSwyllys 		"[ keyusage=[critical:]usage,usage,...]\n\t\t"
290*99ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
291*99ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
292*99ebb4caSwyllys 		"[ prefix=DBprefix ]\n\t\t"
293*99ebb4caSwyllys 		"[ keytype=rsa|dsa ]\n\t\t"
294*99ebb4caSwyllys 		"[ keylen=key-size ]\n\t\t"
295*99ebb4caSwyllys 		"[ trust=trust-value ]\n\t\t"
296*99ebb4caSwyllys 		"[ lifetime=number-hour|number-day|number-year ]\n\t"
297*99ebb4caSwyllys 
298*99ebb4caSwyllys 	"gencert [-i] [ keystore=pkcs11 ]\n\t\t"
299*99ebb4caSwyllys 		"label=key/cert-label\n\t\t"
300*99ebb4caSwyllys 		"subject=subject-DN\n\t\t"
301*99ebb4caSwyllys 		"serial=serial number hex string\n\t\t"
302*99ebb4caSwyllys 		"[ altname=[critical:]SubjectAltName ]\n\t\t"
303*99ebb4caSwyllys 		"[ keyusage=[critical:]usage,usage,...]\n\t\t"
304*99ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
305*99ebb4caSwyllys 		"[ keytype=rsa|dsa ]\n\t\t"
306*99ebb4caSwyllys 		"[ keylen=key-size ]\n\t\t"
307*99ebb4caSwyllys 		"[ lifetime=number-hour|number-day|number-year ]\n\t"
308*99ebb4caSwyllys 
309*99ebb4caSwyllys 	"gencert [-i] keystore=file\n\t\t"
310*99ebb4caSwyllys 		"outcert=cert_filename\n\t\t"
311*99ebb4caSwyllys 		"outkey=key_filename\n\t\t"
312*99ebb4caSwyllys 		"subject=subject-DN\n\t\t"
313*99ebb4caSwyllys 		"serial=serial number hex string\n\t\t"
314*99ebb4caSwyllys 		"[ altname=[critical:]SubjectAltName ]\n\t\t"
315*99ebb4caSwyllys 		"[ keyusage=[critical:]usage,usage,...]\n\t\t"
316*99ebb4caSwyllys 		"[ format=der|pem ]\n\t\t"
317*99ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
318*99ebb4caSwyllys 		"[ prefix=DBprefix ]\n\t\t"
319*99ebb4caSwyllys 		"[ keytype=rsa|dsa ]\n\t\t"
320*99ebb4caSwyllys 		"[ keylen=key-size ]\n\t\t"
321*99ebb4caSwyllys 		"[ lifetime=number-hour|number-day|number-year ]\n\t"
322*99ebb4caSwyllys 	},
323*99ebb4caSwyllys 	{ "gencsr",	pk_gencsr,	0,
324*99ebb4caSwyllys 	"gencsr [-i] keystore=nss \n\t\t"
325*99ebb4caSwyllys 		"nickname=cert-nickname\n\t\t"
326*99ebb4caSwyllys 		"outcsr=csr-fn\n\t\t"
327*99ebb4caSwyllys 		"subject=subject-DN\n\t\t"
328*99ebb4caSwyllys 		"[ altname=[critical:]SubjectAltName ]\n\t\t"
329*99ebb4caSwyllys 		"[ keyusage=[critical:]usage,usage,...]\n\t\t"
330*99ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
331*99ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
332*99ebb4caSwyllys 		"[ prefix=DBprefix ]\n\t\t"
333*99ebb4caSwyllys 		"[ keytype=rsa|dsa ]\n\t\t"
334*99ebb4caSwyllys 		"[ keylen=key-size ]\n\t\t"
335*99ebb4caSwyllys 		"[ format=pem|der]\n\t"
336*99ebb4caSwyllys 	"gencsr [-i] [ keystore=pkcs11 ]\n\t\t"
337*99ebb4caSwyllys 		"label=key-label\n\t\t"
338*99ebb4caSwyllys 		"outcsr=csr-fn\n\t\t"
339*99ebb4caSwyllys 		"subject=subject-DN\n\t\t"
340*99ebb4caSwyllys 		"[ altname=[critical:]SubjectAltName ]\n\t\t"
341*99ebb4caSwyllys 		"[ keyusage=[critical:]usage,usage,...]\n\t\t"
342*99ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
343*99ebb4caSwyllys 		"[ keytype=rsa|dsa ]\n\t\t"
344*99ebb4caSwyllys 		"[ keylen=key-size ]\n\t\t"
345*99ebb4caSwyllys 		"[ format=pem|der]\n\t"
346*99ebb4caSwyllys 	"gencsr [-i] keystore=file\n\t\t"
347*99ebb4caSwyllys 		"outcsr=csr-fn\n\t\t"
348*99ebb4caSwyllys 		"outkey=key-fn\n\t\t"
349*99ebb4caSwyllys 		"subject=subject-DN\n\t\t"
350*99ebb4caSwyllys 		"[ altname=[critical:]SubjectAltName ]\n\t\t"
351*99ebb4caSwyllys 		"[ keyusage=[critical:]usage,usage,...]\n\t\t"
352*99ebb4caSwyllys 		"[ keytype=rsa|dsa ]\n\t\t"
353*99ebb4caSwyllys 		"[ keylen=key-size ]\n\t\t"
354*99ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
355*99ebb4caSwyllys 		"[ format=pem|der]\n\t"
356*99ebb4caSwyllys 	},
357*99ebb4caSwyllys 
358*99ebb4caSwyllys 	{ "download",	pk_download,	0,
359*99ebb4caSwyllys 	"download url=url_str\n\t\t"
360*99ebb4caSwyllys 		"[ objtype=crl|cert ]\n\t\t"
361*99ebb4caSwyllys 		"[ http_proxy=proxy_str ]\n\t\t"
362*99ebb4caSwyllys 		"[ outfile = outfile ]\n\t\t"
363*99ebb4caSwyllys 	},
364*99ebb4caSwyllys 
365*99ebb4caSwyllys 	{ "genkey",	pk_genkey,	0,
366*99ebb4caSwyllys 	"genkey [ keystore=pkcs11 ]\n\t\t"
367*99ebb4caSwyllys 		"label=key-label\n\t\t"
368*99ebb4caSwyllys 		"[ keytype=aes|arcfour|des|3des ]\n\t\t"
369*99ebb4caSwyllys 		"[ keylen=key-size (AES or ARCFOUR only)]\n\t\t"
370*99ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
371*99ebb4caSwyllys 		"[ sensitive=y|n ]\n\t\t"
372*99ebb4caSwyllys 		"[ extractable=y|n ]\n\t\t"
373*99ebb4caSwyllys 		"[ print=y|n ]\n\t"
374*99ebb4caSwyllys 
375*99ebb4caSwyllys 	"genkey keystore=nss\n\t\t"
376*99ebb4caSwyllys 		"label=key-label\n\t\t"
377*99ebb4caSwyllys 		"[ keytype=aes|arcfour|des|3des ]\n\t\t"
378*99ebb4caSwyllys 		"[ keylen=key-size (AES or ARCFOUR only)]\n\t\t"
379*99ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
380*99ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
381*99ebb4caSwyllys 		"[ prefix=DBprefix ]\n\t"
382*99ebb4caSwyllys 
383*99ebb4caSwyllys 	"genkey keystore=file\n\t\t"
384*99ebb4caSwyllys 		"outkey=key-fn\n\t\t"
385*99ebb4caSwyllys 		"[ keytype=aes|arcfour|des|3des ]\n\t\t"
386*99ebb4caSwyllys 		"[ keylen=key-size (AES or ARCFOUR only)]\n\t\t"
387*99ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
388*99ebb4caSwyllys 		"[ print=y|n ]\n\t"
389*99ebb4caSwyllys 	},
390*99ebb4caSwyllys 
39149e21299Sdinak 	{ "-?",	pk_help,	0,	"help\t(help and usage)" },
392*99ebb4caSwyllys 	{ "-f",	pk_help,	0,	"-f option_file" }
3937c478bd9Sstevel@tonic-gate };
3947c478bd9Sstevel@tonic-gate static int	num_cmds = sizeof (cmds) / sizeof (verbcmd);
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate static char	*prog;
397*99ebb4caSwyllys static void	usage(int);
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate /*
4007c478bd9Sstevel@tonic-gate  * Usage information.  This function must be updated when new verbs or
4017c478bd9Sstevel@tonic-gate  * options are added.
4027c478bd9Sstevel@tonic-gate  */
4037c478bd9Sstevel@tonic-gate static void
404*99ebb4caSwyllys usage(int idx)
4057c478bd9Sstevel@tonic-gate {
4067711facfSdinak 	int	i;
4077711facfSdinak 
4087711facfSdinak 	/* Display this block only in command-line mode. */
4097711facfSdinak 	(void) fprintf(stdout, gettext("Usage:\n"));
4107711facfSdinak 	(void) fprintf(stdout, gettext("\t%s -?\t(help and usage)\n"), prog);
411*99ebb4caSwyllys 	(void) fprintf(stdout, gettext("\t%s -f option_file\n"), prog);
4127711facfSdinak 	(void) fprintf(stdout, gettext("\t%s subcommand [options...]\n"), prog);
4137711facfSdinak 	(void) fprintf(stdout, gettext("where subcommands may be:\n"));
4147711facfSdinak 
4157711facfSdinak 	/* Display only those verbs that match the current tool mode. */
416*99ebb4caSwyllys 	if (idx == -1) {
4177711facfSdinak 		for (i = 0; i < num_cmds; i++) {
4187711facfSdinak 			/* Do NOT i18n/l10n. */
4197711facfSdinak 			(void) fprintf(stdout, "\t%s\n", cmds[i].synopsis);
4207711facfSdinak 		}
421*99ebb4caSwyllys 	} else {
422*99ebb4caSwyllys 		(void) fprintf(stdout, "\t%s\n", cmds[idx].synopsis);
423*99ebb4caSwyllys 	}
4247711facfSdinak }
4257711facfSdinak 
4267711facfSdinak /*
4277711facfSdinak  * Provide help, in the form of displaying the usage.
4287711facfSdinak  */
4297711facfSdinak static int
4307711facfSdinak pk_help(int argc, char *argv[])
4317711facfSdinak /* ARGSUSED */
4327711facfSdinak {
433*99ebb4caSwyllys 	usage(-1);
434*99ebb4caSwyllys 	return (0);
435*99ebb4caSwyllys }
4367711facfSdinak 
437*99ebb4caSwyllys /*
438*99ebb4caSwyllys  * Process arguments from the argfile and create a new
439*99ebb4caSwyllys  * argv/argc list to be processed later.
440*99ebb4caSwyllys  */
441*99ebb4caSwyllys static int
442*99ebb4caSwyllys process_arg_file(char *argfile, char ***argv, int *argc)
443*99ebb4caSwyllys {
444*99ebb4caSwyllys 	FILE *fp;
445*99ebb4caSwyllys 	char argline[2 * BUFSIZ]; /* 2048 bytes should be plenty */
446*99ebb4caSwyllys 	char *p;
447*99ebb4caSwyllys 	int nargs = 0;
448*99ebb4caSwyllys 
449*99ebb4caSwyllys 	if ((fp = fopen(argfile, "rF")) == NULL) {
450*99ebb4caSwyllys 		(void) fprintf(stderr,
451*99ebb4caSwyllys 			gettext("Cannot read argfile %s: %s\n"),
452*99ebb4caSwyllys 			argfile, strerror(errno));
453*99ebb4caSwyllys 		return (errno);
454*99ebb4caSwyllys 	}
455*99ebb4caSwyllys 
456*99ebb4caSwyllys 	while (fgets(argline, sizeof (argline), fp) != NULL) {
457*99ebb4caSwyllys 		int j;
458*99ebb4caSwyllys 		/* remove trailing whitespace */
459*99ebb4caSwyllys 		j = strlen(argline) - 1;
460*99ebb4caSwyllys 		while (j >= 0 && isspace(argline[j])) {
461*99ebb4caSwyllys 			argline[j] = 0;
462*99ebb4caSwyllys 			j--;
463*99ebb4caSwyllys 		}
464*99ebb4caSwyllys 		/* If it was a blank line, get the next one. */
465*99ebb4caSwyllys 		if (!strlen(argline))
466*99ebb4caSwyllys 			continue;
467*99ebb4caSwyllys 
468*99ebb4caSwyllys 		(*argv) = realloc((*argv),
469*99ebb4caSwyllys 			(nargs + 1) * sizeof (char *));
470*99ebb4caSwyllys 		if ((*argv) == NULL) {
471*99ebb4caSwyllys 			perror("memory error");
472*99ebb4caSwyllys 			(void) fclose(fp);
473*99ebb4caSwyllys 			return (errno);
474*99ebb4caSwyllys 		}
475*99ebb4caSwyllys 		p = (char *)strdup(argline);
476*99ebb4caSwyllys 		if (p == NULL) {
477*99ebb4caSwyllys 			perror("memory error");
478*99ebb4caSwyllys 			(void) fclose(fp);
479*99ebb4caSwyllys 			return (errno);
480*99ebb4caSwyllys 		}
481*99ebb4caSwyllys 		(*argv)[nargs] = p;
482*99ebb4caSwyllys 		nargs++;
483*99ebb4caSwyllys 	}
484*99ebb4caSwyllys 	*argc = nargs;
485*99ebb4caSwyllys 	(void) fclose(fp);
4867711facfSdinak 	return (0);
4877c478bd9Sstevel@tonic-gate }
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate /*
4907c478bd9Sstevel@tonic-gate  * MAIN() -- where all the action is
4917c478bd9Sstevel@tonic-gate  */
4927c478bd9Sstevel@tonic-gate int
4937c478bd9Sstevel@tonic-gate main(int argc, char *argv[], char *envp[])
4947c478bd9Sstevel@tonic-gate /* ARGSUSED2 */
4957c478bd9Sstevel@tonic-gate {
4967c478bd9Sstevel@tonic-gate 	int	i, found = -1;
4977c478bd9Sstevel@tonic-gate 	int	rv;
4987c478bd9Sstevel@tonic-gate 	int	pk_argc = 0;
4997c478bd9Sstevel@tonic-gate 	char	**pk_argv = NULL;
5007711facfSdinak 	int	save_errno = 0;
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 	/* Set up for i18n/l10n. */
5037c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
5047c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)		/* Should be defined by cc -D. */
5057c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it isn't. */
5067c478bd9Sstevel@tonic-gate #endif
5077c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate 	/* Get program base name and move pointer over 0th arg. */
5107c478bd9Sstevel@tonic-gate 	prog = basename(argv[0]);
5117c478bd9Sstevel@tonic-gate 	argv++, argc--;
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate 	/* Set up for debug and error output. */
5147c478bd9Sstevel@tonic-gate 	if (argc == 0) {
515*99ebb4caSwyllys 		usage(-1);
5167c478bd9Sstevel@tonic-gate 		return (1);
5177c478bd9Sstevel@tonic-gate 	}
5187c478bd9Sstevel@tonic-gate 
5197711facfSdinak 	/* Check for help options.  For CLIP-compliance. */
520*99ebb4caSwyllys 	if (strcmp(argv[0], "-?") == 0) {
5217711facfSdinak 		return (pk_help(argc, argv));
522*99ebb4caSwyllys 	} else if (strcmp(argv[0], "-f") == 0 && argc == 2) {
523*99ebb4caSwyllys 		rv = process_arg_file(argv[1], &pk_argv, &pk_argc);
524*99ebb4caSwyllys 		if (rv)
525*99ebb4caSwyllys 			return (rv);
526*99ebb4caSwyllys 	} else if (argc >= 1 && argv[0][0] == '-') {
527*99ebb4caSwyllys 		usage(-1);
5287711facfSdinak 		return (1);
5297711facfSdinak 	}
5307711facfSdinak 
5317711facfSdinak 	/* Always turns off Metaslot so that we can see softtoken. */
5327c478bd9Sstevel@tonic-gate 	if (setenv("METASLOT_ENABLED", "false", 1) < 0) {
5337711facfSdinak 		save_errno = errno;
5347c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
5357711facfSdinak 		    gettext("Disabling Metaslot failed (%s)."),
5367711facfSdinak 		    strerror(save_errno));
5377c478bd9Sstevel@tonic-gate 		return (1);
5387c478bd9Sstevel@tonic-gate 	}
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 	/* Begin parsing command line. */
541*99ebb4caSwyllys 	if (pk_argc == 0 && pk_argv == NULL) {
5427c478bd9Sstevel@tonic-gate 		pk_argc = argc;
5437c478bd9Sstevel@tonic-gate 		pk_argv = argv;
544*99ebb4caSwyllys 	}
5457c478bd9Sstevel@tonic-gate 
5467711facfSdinak 	/* Check for valid verb (or an abbreviation of it). */
5477c478bd9Sstevel@tonic-gate 	found = -1;
5487c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_cmds; i++) {
5497c478bd9Sstevel@tonic-gate 		if (strcmp(cmds[i].verb, pk_argv[0]) == 0) {
5507c478bd9Sstevel@tonic-gate 			if (found < 0) {
5517c478bd9Sstevel@tonic-gate 				found = i;
5527c478bd9Sstevel@tonic-gate 				break;
5537c478bd9Sstevel@tonic-gate 			}
5547c478bd9Sstevel@tonic-gate 		}
5557c478bd9Sstevel@tonic-gate 	}
5567c478bd9Sstevel@tonic-gate 	/* Stop here if no valid verb found. */
5577c478bd9Sstevel@tonic-gate 	if (found < 0) {
5587711facfSdinak 		cryptoerror(LOG_STDERR, gettext("Invalid verb: %s"),
5597711facfSdinak 		    pk_argv[0]);
5607c478bd9Sstevel@tonic-gate 		return (1);
5617c478bd9Sstevel@tonic-gate 	}
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 	/* Get to work! */
5647c478bd9Sstevel@tonic-gate 	rv = (*cmds[found].action)(pk_argc, pk_argv);
5657c478bd9Sstevel@tonic-gate 	switch (rv) {
5667c478bd9Sstevel@tonic-gate 	case PK_ERR_NONE:
5677c478bd9Sstevel@tonic-gate 		break;		/* Command succeeded, do nothing. */
5687c478bd9Sstevel@tonic-gate 	case PK_ERR_USAGE:
569*99ebb4caSwyllys 		usage(found);
5707c478bd9Sstevel@tonic-gate 		break;
5717c478bd9Sstevel@tonic-gate 	case PK_ERR_QUIT:
5727c478bd9Sstevel@tonic-gate 		exit(0);
5737c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
5747711facfSdinak 	case PK_ERR_PK11:
5757711facfSdinak 	case PK_ERR_SYSTEM:
5767711facfSdinak 	case PK_ERR_OPENSSL:
577*99ebb4caSwyllys 	case PK_ERR_NSS:
5787c478bd9Sstevel@tonic-gate 	default:
5797c478bd9Sstevel@tonic-gate 		break;
5807c478bd9Sstevel@tonic-gate 	}
5817c478bd9Sstevel@tonic-gate 	return (rv);
5827c478bd9Sstevel@tonic-gate }
583