xref: /titanic_50/usr/src/cmd/cmd-crypto/pktool/pktool.c (revision 985be8f145003c39bf82ad09a81ad394e4d7d4b6)
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
599ebb4caSwyllys  * Common Development and Distribution License (the "License").
699ebb4caSwyllys  * 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*985be8f1Swyllys  * Copyright 2007 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;
54*985be8f1Swyllys 	char	*summary;
557711facfSdinak 	char	*synopsis;
567c478bd9Sstevel@tonic-gate } verbcmd;
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate /* External declarations for supported verb actions. */
597c478bd9Sstevel@tonic-gate extern int	pk_setpin(int argc, char *argv[]);
607711facfSdinak extern int	pk_list(int argc, char *argv[]);
617711facfSdinak extern int	pk_delete(int argc, char *argv[]);
627711facfSdinak extern int	pk_import(int argc, char *argv[]);
637711facfSdinak extern int	pk_export(int argc, char *argv[]);
647711facfSdinak extern int	pk_tokens(int argc, char *argv[]);
6599ebb4caSwyllys extern int	pk_gencert(int argc, char *argv[]);
6699ebb4caSwyllys extern int	pk_gencsr(int argc, char *argv[]);
6799ebb4caSwyllys extern int	pk_download(int argc, char *argv[]);
6899ebb4caSwyllys extern int	pk_genkey(int argc, char *argv[]);
697711facfSdinak 
707711facfSdinak /* Forward declarations for "built-in" verb actions. */
717711facfSdinak static int	pk_help(int argc, char *argv[]);
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate /* Command structure for verbs and their actions.  Do NOT i18n/l10n. */
747c478bd9Sstevel@tonic-gate static verbcmd	cmds[] = {
75*985be8f1Swyllys 	{ "tokens",	pk_tokens,	0,
76*985be8f1Swyllys 		"lists all visible PKCS#11 tokens", "tokens" },
7749e21299Sdinak 	{ "setpin",	pk_setpin,	0,
78*985be8f1Swyllys 		"changes user authentication passphrase for keystore access",
7999ebb4caSwyllys 		"setpin [ keystore=pkcs11 ]\n\t\t"
8099ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t"
8199ebb4caSwyllys 
8299ebb4caSwyllys 		"setpin keystore=nss\n\t\t"
8399ebb4caSwyllys 		"[ token=token ]\n\t\t"
8499ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
8599ebb4caSwyllys 		"[ prefix=DBprefix ]\n\t"
8699ebb4caSwyllys 	},
8749e21299Sdinak 	{ "list",	pk_list,	0,
88*985be8f1Swyllys 		"lists a summary of objects in the keystore",
8999ebb4caSwyllys 	"list [ token=token[:manuf[:serial]]]\n\t\t"
9099ebb4caSwyllys 		"[ objtype=private|public|both ]\n\t\t"
9199ebb4caSwyllys 		"[ label=label ]\n\t"
9299ebb4caSwyllys 
9399ebb4caSwyllys 	"list objtype=cert[:[public | private | both ]]\n\t\t"
9499ebb4caSwyllys 		"[ subject=subject-DN ]\n\t\t"
9599ebb4caSwyllys 		"[ keystore=pkcs11 ]\n\t\t"
9699ebb4caSwyllys 		"[ issuer=issuer-DN ]\n\t\t"
9799ebb4caSwyllys 		"[ serial=serial number]\n\t\t"
9899ebb4caSwyllys 		"[ label=cert-label ]\n\t\t"
9999ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
10099ebb4caSwyllys 		"[ criteria=valid|expired|both ]\n\t"
10199ebb4caSwyllys 
10299ebb4caSwyllys 	"list objtype=key[:[public | private | both ]]\n\t\t"
10399ebb4caSwyllys 		"[ keystore=pkcs11 ]\n\t\t"
10499ebb4caSwyllys 		"[ subject=subject-DN ]\n\t\t"
10599ebb4caSwyllys 		"[ label=key-label ]\n\t\t"
10699ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t"
10799ebb4caSwyllys 
10899ebb4caSwyllys 	"list keystore=pkcs11 objtype=crl\n\t\t"
10999ebb4caSwyllys 		"infile=crl-fn\n\t\t"
11099ebb4caSwyllys 		"[ dir=directory-path ]\n\t"
11199ebb4caSwyllys 
11299ebb4caSwyllys 	"list keystore=nss objtype=cert\n\t\t"
11399ebb4caSwyllys 		"[ subject=subject-DN ]\n\t\t"
11499ebb4caSwyllys 		"[ issuer=issuer-DN ]\n\t\t"
11599ebb4caSwyllys 		"[ serial=serial number]\n\t\t"
11699ebb4caSwyllys 		"[ nickname=cert-nickname ]\n\t\t"
11799ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
11899ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
11999ebb4caSwyllys 		"[ prefix=DBprefix ]\n\t\t"
12099ebb4caSwyllys 		"[ criteria=valid|expired|both ]\n\t"
12199ebb4caSwyllys 
12299ebb4caSwyllys 	"list keystore=nss objtype=key\n\t\t"
12399ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
12499ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
12599ebb4caSwyllys 		"[ prefix=DBprefix ]\n\t\t"
12699ebb4caSwyllys 		"[ nickname=key-nickname ]\n\t"
12799ebb4caSwyllys 
12899ebb4caSwyllys 	"list keystore=file objtype=cert\n\t\t"
12999ebb4caSwyllys 		"[ subject=subject-DN ]\n\t\t"
13099ebb4caSwyllys 		"[ issuer=issuer-DN ]\n\t\t"
13199ebb4caSwyllys 		"[ serial=serial number]\n\t\t"
13299ebb4caSwyllys 		"[ infile=cert-fn ]\n\t\t"
13399ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
13499ebb4caSwyllys 		"[ criteria=valid|expired|both ]\n\t"
13599ebb4caSwyllys 
13699ebb4caSwyllys 	"list keystore=file objtype=key\n\t\t"
13799ebb4caSwyllys 		"[ infile=key-fn ]\n\t\t"
13899ebb4caSwyllys 		"[ dir=directory-path ]\n\t"
13999ebb4caSwyllys 
14099ebb4caSwyllys 	"list keystore=file objtype=crl\n\t\t"
14199ebb4caSwyllys 		"infile=crl-fn\n\t\t"
14299ebb4caSwyllys 		"[ dir=directory-path ]\n\t"
14399ebb4caSwyllys 	},
14499ebb4caSwyllys 
1457711facfSdinak 	{ "delete",	pk_delete,	0,
146*985be8f1Swyllys 		"deletes objects in the keystore",
14799ebb4caSwyllys 
14899ebb4caSwyllys 	"delete [ token=token[:manuf[:serial]]]\n\t\t"
14999ebb4caSwyllys 		"[ objtype=private|public|both ]\n\t\t"
15099ebb4caSwyllys 		"[ label=object-label ]\n\t"
15199ebb4caSwyllys 
15299ebb4caSwyllys 	"delete keystore=nss objtype=cert\n\t\t"
15399ebb4caSwyllys 		"[ subject=subject-DN ]\n\t\t"
15499ebb4caSwyllys 		"[ issuer=issuer-DN ]\n\t\t"
15599ebb4caSwyllys 		"[ serial=serial number]\n\t\t"
15699ebb4caSwyllys 		"[ nickname=cert-nickname ]\n\t\t"
15799ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
15899ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
15999ebb4caSwyllys 		"[ prefix=DBprefix ]\n\t\t"
16099ebb4caSwyllys 		"[ criteria=valid|expired|both ]\n\t"
16199ebb4caSwyllys 
16299ebb4caSwyllys 	"delete keystore=nss objtype=key\n\t\t"
16399ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
16499ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
16599ebb4caSwyllys 		"[ prefix=DBprefix ]\n\t\t"
16699ebb4caSwyllys 		"[ nickname=key-nickname ]\n\t\t"
16799ebb4caSwyllys 
16899ebb4caSwyllys 	"delete keystore=nss objtype=crl\n\t\t"
16999ebb4caSwyllys 		"[ nickname=issuer-nickname ]\n\t\t"
17099ebb4caSwyllys 		"[ subject=subject-DN ]\n\t\t"
17199ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
17299ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
17399ebb4caSwyllys 		"[ prefix=DBprefix ]\n\t"
17499ebb4caSwyllys 
17599ebb4caSwyllys 	"delete keystore=pkcs11 objtype=cert[:[public | private | both]]\n\t\t"
17699ebb4caSwyllys 		"[ subject=subject-DN ]\n\t\t"
17799ebb4caSwyllys 		"[ issuer=issuer-DN ]\n\t\t"
17899ebb4caSwyllys 		"[ serial=serial number]\n\t\t"
17999ebb4caSwyllys 		"[ label=cert-label ]\n\t\t"
18099ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
18199ebb4caSwyllys 		"[ criteria=valid|expired|both ]\n\t"
18299ebb4caSwyllys 
18399ebb4caSwyllys 	"delete keystore=pkcs11 objtype=key[:[public | private | both]]\n\t\t"
18499ebb4caSwyllys 		"[ subject=subject-DN ]\n\t\t"
18599ebb4caSwyllys 		"[ label=key-label ]\n\t\t"
18699ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t"
18799ebb4caSwyllys 
18899ebb4caSwyllys 	"delete keystore=pkcs11 objtype=crl\n\t\t"
18999ebb4caSwyllys 		"infile=crl-fn\n\t\t"
19099ebb4caSwyllys 		"[ dir=directory-path ]\n\t"
19199ebb4caSwyllys 
19299ebb4caSwyllys 	"delete keystore=file objtype=cert\n\t\t"
19399ebb4caSwyllys 		"[ subject=subject-DN ]\n\t\t"
19499ebb4caSwyllys 		"[ issuer=issuer-DN ]\n\t\t"
19599ebb4caSwyllys 		"[ serial=serial number]\n\t\t"
19699ebb4caSwyllys 		"[ infile=cert-fn ]\n\t\t"
19799ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
19899ebb4caSwyllys 		"[ criteria=valid|expired|both ]\n\t"
19999ebb4caSwyllys 
20099ebb4caSwyllys 	"delete keystore=file objtype=key\n\t\t"
20199ebb4caSwyllys 		"[ infile=key-fn ]\n\t\t"
20299ebb4caSwyllys 		"[ dir=directory-path ]\n\t"
20399ebb4caSwyllys 
20499ebb4caSwyllys 	"delete keystore=file objtype=crl\n\t\t"
20599ebb4caSwyllys 		"infile=crl-fn\n\t\t"
20699ebb4caSwyllys 		"[ dir=directory-path ]\n\t"
20799ebb4caSwyllys 	},
20849e21299Sdinak 	{ "import",	pk_import,	0,
209*985be8f1Swyllys 		"imports objects from an external source",
21099ebb4caSwyllys 
21199ebb4caSwyllys 	"import [token=token[:manuf[:serial]]]\n\t\t"
21299ebb4caSwyllys 	"infile=input-fn\n\t"
21399ebb4caSwyllys 
21499ebb4caSwyllys 	"import keystore=nss objtype=cert\n\t\t"
21599ebb4caSwyllys 		"infile=input-fn\n\t\t"
21699ebb4caSwyllys 		"nickname=cert-nickname\n\t\t"
21799ebb4caSwyllys 		"[ trust=trust-value ]\n\t\t"
21899ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
21999ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
22099ebb4caSwyllys 		"[ prefix=DBprefix ]\n\t"
22199ebb4caSwyllys 
22299ebb4caSwyllys 	"import keystore=nss objtype=crl\n\t\t"
22399ebb4caSwyllys 		"infile=input-fn\n\t\t"
22499ebb4caSwyllys 		"[ verifycrl=y|n ]\n\t\t"
22599ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
22699ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
22799ebb4caSwyllys 		"[ prefix=DBprefix ]\n\t"
22899ebb4caSwyllys 
22999ebb4caSwyllys 	"import keystore=pkcs11\n\t\t"
23099ebb4caSwyllys 		"infile=input-fn\n\t\t"
23199ebb4caSwyllys 		"label=cert-label\n\t\t"
23299ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t"
23399ebb4caSwyllys 
23499ebb4caSwyllys 	"import keystore=pkcs11 objtype=crl\n\t\t"
23599ebb4caSwyllys 		"infile=input-crl-fn\n\t\t"
23699ebb4caSwyllys 		"outcrl=output-crl-fn\n\t\t"
23799ebb4caSwyllys 		"outformat=pem|der\n\t\t"
23899ebb4caSwyllys 		"[ dir=output-crl-directory-path ]\n\t"
23999ebb4caSwyllys 
24099ebb4caSwyllys 	"import keystore=file\n\t\t"
24199ebb4caSwyllys 		"infile=input-fn\n\t\t"
24299ebb4caSwyllys 		"outkey=output-key-fn\n\t\t"
24399ebb4caSwyllys 		"outcert=output-cert-fn\n\t\t"
24499ebb4caSwyllys 		"[ dir=output-cert-dir-path ]\n\t\t"
24599ebb4caSwyllys 		"[ keydir=output-key-dir-path ]\n\t\t"
24699ebb4caSwyllys 		"[ outformat=pem|der|pkcs12 ]\n\t"
24799ebb4caSwyllys 
24899ebb4caSwyllys 	"import keystore=file objtype=crl\n\t\t"
24999ebb4caSwyllys 		"infile=input-crl-fn\n\t\t"
25099ebb4caSwyllys 		"outcrl=output-crl-fn\n\t\t"
25199ebb4caSwyllys 		"outformat=pem|der\n\t\t"
25299ebb4caSwyllys 		"[ dir=output-crl-directory-path ]\n\t"
25399ebb4caSwyllys 	},
25499ebb4caSwyllys 
25549e21299Sdinak 	{ "export",	pk_export,	0,
256*985be8f1Swyllys 		"exports objects from the keystore to a file",
25799ebb4caSwyllys 
25899ebb4caSwyllys 	"export [token=token[:manuf[:serial]]]\n\t\t"
25999ebb4caSwyllys 	"outfile=output-fn\n\t"
26099ebb4caSwyllys 
26199ebb4caSwyllys 	"export keystore=nss\n\t\t"
26299ebb4caSwyllys 		"outfile=output-fn\n\t\t"
26399ebb4caSwyllys 		"[ objtype=cert|key ]\n\t\t"
26499ebb4caSwyllys 		"[ subject=subject-DN ]\n\t\t"
26599ebb4caSwyllys 		"[ issuer=issuer-DN ]\n\t\t"
26699ebb4caSwyllys 		"[ serial=serial number]\n\t\t"
26799ebb4caSwyllys 		"[ nickname=cert-nickname]\n\t\t"
26899ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
26999ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
27099ebb4caSwyllys 		"[ prefix=DBPrefix ]\n\t\t"
27199ebb4caSwyllys 		"[ outformat=pem|der|pkcs12 ]\n\t"
27299ebb4caSwyllys 
27399ebb4caSwyllys 	"export keystore=pkcs11\n\t\t"
27499ebb4caSwyllys 		"outfile=output-fn\n\t\t"
27599ebb4caSwyllys 		"[ label=cert-label]\n\t\t"
27699ebb4caSwyllys 		"[ subject=subject-DN ]\n\t\t"
27799ebb4caSwyllys 		"[ issuer=issuer-DN ]\n\t\t"
27899ebb4caSwyllys 		"[ serial=serial number]\n\t\t"
27999ebb4caSwyllys 		"[ outformat=pem|der|pkcs12]\n\t\t"
28099ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t"
28199ebb4caSwyllys 
28299ebb4caSwyllys 	"export keystore=file\n\t\t"
28399ebb4caSwyllys 		"certfile=cert-input-fn\n\t\t"
28499ebb4caSwyllys 		"keyfile=key-input-fn\n\t\t"
28599ebb4caSwyllys 		"outfile=output-pkcs12-fn\n\t\t"
28699ebb4caSwyllys 		"[ dir=directory-path ]\n\t"
28799ebb4caSwyllys 	},
28899ebb4caSwyllys 
28999ebb4caSwyllys 	{ "gencert",	pk_gencert,	0,
290*985be8f1Swyllys 		"creates a self-signed X.509v3 certificate",
291*985be8f1Swyllys 
29299ebb4caSwyllys 	"gencert [-i] keystore=nss\n\t\t"
29399ebb4caSwyllys 		"label=cert-nickname\n\t\t"
29499ebb4caSwyllys 		"serial=serial number hex string]\n\t\t"
29599ebb4caSwyllys 		"subject=subject-DN\n\t\t"
29699ebb4caSwyllys 		"[ altname=[critical:]SubjectAltName ]\n\t\t"
29799ebb4caSwyllys 		"[ keyusage=[critical:]usage,usage,...]\n\t\t"
29899ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
29999ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
30099ebb4caSwyllys 		"[ prefix=DBprefix ]\n\t\t"
30199ebb4caSwyllys 		"[ keytype=rsa|dsa ]\n\t\t"
30299ebb4caSwyllys 		"[ keylen=key-size ]\n\t\t"
30399ebb4caSwyllys 		"[ trust=trust-value ]\n\t\t"
30499ebb4caSwyllys 		"[ lifetime=number-hour|number-day|number-year ]\n\t"
30599ebb4caSwyllys 
30699ebb4caSwyllys 	"gencert [-i] [ keystore=pkcs11 ]\n\t\t"
30799ebb4caSwyllys 		"label=key/cert-label\n\t\t"
30899ebb4caSwyllys 		"subject=subject-DN\n\t\t"
30999ebb4caSwyllys 		"serial=serial number hex string\n\t\t"
31099ebb4caSwyllys 		"[ altname=[critical:]SubjectAltName ]\n\t\t"
31199ebb4caSwyllys 		"[ keyusage=[critical:]usage,usage,...]\n\t\t"
31299ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
31399ebb4caSwyllys 		"[ keytype=rsa|dsa ]\n\t\t"
31499ebb4caSwyllys 		"[ keylen=key-size ]\n\t\t"
31599ebb4caSwyllys 		"[ lifetime=number-hour|number-day|number-year ]\n\t"
31699ebb4caSwyllys 
31799ebb4caSwyllys 	"gencert [-i] keystore=file\n\t\t"
31899ebb4caSwyllys 		"outcert=cert_filename\n\t\t"
31999ebb4caSwyllys 		"outkey=key_filename\n\t\t"
32099ebb4caSwyllys 		"subject=subject-DN\n\t\t"
32199ebb4caSwyllys 		"serial=serial number hex string\n\t\t"
32299ebb4caSwyllys 		"[ altname=[critical:]SubjectAltName ]\n\t\t"
32399ebb4caSwyllys 		"[ keyusage=[critical:]usage,usage,...]\n\t\t"
32499ebb4caSwyllys 		"[ format=der|pem ]\n\t\t"
32599ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
32699ebb4caSwyllys 		"[ prefix=DBprefix ]\n\t\t"
32799ebb4caSwyllys 		"[ keytype=rsa|dsa ]\n\t\t"
32899ebb4caSwyllys 		"[ keylen=key-size ]\n\t\t"
32999ebb4caSwyllys 		"[ lifetime=number-hour|number-day|number-year ]\n\t"
33099ebb4caSwyllys 	},
33199ebb4caSwyllys 	{ "gencsr",	pk_gencsr,	0,
332*985be8f1Swyllys 		"creates a PKCS#10 certificate signing request file",
33399ebb4caSwyllys 	"gencsr [-i] keystore=nss \n\t\t"
33499ebb4caSwyllys 		"nickname=cert-nickname\n\t\t"
33599ebb4caSwyllys 		"outcsr=csr-fn\n\t\t"
33699ebb4caSwyllys 		"subject=subject-DN\n\t\t"
33799ebb4caSwyllys 		"[ altname=[critical:]SubjectAltName ]\n\t\t"
33899ebb4caSwyllys 		"[ keyusage=[critical:]usage,usage,...]\n\t\t"
33999ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
34099ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
34199ebb4caSwyllys 		"[ prefix=DBprefix ]\n\t\t"
34299ebb4caSwyllys 		"[ keytype=rsa|dsa ]\n\t\t"
34399ebb4caSwyllys 		"[ keylen=key-size ]\n\t\t"
34499ebb4caSwyllys 		"[ format=pem|der]\n\t"
34599ebb4caSwyllys 	"gencsr [-i] [ keystore=pkcs11 ]\n\t\t"
34699ebb4caSwyllys 		"label=key-label\n\t\t"
34799ebb4caSwyllys 		"outcsr=csr-fn\n\t\t"
34899ebb4caSwyllys 		"subject=subject-DN\n\t\t"
34999ebb4caSwyllys 		"[ altname=[critical:]SubjectAltName ]\n\t\t"
35099ebb4caSwyllys 		"[ keyusage=[critical:]usage,usage,...]\n\t\t"
35199ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
35299ebb4caSwyllys 		"[ keytype=rsa|dsa ]\n\t\t"
35399ebb4caSwyllys 		"[ keylen=key-size ]\n\t\t"
35499ebb4caSwyllys 		"[ format=pem|der]\n\t"
35599ebb4caSwyllys 	"gencsr [-i] keystore=file\n\t\t"
35699ebb4caSwyllys 		"outcsr=csr-fn\n\t\t"
35799ebb4caSwyllys 		"outkey=key-fn\n\t\t"
35899ebb4caSwyllys 		"subject=subject-DN\n\t\t"
35999ebb4caSwyllys 		"[ altname=[critical:]SubjectAltName ]\n\t\t"
36099ebb4caSwyllys 		"[ keyusage=[critical:]usage,usage,...]\n\t\t"
36199ebb4caSwyllys 		"[ keytype=rsa|dsa ]\n\t\t"
36299ebb4caSwyllys 		"[ keylen=key-size ]\n\t\t"
36399ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
36499ebb4caSwyllys 		"[ format=pem|der]\n\t"
36599ebb4caSwyllys 	},
36699ebb4caSwyllys 
36799ebb4caSwyllys 	{ "download",	pk_download,	0,
368*985be8f1Swyllys 		"downloads a CRL or certificate file from an external source",
369*985be8f1Swyllys 
37099ebb4caSwyllys 	"download url=url_str\n\t\t"
37199ebb4caSwyllys 		"[ objtype=crl|cert ]\n\t\t"
37299ebb4caSwyllys 		"[ http_proxy=proxy_str ]\n\t\t"
37399ebb4caSwyllys 		"[ outfile = outfile ]\n\t\t"
37499ebb4caSwyllys 	},
37599ebb4caSwyllys 
37699ebb4caSwyllys 	{ "genkey",	pk_genkey,	0,
377*985be8f1Swyllys 		"creates a symmetric key in the keystore",
378*985be8f1Swyllys 
37999ebb4caSwyllys 	"genkey [ keystore=pkcs11 ]\n\t\t"
38099ebb4caSwyllys 		"label=key-label\n\t\t"
38199ebb4caSwyllys 		"[ keytype=aes|arcfour|des|3des ]\n\t\t"
38299ebb4caSwyllys 		"[ keylen=key-size (AES or ARCFOUR only)]\n\t\t"
38399ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
38499ebb4caSwyllys 		"[ sensitive=y|n ]\n\t\t"
38599ebb4caSwyllys 		"[ extractable=y|n ]\n\t\t"
38699ebb4caSwyllys 		"[ print=y|n ]\n\t"
38799ebb4caSwyllys 
38899ebb4caSwyllys 	"genkey keystore=nss\n\t\t"
38999ebb4caSwyllys 		"label=key-label\n\t\t"
39099ebb4caSwyllys 		"[ keytype=aes|arcfour|des|3des ]\n\t\t"
39199ebb4caSwyllys 		"[ keylen=key-size (AES or ARCFOUR only)]\n\t\t"
39299ebb4caSwyllys 		"[ token=token[:manuf[:serial]]]\n\t\t"
39399ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
39499ebb4caSwyllys 		"[ prefix=DBprefix ]\n\t"
39599ebb4caSwyllys 
39699ebb4caSwyllys 	"genkey keystore=file\n\t\t"
39799ebb4caSwyllys 		"outkey=key-fn\n\t\t"
39899ebb4caSwyllys 		"[ keytype=aes|arcfour|des|3des ]\n\t\t"
39999ebb4caSwyllys 		"[ keylen=key-size (AES or ARCFOUR only)]\n\t\t"
40099ebb4caSwyllys 		"[ dir=directory-path ]\n\t\t"
40199ebb4caSwyllys 		"[ print=y|n ]\n\t"
40299ebb4caSwyllys 	},
40399ebb4caSwyllys 
404*985be8f1Swyllys 	{ "help",	pk_help,	0,
405*985be8f1Swyllys 		"displays help message",
406*985be8f1Swyllys 		"help\t(help and usage)" }
4077c478bd9Sstevel@tonic-gate };
408*985be8f1Swyllys 
4097c478bd9Sstevel@tonic-gate static int	num_cmds = sizeof (cmds) / sizeof (verbcmd);
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate static char	*prog;
41299ebb4caSwyllys static void	usage(int);
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate /*
4157c478bd9Sstevel@tonic-gate  * Usage information.  This function must be updated when new verbs or
4167c478bd9Sstevel@tonic-gate  * options are added.
4177c478bd9Sstevel@tonic-gate  */
4187c478bd9Sstevel@tonic-gate static void
41999ebb4caSwyllys usage(int idx)
4207c478bd9Sstevel@tonic-gate {
4217711facfSdinak 	int	i;
4227711facfSdinak 
4237711facfSdinak 	/* Display this block only in command-line mode. */
4247711facfSdinak 	(void) fprintf(stdout, gettext("Usage:\n"));
425*985be8f1Swyllys 	(void) fprintf(stdout, gettext("   %s -?\t(help and usage)\n"),
426*985be8f1Swyllys 		prog);
427*985be8f1Swyllys 	(void) fprintf(stdout, gettext("   %s -f option_file\n"), prog);
428*985be8f1Swyllys 	(void) fprintf(stdout, gettext("   %s subcommand [options...]\n"),
429*985be8f1Swyllys 		prog);
4307711facfSdinak 	(void) fprintf(stdout, gettext("where subcommands may be:\n"));
4317711facfSdinak 
4327711facfSdinak 	/* Display only those verbs that match the current tool mode. */
43399ebb4caSwyllys 	if (idx == -1) {
4347711facfSdinak 		for (i = 0; i < num_cmds; i++) {
4357711facfSdinak 			/* Do NOT i18n/l10n. */
436*985be8f1Swyllys 			(void) fprintf(stdout, "   %-8s	- %s\n",
437*985be8f1Swyllys 				cmds[i].verb, cmds[i].summary);
4387711facfSdinak 		}
439*985be8f1Swyllys 		(void) fprintf(stdout, gettext("\nFurther details on the "
440*985be8f1Swyllys 			"subcommands can be found by adding \'help\'.\n"
441*985be8f1Swyllys 			"Ex: pktool gencert help\n\n"));
44299ebb4caSwyllys 	} else {
44399ebb4caSwyllys 		(void) fprintf(stdout, "\t%s\n", cmds[idx].synopsis);
44499ebb4caSwyllys 	}
4457711facfSdinak }
4467711facfSdinak 
4477711facfSdinak /*
4487711facfSdinak  * Provide help, in the form of displaying the usage.
4497711facfSdinak  */
4507711facfSdinak static int
4517711facfSdinak pk_help(int argc, char *argv[])
4527711facfSdinak /* ARGSUSED */
4537711facfSdinak {
45499ebb4caSwyllys 	usage(-1);
45599ebb4caSwyllys 	return (0);
45699ebb4caSwyllys }
4577711facfSdinak 
45899ebb4caSwyllys /*
45999ebb4caSwyllys  * Process arguments from the argfile and create a new
46099ebb4caSwyllys  * argv/argc list to be processed later.
46199ebb4caSwyllys  */
46299ebb4caSwyllys static int
46399ebb4caSwyllys process_arg_file(char *argfile, char ***argv, int *argc)
46499ebb4caSwyllys {
46599ebb4caSwyllys 	FILE *fp;
46699ebb4caSwyllys 	char argline[2 * BUFSIZ]; /* 2048 bytes should be plenty */
46799ebb4caSwyllys 	char *p;
46899ebb4caSwyllys 	int nargs = 0;
46999ebb4caSwyllys 
47099ebb4caSwyllys 	if ((fp = fopen(argfile, "rF")) == NULL) {
47199ebb4caSwyllys 		(void) fprintf(stderr,
47299ebb4caSwyllys 			gettext("Cannot read argfile %s: %s\n"),
47399ebb4caSwyllys 			argfile, strerror(errno));
47499ebb4caSwyllys 		return (errno);
47599ebb4caSwyllys 	}
47699ebb4caSwyllys 
47799ebb4caSwyllys 	while (fgets(argline, sizeof (argline), fp) != NULL) {
47899ebb4caSwyllys 		int j;
47999ebb4caSwyllys 		/* remove trailing whitespace */
48099ebb4caSwyllys 		j = strlen(argline) - 1;
48199ebb4caSwyllys 		while (j >= 0 && isspace(argline[j])) {
48299ebb4caSwyllys 			argline[j] = 0;
48399ebb4caSwyllys 			j--;
48499ebb4caSwyllys 		}
48599ebb4caSwyllys 		/* If it was a blank line, get the next one. */
48699ebb4caSwyllys 		if (!strlen(argline))
48799ebb4caSwyllys 			continue;
48899ebb4caSwyllys 
48999ebb4caSwyllys 		(*argv) = realloc((*argv),
49099ebb4caSwyllys 			(nargs + 1) * sizeof (char *));
49199ebb4caSwyllys 		if ((*argv) == NULL) {
49299ebb4caSwyllys 			perror("memory error");
49399ebb4caSwyllys 			(void) fclose(fp);
49499ebb4caSwyllys 			return (errno);
49599ebb4caSwyllys 		}
49699ebb4caSwyllys 		p = (char *)strdup(argline);
49799ebb4caSwyllys 		if (p == NULL) {
49899ebb4caSwyllys 			perror("memory error");
49999ebb4caSwyllys 			(void) fclose(fp);
50099ebb4caSwyllys 			return (errno);
50199ebb4caSwyllys 		}
50299ebb4caSwyllys 		(*argv)[nargs] = p;
50399ebb4caSwyllys 		nargs++;
50499ebb4caSwyllys 	}
50599ebb4caSwyllys 	*argc = nargs;
50699ebb4caSwyllys 	(void) fclose(fp);
5077711facfSdinak 	return (0);
5087c478bd9Sstevel@tonic-gate }
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate /*
5117c478bd9Sstevel@tonic-gate  * MAIN() -- where all the action is
5127c478bd9Sstevel@tonic-gate  */
5137c478bd9Sstevel@tonic-gate int
5147c478bd9Sstevel@tonic-gate main(int argc, char *argv[], char *envp[])
5157c478bd9Sstevel@tonic-gate /* ARGSUSED2 */
5167c478bd9Sstevel@tonic-gate {
5177c478bd9Sstevel@tonic-gate 	int	i, found = -1;
5187c478bd9Sstevel@tonic-gate 	int	rv;
5197c478bd9Sstevel@tonic-gate 	int	pk_argc = 0;
5207c478bd9Sstevel@tonic-gate 	char	**pk_argv = NULL;
5217711facfSdinak 	int	save_errno = 0;
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate 	/* Set up for i18n/l10n. */
5247c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
5257c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)		/* Should be defined by cc -D. */
5267c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it isn't. */
5277c478bd9Sstevel@tonic-gate #endif
5287c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate 	/* Get program base name and move pointer over 0th arg. */
5317c478bd9Sstevel@tonic-gate 	prog = basename(argv[0]);
5327c478bd9Sstevel@tonic-gate 	argv++, argc--;
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate 	/* Set up for debug and error output. */
5357c478bd9Sstevel@tonic-gate 	if (argc == 0) {
53699ebb4caSwyllys 		usage(-1);
5377c478bd9Sstevel@tonic-gate 		return (1);
5387c478bd9Sstevel@tonic-gate 	}
5397c478bd9Sstevel@tonic-gate 
5407711facfSdinak 	/* Check for help options.  For CLIP-compliance. */
54199ebb4caSwyllys 	if (strcmp(argv[0], "-?") == 0) {
5427711facfSdinak 		return (pk_help(argc, argv));
54399ebb4caSwyllys 	} else if (strcmp(argv[0], "-f") == 0 && argc == 2) {
54499ebb4caSwyllys 		rv = process_arg_file(argv[1], &pk_argv, &pk_argc);
54599ebb4caSwyllys 		if (rv)
54699ebb4caSwyllys 			return (rv);
54799ebb4caSwyllys 	} else if (argc >= 1 && argv[0][0] == '-') {
54899ebb4caSwyllys 		usage(-1);
5497711facfSdinak 		return (1);
5507711facfSdinak 	}
5517711facfSdinak 
5527711facfSdinak 	/* Always turns off Metaslot so that we can see softtoken. */
5537c478bd9Sstevel@tonic-gate 	if (setenv("METASLOT_ENABLED", "false", 1) < 0) {
5547711facfSdinak 		save_errno = errno;
5557c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
5567711facfSdinak 		    gettext("Disabling Metaslot failed (%s)."),
5577711facfSdinak 		    strerror(save_errno));
5587c478bd9Sstevel@tonic-gate 		return (1);
5597c478bd9Sstevel@tonic-gate 	}
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 	/* Begin parsing command line. */
56299ebb4caSwyllys 	if (pk_argc == 0 && pk_argv == NULL) {
5637c478bd9Sstevel@tonic-gate 		pk_argc = argc;
5647c478bd9Sstevel@tonic-gate 		pk_argv = argv;
56599ebb4caSwyllys 	}
5667c478bd9Sstevel@tonic-gate 
5677711facfSdinak 	/* Check for valid verb (or an abbreviation of it). */
5687c478bd9Sstevel@tonic-gate 	found = -1;
5697c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_cmds; i++) {
5707c478bd9Sstevel@tonic-gate 		if (strcmp(cmds[i].verb, pk_argv[0]) == 0) {
5717c478bd9Sstevel@tonic-gate 			if (found < 0) {
5727c478bd9Sstevel@tonic-gate 				found = i;
5737c478bd9Sstevel@tonic-gate 				break;
5747c478bd9Sstevel@tonic-gate 			}
5757c478bd9Sstevel@tonic-gate 		}
5767c478bd9Sstevel@tonic-gate 	}
5777c478bd9Sstevel@tonic-gate 	/* Stop here if no valid verb found. */
5787c478bd9Sstevel@tonic-gate 	if (found < 0) {
5797711facfSdinak 		cryptoerror(LOG_STDERR, gettext("Invalid verb: %s"),
5807711facfSdinak 		    pk_argv[0]);
5817c478bd9Sstevel@tonic-gate 		return (1);
5827c478bd9Sstevel@tonic-gate 	}
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 	/* Get to work! */
5857c478bd9Sstevel@tonic-gate 	rv = (*cmds[found].action)(pk_argc, pk_argv);
5867c478bd9Sstevel@tonic-gate 	switch (rv) {
5877c478bd9Sstevel@tonic-gate 	case PK_ERR_NONE:
5887c478bd9Sstevel@tonic-gate 		break;		/* Command succeeded, do nothing. */
5897c478bd9Sstevel@tonic-gate 	case PK_ERR_USAGE:
59099ebb4caSwyllys 		usage(found);
5917c478bd9Sstevel@tonic-gate 		break;
5927c478bd9Sstevel@tonic-gate 	case PK_ERR_QUIT:
5937c478bd9Sstevel@tonic-gate 		exit(0);
5947c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
5957711facfSdinak 	case PK_ERR_PK11:
5967711facfSdinak 	case PK_ERR_SYSTEM:
5977711facfSdinak 	case PK_ERR_OPENSSL:
59899ebb4caSwyllys 	case PK_ERR_NSS:
5997c478bd9Sstevel@tonic-gate 	default:
6007c478bd9Sstevel@tonic-gate 		break;
6017c478bd9Sstevel@tonic-gate 	}
6027c478bd9Sstevel@tonic-gate 	return (rv);
6037c478bd9Sstevel@tonic-gate }
604