xref: /onnv-gate/usr/src/cmd/cmd-crypto/pktool/pktool.c (revision 12234:cd6642d6b7dd)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
53089Swyllys  * Common Development and Distribution License (the "License").
63089Swyllys  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*12234Swyllys.ingersoll@sun.com  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate /*
260Sstevel@tonic-gate  * This file comprises the main driver for this tool.
2717Sdinak  * Upon parsing the command verbs from user input, it
2817Sdinak  * branches to the appropriate modules to perform the
2917Sdinak  * requested task.
300Sstevel@tonic-gate  */
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <stdio.h>
330Sstevel@tonic-gate #include <string.h>
340Sstevel@tonic-gate #include <ctype.h>
350Sstevel@tonic-gate #include <malloc.h>
366051Swyllys #include <libintl.h>
370Sstevel@tonic-gate #include <libgen.h>
380Sstevel@tonic-gate #include <errno.h>
390Sstevel@tonic-gate #include <cryptoutil.h>
400Sstevel@tonic-gate #include <security/cryptoki.h>
410Sstevel@tonic-gate #include "common.h"
420Sstevel@tonic-gate 
430Sstevel@tonic-gate /*
440Sstevel@tonic-gate  * The verbcmd construct allows genericizing information about a verb so
450Sstevel@tonic-gate  * that it is easier to manipulate.  Makes parsing code easier to read,
460Sstevel@tonic-gate  * fix, and extend with new verbs.
470Sstevel@tonic-gate  */
480Sstevel@tonic-gate typedef struct verbcmd_s {
490Sstevel@tonic-gate 	char	*verb;
500Sstevel@tonic-gate 	int	(*action)(int, char *[]);
5117Sdinak 	int	mode;
523501Swyllys 	char	*summary;
5317Sdinak 	char	*synopsis;
540Sstevel@tonic-gate } verbcmd;
550Sstevel@tonic-gate 
560Sstevel@tonic-gate /* External declarations for supported verb actions. */
570Sstevel@tonic-gate extern int	pk_setpin(int argc, char *argv[]);
5817Sdinak extern int	pk_list(int argc, char *argv[]);
5917Sdinak extern int	pk_delete(int argc, char *argv[]);
6017Sdinak extern int	pk_import(int argc, char *argv[]);
6117Sdinak extern int	pk_export(int argc, char *argv[]);
6217Sdinak extern int	pk_tokens(int argc, char *argv[]);
633089Swyllys extern int	pk_gencert(int argc, char *argv[]);
643089Swyllys extern int	pk_gencsr(int argc, char *argv[]);
653089Swyllys extern int	pk_download(int argc, char *argv[]);
663089Swyllys extern int	pk_genkey(int argc, char *argv[]);
676051Swyllys extern int	pk_signcsr(int argc, char *argv[]);
689126SWyllys.Ingersoll@Sun.COM extern int	pk_inittoken(int argc, char *argv[]);
6911973Swyllys.ingersoll@sun.com extern int	pk_genkeypair(int argc, char *argv[]);
7017Sdinak 
7117Sdinak /* Forward declarations for "built-in" verb actions. */
7217Sdinak static int	pk_help(int argc, char *argv[]);
730Sstevel@tonic-gate 
746051Swyllys #define	TOKEN_IDX 0
756354Swyllys #define	TOKEN_VERB "tokens"
766051Swyllys #define	TOKEN_SUMM gettext("lists all visible PKCS#11 tokens")
776354Swyllys #define	TOKEN_SYN  "tokens"
786051Swyllys 
796051Swyllys #define	SETPIN_IDX 1
806354Swyllys #define	SETPIN_VERB "setpin"
816051Swyllys #define	SETPIN_SUMM gettext("changes user authentication passphrase "\
826051Swyllys 	"for keystore access")
836354Swyllys #define	SETPIN_SYN \
846051Swyllys 	"setpin [ keystore=pkcs11 ]\n\t\t" \
859126SWyllys.Ingersoll@Sun.COM 	"[ token=token[:manuf[:serial]]]\n\t\t" \
869126SWyllys.Ingersoll@Sun.COM 	"[ usertype=so|user ]\n\t" \
879126SWyllys.Ingersoll@Sun.COM \
886051Swyllys 	"setpin keystore=nss\n\t\t" \
896051Swyllys 	"[ token=token ]\n\t\t" \
906051Swyllys 	"[ dir=directory-path ]\n\t\t" \
916354Swyllys 	"[ prefix=DBprefix ]\n\t"
926051Swyllys 
936051Swyllys #define	LIST_IDX 2
946354Swyllys #define	LIST_VERB "list"
956051Swyllys #define	LIST_SUMM gettext("lists a summary of objects in the keystore")
966354Swyllys #define	LIST_SYN \
976051Swyllys 	"list [ token=token[:manuf[:serial]]]\n\t\t" \
986051Swyllys 	"[ objtype=private|public|both ]\n\t\t" \
996051Swyllys 	"[ label=label ]\n\t" \
1006051Swyllys  \
1016051Swyllys 	"list objtype=cert[:[public | private | both ]]\n\t\t" \
1026051Swyllys 	"[ subject=subject-DN ]\n\t\t" \
1036051Swyllys 	"[ keystore=pkcs11 ]\n\t\t" \
1046051Swyllys 	"[ issuer=issuer-DN ]\n\t\t" \
1056051Swyllys 	"[ serial=serial number ]\n\t\t" \
1066051Swyllys 	"[ label=cert-label ]\n\t\t" \
1076051Swyllys 	"[ token=token[:manuf[:serial]]]\n\t\t" \
1086051Swyllys 	"[ criteria=valid|expired|both ]\n\t" \
1096051Swyllys  \
1106051Swyllys 	"list objtype=key[:[public | private | both ]]\n\t\t" \
1116051Swyllys 	"[ keystore=pkcs11 ]\n\t\t" \
1126051Swyllys 	"[ label=key-label ]\n\t\t" \
1136051Swyllys 	"[ token=token[:manuf[:serial]]]\n\t" \
1146051Swyllys  \
1156051Swyllys 	"list keystore=pkcs11 objtype=crl\n\t\t" \
1166669Swyllys 	"infile=crl-fn\n\t" \
1176051Swyllys  \
1186051Swyllys 	"list keystore=nss objtype=cert\n\t\t" \
1196051Swyllys 	"[ subject=subject-DN ]\n\t\t" \
1206051Swyllys 	"[ issuer=issuer-DN ]\n\t\t" \
1216051Swyllys 	"[ serial=serial number ]\n\t\t" \
1226051Swyllys 	"[ nickname=cert-nickname ]\n\t\t" \
1236051Swyllys 	"[ token=token[:manuf[:serial]]]\n\t\t" \
1246051Swyllys 	"[ dir=directory-path ]\n\t\t" \
1256051Swyllys 	"[ prefix=DBprefix ]\n\t\t" \
1266051Swyllys 	"[ criteria=valid|expired|both ]\n\t" \
1276051Swyllys  \
1286051Swyllys 	"list keystore=nss objtype=key\n\t\t" \
1296051Swyllys 	"[ token=token[:manuf[:serial]]]\n\t\t" \
1306051Swyllys 	"[ dir=directory-path ]\n\t\t" \
1316051Swyllys 	"[ prefix=DBprefix ]\n\t\t" \
1326051Swyllys 	"[ nickname=key-nickname ]\n\t" \
1336051Swyllys  \
1346051Swyllys 	"list keystore=file objtype=cert\n\t\t" \
1356051Swyllys 	"[ subject=subject-DN ]\n\t\t" \
1366051Swyllys 	"[ issuer=issuer-DN ]\n\t\t" \
1376051Swyllys 	"[ serial=serial number ]\n\t\t" \
1386051Swyllys 	"[ infile=cert-fn ]\n\t\t" \
1396051Swyllys 	"[ dir=directory-path ]\n\t\t" \
1406051Swyllys 	"[ criteria=valid|expired|both ]\n\t" \
1416051Swyllys  \
1426051Swyllys 	"list keystore=file objtype=key\n\t\t" \
1436051Swyllys 	"[ infile=key-fn ]\n\t\t" \
1446051Swyllys 	"[ dir=directory-path ]\n\t" \
1456051Swyllys  \
1466051Swyllys 	"list keystore=file objtype=crl\n\t\t" \
1476669Swyllys 	"infile=crl-fn\n\t"
1486051Swyllys 
1496051Swyllys #define	DELETE_IDX 3
1506354Swyllys #define	DELETE_VERB "delete"
1516051Swyllys #define	DELETE_SUMM gettext("deletes objects in the keystore")
1526354Swyllys #define	DELETE_SYN \
1536051Swyllys 	"delete [ token=token[:manuf[:serial]]]\n\t\t" \
1546051Swyllys 	"[ objtype=private|public|both ]\n\t\t" \
1556051Swyllys 	"[ label=object-label ]\n\t" \
1566051Swyllys  \
1576051Swyllys 	"delete keystore=nss objtype=cert\n\t\t" \
1586051Swyllys 	"[ subject=subject-DN ]\n\t\t" \
1596051Swyllys 	"[ issuer=issuer-DN ]\n\t\t" \
1606051Swyllys 	"[ serial=serial number ]\n\t\t" \
1616051Swyllys 	"[ label=cert-label ]\n\t\t" \
1626051Swyllys 	"[ token=token[:manuf[:serial]]]\n\t\t" \
1636051Swyllys 	"[ dir=directory-path ]\n\t\t" \
1646051Swyllys 	"[ prefix=DBprefix ]\n\t\t" \
1656051Swyllys 	"[ criteria=valid|expired|both ]\n\t" \
1666051Swyllys  \
1676051Swyllys 	"delete keystore=nss objtype=key\n\t\t" \
1686051Swyllys 	"[ token=token[:manuf[:serial]]]\n\t\t" \
1696051Swyllys 	"[ dir=directory-path ]\n\t\t" \
1706051Swyllys 	"[ prefix=DBprefix ]\n\t\t" \
1716051Swyllys 	"[ nickname=key-nickname ]\n\t\t" \
1726051Swyllys  \
1736051Swyllys 	"delete keystore=nss objtype=crl\n\t\t" \
1746051Swyllys 	"[ nickname=issuer-nickname ]\n\t\t" \
1756051Swyllys 	"[ subject=subject-DN ]\n\t\t" \
1766051Swyllys 	"[ token=token[:manuf[:serial]]]\n\t\t" \
1776051Swyllys 	"[ dir=directory-path ]\n\t\t" \
1786051Swyllys 	"[ prefix=DBprefix ]\n\t" \
1796051Swyllys  \
1806051Swyllys 	"delete keystore=pkcs11 " \
1816051Swyllys 	"objtype=cert[:[public | private | both]]\n\t\t" \
1826051Swyllys 	"[ subject=subject-DN ]\n\t\t" \
1836051Swyllys 	"[ issuer=issuer-DN ]\n\t\t" \
1846051Swyllys 	"[ serial=serial number ]\n\t\t" \
1856051Swyllys 	"[ label=cert-label ]\n\t\t" \
1866051Swyllys 	"[ token=token[:manuf[:serial]]]\n\t\t" \
1876051Swyllys 	"[ criteria=valid|expired|both ]\n\t" \
1886051Swyllys  \
1896051Swyllys 	"delete keystore=pkcs11 " \
1906051Swyllys 	"objtype=key[:[public | private | both]]\n\t\t" \
1916051Swyllys 	"[ label=key-label ]\n\t\t" \
1926051Swyllys 	"[ token=token[:manuf[:serial]]]\n\t" \
1936051Swyllys  \
1946051Swyllys 	"delete keystore=pkcs11 objtype=crl\n\t\t" \
1956669Swyllys 	"infile=crl-fn\n\t" \
1966051Swyllys  \
1976051Swyllys 	"delete keystore=file objtype=cert\n\t\t" \
1986051Swyllys 	"[ subject=subject-DN ]\n\t\t" \
1996051Swyllys 	"[ issuer=issuer-DN ]\n\t\t" \
2006051Swyllys 	"[ serial=serial number ]\n\t\t" \
2016051Swyllys 	"[ infile=cert-fn ]\n\t\t" \
2026051Swyllys 	"[ dir=directory-path ]\n\t\t" \
2036051Swyllys 	"[ criteria=valid|expired|both ]\n\t" \
2046051Swyllys  \
2056051Swyllys 	"delete keystore=file objtype=key\n\t\t" \
2066051Swyllys 	"[ infile=key-fn ]\n\t\t" \
2076051Swyllys 	"[ dir=directory-path ]\n\t" \
2086051Swyllys  \
2096051Swyllys 	"delete keystore=file objtype=crl\n\t\t" \
2106669Swyllys 	"infile=crl-fn\n\t"
2116051Swyllys 
2126051Swyllys #define	IMPORT_IDX 4
2136354Swyllys #define	IMPORT_VERB "import"
2146051Swyllys #define	IMPORT_SUMM gettext("imports objects from an external source")
2156354Swyllys #define	IMPORT_SYN \
2166051Swyllys 	"import [token=token[:manuf[:serial]]]\n\t\t" \
2176051Swyllys 	"infile=input-fn\n\t" \
2186051Swyllys  \
2196051Swyllys 	"import keystore=nss objtype=cert\n\t\t" \
2206051Swyllys 	"infile=input-fn\n\t\t" \
2216051Swyllys 	"label=cert-label\n\t\t" \
2226051Swyllys 	"[ trust=trust-value ]\n\t\t" \
2236051Swyllys 	"[ token=token[:manuf[:serial]]]\n\t\t" \
2246051Swyllys 	"[ dir=directory-path ]\n\t\t" \
2256051Swyllys 	"[ prefix=DBprefix ]\n\t" \
2266051Swyllys  \
2276051Swyllys 	"import keystore=nss objtype=crl\n\t\t" \
2286051Swyllys 	"infile=input-fn\n\t\t" \
2296051Swyllys 	"[ verifycrl=y|n ]\n\t\t" \
2306051Swyllys 	"[ token=token[:manuf[:serial]]]\n\t\t" \
2316051Swyllys 	"[ dir=directory-path ]\n\t\t" \
2326051Swyllys 	"[ prefix=DBprefix ]\n\t" \
2336051Swyllys  \
2346051Swyllys 	"import keystore=pkcs11\n\t\t" \
2356051Swyllys 	"infile=input-fn\n\t\t" \
2366051Swyllys 	"label=label\n\t\t" \
2376051Swyllys 	"[ objtype=cert|key ]\n\t\t" \
2386051Swyllys 	"[ keytype=aes|arcfour|des|3des|generic ]\n\t\t" \
2396051Swyllys 	"[ sensitive=y|n ]\n\t\t" \
2406051Swyllys 	"[ extractable=y|n ]\n\t\t" \
2416051Swyllys 	"[ token=token[:manuf[:serial]]]\n\t" \
2426051Swyllys  \
2436051Swyllys 	"import keystore=pkcs11 objtype=crl\n\t\t" \
2446051Swyllys 	"infile=input-crl-fn\n\t\t" \
2456051Swyllys 	"outcrl=output-crl-fn\n\t\t" \
2466669Swyllys 	"outformat=pem|der\n\t" \
2476051Swyllys  \
2486051Swyllys 	"import keystore=file\n\t\t" \
2496051Swyllys 	"infile=input-fn\n\t\t" \
2506051Swyllys 	"outkey=output-key-fn\n\t\t" \
2516051Swyllys 	"outcert=output-cert-fn\n\t\t" \
2526051Swyllys 	"[ outformat=pem|der|pkcs12 ]\n\t" \
2536051Swyllys  \
2546051Swyllys 	"import keystore=file objtype=crl\n\t\t" \
2556051Swyllys 	"infile=input-crl-fn\n\t\t" \
2566051Swyllys 	"outcrl=output-crl-fn\n\t\t" \
2576669Swyllys 	"outformat=pem|der\n\t"
2586051Swyllys 
2596051Swyllys #define	EXPORT_IDX 5
2606354Swyllys #define	EXPORT_VERB "export"
2616051Swyllys #define	EXPORT_SUMM gettext("exports objects from the keystore to a file")
2626354Swyllys #define	EXPORT_SYN \
2636051Swyllys 	"export [token=token[:manuf[:serial]]]\n\t\t" \
2646051Swyllys 	"outfile=output-fn\n\t" \
2656051Swyllys  \
2666051Swyllys 	"export keystore=nss\n\t\t" \
2676051Swyllys 	"outfile=output-fn\n\t\t" \
2686051Swyllys 	"[ objtype=cert|key ]\n\t\t" \
2696051Swyllys 	"[ subject=subject-DN ]\n\t\t" \
2706051Swyllys 	"[ issuer=issuer-DN ]\n\t\t" \
2716051Swyllys 	"[ serial=serial number ]\n\t\t" \
2726051Swyllys 	"[ nickname=cert-nickname ]\n\t\t" \
2736051Swyllys 	"[ token=token[:manuf[:serial]]]\n\t\t" \
2746051Swyllys 	"[ dir=directory-path ]\n\t\t" \
2756051Swyllys 	"[ prefix=DBPrefix ]\n\t\t" \
2766051Swyllys 	"[ outformat=pem|der|pkcs12 ]\n\t" \
2776051Swyllys  \
2786051Swyllys 	"export keystore=pkcs11\n\t\t" \
2796051Swyllys 	"outfile=output-fn\n\t\t" \
2806051Swyllys 	"[ objtype=cert|key ]\n\t\t" \
2816051Swyllys 	"[ label=label ]\n\t\t" \
2826051Swyllys 	"[ subject=subject-DN ]\n\t\t" \
2836051Swyllys 	"[ issuer=issuer-DN ]\n\t\t" \
2846051Swyllys 	"[ serial=serial number ]\n\t\t" \
2856051Swyllys 	"[ outformat=pem|der|pkcs12|raw ]\n\t\t" \
2866051Swyllys 	"[ token=token[:manuf[:serial]]]\n\t" \
2876051Swyllys  \
2886051Swyllys 	"export keystore=file\n\t\t" \
2896051Swyllys 	"certfile=cert-input-fn\n\t\t" \
2906051Swyllys 	"keyfile=key-input-fn\n\t\t" \
2916669Swyllys 	"outfile=output-pkcs12-fn\n\t"
2926051Swyllys 
2936051Swyllys #define	GENCERT_IDX 6
2946354Swyllys #define	GENCERT_VERB "gencert"
2956051Swyllys #define	GENCERT_SUMM gettext("creates a self-signed X.509v3 certificate")
2966354Swyllys #define	GENCERT_SYN \
29711973Swyllys.ingersoll@sun.com 	"gencert listcurves\n\t" \
29811973Swyllys.ingersoll@sun.com \
29910241Swyllys.ingersoll@sun.com 	"gencert keystore=nss\n\t\t" \
3006051Swyllys 	"label=cert-nickname\n\t\t" \
30111973Swyllys.ingersoll@sun.com 	"serial=serial number hex string\n\t\t" \
30210241Swyllys.ingersoll@sun.com 	"[ -i ] | [subject=subject-DN]\n\t\t" \
3036051Swyllys 	"[ altname=[critical:]SubjectAltName ]\n\t\t" \
3046051Swyllys 	"[ keyusage=[critical:]usage,usage,...]\n\t\t" \
3056051Swyllys 	"[ token=token[:manuf[:serial]]]\n\t\t" \
3066051Swyllys 	"[ dir=directory-path ]\n\t\t" \
3076051Swyllys 	"[ prefix=DBprefix ]\n\t\t" \
30811973Swyllys.ingersoll@sun.com 	"[ keytype=rsa | ec [curve=ECC Curve Name] " \
30911973Swyllys.ingersoll@sun.com 	"[hash=md5 | sha1 | sha256 | sha384 | sha512]]\n\t\t" \
31011973Swyllys.ingersoll@sun.com 	"[ keytype=dsa [hash=sha1]]\n\t\t" \
3116051Swyllys 	"[ keylen=key-size ]\n\t\t" \
3126051Swyllys 	"[ trust=trust-value ]\n\t\t" \
3136051Swyllys 	"[ eku=[critical:]EKU name,...]\n\t\t" \
3146051Swyllys 	"[ lifetime=number-hour|number-day|number-year ]\n\t" \
3156051Swyllys  \
31610241Swyllys.ingersoll@sun.com 	"gencert [ keystore=pkcs11 ]\n\t\t" \
3176051Swyllys 	"label=key/cert-label\n\t\t" \
3186051Swyllys 	"serial=serial number hex string\n\t\t" \
31910241Swyllys.ingersoll@sun.com 	"[ -i ] | [subject=subject-DN]\n\t\t" \
3206051Swyllys 	"[ altname=[critical:]SubjectAltName ]\n\t\t" \
3216051Swyllys 	"[ keyusage=[critical:]usage,usage,...]\n\t\t" \
3226051Swyllys 	"[ token=token[:manuf[:serial]]]\n\t\t" \
32311973Swyllys.ingersoll@sun.com 	"[ keytype=rsa | ec [curve=ECC Curve Name] " \
32411973Swyllys.ingersoll@sun.com 	"[hash=md5 | sha1 | sha256 | sha384 | sha512]]\n\t\t" \
32511973Swyllys.ingersoll@sun.com 	"[ keytype=dsa [hash=sha1 | sha256 ]]\n\t\t" \
3266051Swyllys 	"[ keylen=key-size ]\n\t\t" \
3276051Swyllys 	"[ eku=[critical:]EKU name,...]\n\t\t" \
3286051Swyllys 	"[ lifetime=number-hour|number-day|number-year ]\n\t" \
3296051Swyllys  \
33010241Swyllys.ingersoll@sun.com 	"gencert keystore=file\n\t\t" \
3316051Swyllys 	"outcert=cert_filename\n\t\t" \
3326051Swyllys 	"outkey=key_filename\n\t\t" \
3336051Swyllys 	"serial=serial number hex string\n\t\t" \
33410241Swyllys.ingersoll@sun.com 	"[ -i ] | [subject=subject-DN]\n\t\t" \
3356051Swyllys 	"[ altname=[critical:]SubjectAltName ]\n\t\t" \
3366051Swyllys 	"[ keyusage=[critical:]usage,usage,...]\n\t\t" \
3376051Swyllys 	"[ format=der|pem ]\n\t\t" \
33811973Swyllys.ingersoll@sun.com 	"[ keytype=rsa [hash=md5 | sha1 | sha256 | sha384 | sha512]]\n\t\t" \
33911973Swyllys.ingersoll@sun.com 	"[ keytype=dsa [hash=sha1 | sha256 ]]\n\t\t" \
3406051Swyllys 	"[ keylen=key-size ]\n\t\t" \
3416051Swyllys 	"[ eku=[critical:]EKU name,...]\n\t\t" \
3426354Swyllys 	"[ lifetime=number-hour|number-day|number-year ]\n\t"
3436051Swyllys 
3446051Swyllys #define	GENCSR_IDX 7
3456354Swyllys #define	GENCSR_VERB "gencsr"
3466051Swyllys #define	GENCSR_SUMM gettext("creates a PKCS#10 certificate signing " \
3476051Swyllys 	"request file")
3486051Swyllys 
3496354Swyllys #define	GENCSR_SYN \
35011973Swyllys.ingersoll@sun.com 	"gencsr listcurves\n\t" \
35111973Swyllys.ingersoll@sun.com \
35210241Swyllys.ingersoll@sun.com 	"gencsr keystore=nss \n\t\t" \
3536051Swyllys 	"nickname=cert-nickname\n\t\t" \
3546051Swyllys 	"outcsr=csr-fn\n\t\t" \
35510241Swyllys.ingersoll@sun.com 	"[ -i ] | [subject=subject-DN]\n\t\t" \
3566051Swyllys 	"[ altname=[critical:]SubjectAltName ]\n\t\t" \
3576051Swyllys 	"[ keyusage=[critical:]usage,usage,...]\n\t\t" \
3586051Swyllys 	"[ token=token[:manuf[:serial]]]\n\t\t" \
3596051Swyllys 	"[ dir=directory-path ]\n\t\t" \
3606051Swyllys 	"[ prefix=DBprefix ]\n\t\t" \
36111973Swyllys.ingersoll@sun.com 	"[ keytype=rsa | ec [curve=ECC Curve Name] " \
36211973Swyllys.ingersoll@sun.com 	"[hash=md5 | sha1 | sha256 | sha384 | sha512]]\n\t\t" \
36311973Swyllys.ingersoll@sun.com 	"[ keytype=dsa [hash=sha1]]\n\t\t" \
3646051Swyllys 	"[ keylen=key-size ]\n\t\t" \
3656051Swyllys 	"[ eku=[critical:]EKU name,...]\n\t\t" \
3666051Swyllys 	"[ format=pem|der ]\n\t" \
3676051Swyllys  \
36810241Swyllys.ingersoll@sun.com 	"gencsr [ keystore=pkcs11 ]\n\t\t" \
3696051Swyllys 	"label=key-label\n\t\t" \
3706051Swyllys 	"outcsr=csr-fn\n\t\t" \
37110241Swyllys.ingersoll@sun.com 	"[ -i ] | [subject=subject-DN]\n\t\t" \
3726051Swyllys 	"[ altname=[critical:]SubjectAltName ]\n\t\t" \
3736051Swyllys 	"[ keyusage=[critical:]usage,usage,...]\n\t\t" \
3746051Swyllys 	"[ token=token[:manuf[:serial]]]\n\t\t" \
37511973Swyllys.ingersoll@sun.com 	"[ keytype=rsa | ec [curve=ECC Curve Name] " \
37611973Swyllys.ingersoll@sun.com 	"[hash=md5 | sha1 | sha256 | sha384 | sha512]]\n\t\t" \
37711973Swyllys.ingersoll@sun.com 	"[ keytype=dsa [hash=sha1 | sha256 ]]\n\t\t" \
3786051Swyllys 	"[ keylen=key-size ]\n\t\t" \
3796051Swyllys 	"[ eku=[critical:]EKU name,...]\n\t\t" \
3806051Swyllys 	"[ format=pem|der ]]\n\t" \
3816051Swyllys  \
38210241Swyllys.ingersoll@sun.com 	"gencsr keystore=file\n\t\t" \
3836051Swyllys 	"outcsr=csr-fn\n\t\t" \
3846051Swyllys 	"outkey=key-fn\n\t\t" \
38510241Swyllys.ingersoll@sun.com 	"[ -i ] | [subject=subject-DN]\n\t\t" \
3866051Swyllys 	"[ altname=[critical:]SubjectAltName ]\n\t\t" \
3876051Swyllys 	"[ keyusage=[critical:]usage,usage,...]\n\t\t" \
38811973Swyllys.ingersoll@sun.com 	"[ keytype=rsa [hash=md5 | sha1 | sha256 | sha384 | sha512]]\n\t\t" \
38911973Swyllys.ingersoll@sun.com 	"[ keytype=dsa [hash=sha1 | sha256 ]]\n\t\t" \
3906051Swyllys 	"[ keylen=key-size ]\n\t\t" \
3916051Swyllys 	"[ eku=[critical:]EKU name,...]\n\t\t" \
3926354Swyllys 	"[ format=pem|der ]\n\t"
3936051Swyllys 
3946051Swyllys #define	DOWNLOAD_IDX 8
3956354Swyllys #define	DOWNLOAD_VERB "download"
3966051Swyllys #define	DOWNLOAD_SUMM gettext("downloads a CRL or certificate file " \
3976051Swyllys 	"from an external source")
3986354Swyllys #define	DOWNLOAD_SYN \
3996051Swyllys 	"download url=url_str\n\t\t" \
4006051Swyllys 	"[ objtype=crl|cert ]\n\t\t" \
4016051Swyllys 	"[ http_proxy=proxy_str ]\n\t\t" \
4026354Swyllys 	"[ outfile = outfile ]\n\t"
4036051Swyllys 
4046051Swyllys #define	GENKEY_IDX 9
4056354Swyllys #define	GENKEY_VERB "genkey"
4066051Swyllys #define	GENKEY_SUMM gettext("creates a symmetric key in the keystore")
4076354Swyllys #define	GENKEY_SYN \
4086051Swyllys 	"genkey [ keystore=pkcs11 ]\n\t\t" \
4096051Swyllys 	"label=key-label\n\t\t" \
4106051Swyllys 	"[ keytype=aes|arcfour|des|3des|generic ]\n\t\t" \
4116051Swyllys 	"[ keylen=key-size (AES, ARCFOUR or GENERIC only)]\n\t\t" \
4126051Swyllys 	"[ token=token[:manuf[:serial]]]\n\t\t" \
4136051Swyllys 	"[ sensitive=y|n ]\n\t\t" \
4146051Swyllys 	"[ extractable=y|n ]\n\t\t" \
4156051Swyllys 	"[ print=y|n ]\n\t" \
4166051Swyllys  \
4176051Swyllys 	"genkey keystore=nss\n\t\t" \
4186051Swyllys 	"label=key-label\n\t\t" \
4196051Swyllys 	"[ keytype=aes|arcfour|des|3des|generic ]\n\t\t" \
4206051Swyllys 	"[ keylen=key-size (AES, ARCFOUR or GENERIC only)]\n\t\t" \
4216051Swyllys 	"[ token=token[:manuf[:serial]]]\n\t\t" \
4226051Swyllys 	"[ dir=directory-path ]\n\t\t" \
4236051Swyllys 	"[ prefix=DBprefix ]\n\t" \
4246051Swyllys  \
4256051Swyllys 	"genkey keystore=file\n\t\t" \
4266051Swyllys 	"outkey=key-fn\n\t\t" \
4276051Swyllys 	"[ keytype=aes|arcfour|des|3des|generic ]\n\t\t" \
4286051Swyllys 	"[ keylen=key-size (AES, ARCFOUR or GENERIC only)]\n\t\t" \
4296354Swyllys 	"[ print=y|n ]\n\t"
4306051Swyllys 
4316051Swyllys #define	SIGNCSR_IDX 10
4326354Swyllys #define	SIGNCSR_VERB "signcsr"
4336051Swyllys #define	SIGNCSR_SUMM gettext("Sign a PKCS#10 Certificate Signing Request")
4346354Swyllys #define	SIGNCSR_SYN \
4356051Swyllys 	"signcsr keystore=pkcs11\n\t\t" \
4366051Swyllys 	"signkey=label (label of signing key)\n\t\t" \
4376051Swyllys 	"csr=CSR filename\n\t\t" \
4386051Swyllys 	"serial=serial number hex string\n\t\t" \
4396051Swyllys 	"outcert=filename for final certificate\n\t\t" \
4406051Swyllys 	"issuer=issuer-DN\n\t\t" \
441*12234Swyllys.ingersoll@sun.com 	"[ store=y|n ] (store the new cert on the token, default=n)\n\t\t" \
4426051Swyllys 	"[ outlabel=certificate label ]\n\t\t" \
4436051Swyllys 	"[ format=pem|der ] (output format)\n\t\t" \
4446051Swyllys 	"[ subject=subject-DN ] (new subject name)\n\t\t" \
4456051Swyllys 	"[ altname=subjectAltName ]\n\t\t" \
4466051Swyllys 	"[ keyusage=[critical:]usage,...]\n\t\t" \
4476051Swyllys 	"[ eku=[critical:]EKU Name,...]\n\t\t" \
4486051Swyllys 	"[ lifetime=number-hour|number-day|number-year ]\n\t\t" \
4496051Swyllys 	"[ token=token[:manuf[:serial]]]\n\t" \
4506051Swyllys  \
4516051Swyllys 	"signcsr keystore=file\n\t\t" \
4526051Swyllys 	"signkey=filename\n\t\t" \
4536051Swyllys 	"csr=CSR filename\n\t\t" \
4546051Swyllys 	"serial=serial number hex string\n\t\t" \
4556051Swyllys 	"outcert=filename for final certificate\n\t\t" \
4566051Swyllys 	"issuer=issuer-DN\n\t\t" \
4576051Swyllys 	"[ format=pem|der ] (output format)\n\t\t" \
4586051Swyllys 	"[ subject=subject-DN ] (new subject name)\n\t\t" \
4596051Swyllys 	"[ altname=subjectAltName ]\n\t\t" \
4606051Swyllys 	"[ keyusage=[critical:]usage,...]\n\t\t" \
4616051Swyllys 	"[ lifetime=number-hour|number-day|number-year ]\n\t\t" \
4626051Swyllys 	"[ eku=[critical:]EKU Name,...]\n\t" \
4636051Swyllys  \
4646051Swyllys 	"signcsr keystore=nss\n\t\t" \
4656051Swyllys 	"signkey=label (label of signing key)\n\t\t" \
4666051Swyllys 	"csr=CSR filename\n\t\t" \
4676051Swyllys 	"serial=serial number hex string\n\t\t" \
4686051Swyllys 	"outcert=filename for final certificate\n\t\t" \
4696051Swyllys 	"issuer=issuer-DN\n\t\t" \
4706051Swyllys 	"[ store=y|n ] (store the new cert in NSS DB, default=n)\n\t\t" \
4716051Swyllys 	"[ outlabel=certificate label ]\n\t\t" \
4726051Swyllys 	"[ format=pem|der ] (output format)\n\t\t" \
4736051Swyllys 	"[ subject=subject-DN ] (new subject name)\n\t\t" \
4746051Swyllys 	"[ altname=subjectAltName ]\n\t\t" \
4756051Swyllys 	"[ keyusage=[critical:]usage,...]\n\t\t" \
4766051Swyllys 	"[ eku=[critical:]EKU Name,...]\n\t\t" \
4776051Swyllys 	"[ lifetime=number-hour|number-day|number-year ]\n\t\t" \
4786051Swyllys 	"[ token=token[:manuf[:serial]]]\n\t\t" \
4796051Swyllys 	"[ dir=directory-path ]\n\t\t" \
4806354Swyllys 	"[ prefix=DBprefix ]\n\t"
4816051Swyllys 
4829126SWyllys.Ingersoll@Sun.COM #define	INITTOKEN_IDX 11
4839126SWyllys.Ingersoll@Sun.COM #define	INITTOKEN_VERB "inittoken"
4849126SWyllys.Ingersoll@Sun.COM #define	INITTOKEN_SUMM gettext("Initialize a PKCS11 token")
4859126SWyllys.Ingersoll@Sun.COM #define	INITTOKEN_SYN \
4869126SWyllys.Ingersoll@Sun.COM 	"inittoken \n\t\t" \
4879126SWyllys.Ingersoll@Sun.COM 	"[ currlabel=token[:manuf[:serial]]]\n\t\t" \
4889126SWyllys.Ingersoll@Sun.COM 	"[ newlabel=new token label ]\n\t"
4899126SWyllys.Ingersoll@Sun.COM 
49011973Swyllys.ingersoll@sun.com #define	GENKEYPAIR_IDX 12
49111973Swyllys.ingersoll@sun.com #define	GENKEYPAIR_VERB "genkeypair"
49211973Swyllys.ingersoll@sun.com #define	GENKEYPAIR_SUMM gettext("creates an asymmetric keypair")
49311973Swyllys.ingersoll@sun.com #define	GENKEYPAIR_SYN \
49411973Swyllys.ingersoll@sun.com 	"genkeypair listcurves\n\t" \
49511973Swyllys.ingersoll@sun.com \
49611973Swyllys.ingersoll@sun.com 	"genkeypair keystore=nss\n\t\t" \
49711973Swyllys.ingersoll@sun.com 	"label=key-nickname\n\t\t" \
49811973Swyllys.ingersoll@sun.com 	"[ token=token[:manuf[:serial]]]\n\t\t" \
49911973Swyllys.ingersoll@sun.com 	"[ dir=directory-path ]\n\t\t" \
50011973Swyllys.ingersoll@sun.com 	"[ prefix=DBprefix ]\n\t\t" \
50111973Swyllys.ingersoll@sun.com 	"[ keytype=rsa | dsa | ec [curve=ECC Curve Name]]\n\t\t" \
50211973Swyllys.ingersoll@sun.com 	"[ keylen=key-size ]\n\t" \
50311973Swyllys.ingersoll@sun.com  \
50411973Swyllys.ingersoll@sun.com 	"genkeypair [ keystore=pkcs11 ]\n\t\t" \
50511973Swyllys.ingersoll@sun.com 	"label=key-label\n\t\t" \
50611973Swyllys.ingersoll@sun.com 	"[ token=token[:manuf[:serial]]]\n\t\t" \
50711973Swyllys.ingersoll@sun.com 	"[ keytype=rsa | dsa | ec [curve=ECC Curve Name]]\n\t\t" \
50811973Swyllys.ingersoll@sun.com 	"[ keylen=key-size ]\n\t" \
50911973Swyllys.ingersoll@sun.com  \
51011973Swyllys.ingersoll@sun.com 	"genkeypair keystore=file\n\t\t" \
51111973Swyllys.ingersoll@sun.com 	"outkey=key_filename\n\t\t" \
51211973Swyllys.ingersoll@sun.com 	"[ format=der|pem ]\n\t\t" \
51311973Swyllys.ingersoll@sun.com 	"[ keytype=rsa|dsa ]\n\t\t" \
51411973Swyllys.ingersoll@sun.com 	"[ keylen=key-size ]\n\t"
51511973Swyllys.ingersoll@sun.com 
51611973Swyllys.ingersoll@sun.com #define	HELP_IDX 13
5176354Swyllys #define	HELP_VERB "help"
5186051Swyllys #define	HELP_SUMM gettext("displays help message")
5196354Swyllys #define	HELP_SYN "help\t(help and usage)"
5206051Swyllys 
5210Sstevel@tonic-gate /* Command structure for verbs and their actions.  Do NOT i18n/l10n. */
5220Sstevel@tonic-gate static verbcmd	cmds[] = {
5236051Swyllys 	{ NULL,	pk_tokens, 0, NULL, NULL},
5246051Swyllys 	{ NULL,	pk_setpin, 0, NULL, NULL},
5256051Swyllys 	{ NULL, pk_list, 0, NULL, NULL},
5266051Swyllys 	{ NULL, pk_delete, 0, NULL, NULL},
5276051Swyllys 	{ NULL,	pk_import, 0, NULL, NULL},
5286051Swyllys 	{ NULL,	pk_export, 0, NULL, NULL},
5296051Swyllys 	{ NULL,	pk_gencert, 0, NULL, NULL},
5306051Swyllys 	{ NULL,	pk_gencsr, 0, NULL, NULL},
5316051Swyllys 	{ NULL,	pk_download, 0, NULL, NULL},
5326051Swyllys 	{ NULL,	pk_genkey, 0, NULL, NULL},
5336051Swyllys 	{ NULL, pk_signcsr, 0, NULL, NULL},
5349126SWyllys.Ingersoll@Sun.COM 	{ NULL, pk_inittoken, 0, NULL, NULL},
53511973Swyllys.ingersoll@sun.com 	{ NULL, pk_genkeypair, 0, NULL, NULL},
5366051Swyllys 	{ NULL,	pk_help, 0, NULL, NULL}
5370Sstevel@tonic-gate };
5383501Swyllys 
5390Sstevel@tonic-gate static int	num_cmds = sizeof (cmds) / sizeof (verbcmd);
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate static char	*prog;
5423089Swyllys static void	usage(int);
5430Sstevel@tonic-gate 
5446051Swyllys static void
init_command_list()5456051Swyllys init_command_list()
5466051Swyllys {
5476051Swyllys 	cmds[TOKEN_IDX].verb = TOKEN_VERB;
5486051Swyllys 	cmds[TOKEN_IDX].summary = TOKEN_SUMM;
5496051Swyllys 	cmds[TOKEN_IDX].synopsis = TOKEN_SYN;
5506051Swyllys 
5516051Swyllys 	cmds[SETPIN_IDX].verb = SETPIN_VERB;
5526051Swyllys 	cmds[SETPIN_IDX].summary = SETPIN_SUMM;
5536051Swyllys 	cmds[SETPIN_IDX].synopsis = SETPIN_SYN;
5546051Swyllys 
5556051Swyllys 	cmds[LIST_IDX].verb = LIST_VERB;
5566051Swyllys 	cmds[LIST_IDX].summary = LIST_SUMM;
5576051Swyllys 	cmds[LIST_IDX].synopsis = LIST_SYN;
5586051Swyllys 
5596051Swyllys 	cmds[DELETE_IDX].verb = DELETE_VERB;
5606051Swyllys 	cmds[DELETE_IDX].summary = DELETE_SUMM;
5616051Swyllys 	cmds[DELETE_IDX].synopsis = DELETE_SYN;
5626051Swyllys 
5636051Swyllys 	cmds[IMPORT_IDX].verb = IMPORT_VERB;
5646051Swyllys 	cmds[IMPORT_IDX].summary = IMPORT_SUMM;
5656051Swyllys 	cmds[IMPORT_IDX].synopsis = IMPORT_SYN;
5666051Swyllys 
5676051Swyllys 	cmds[EXPORT_IDX].verb = EXPORT_VERB;
5686051Swyllys 	cmds[EXPORT_IDX].summary = EXPORT_SUMM;
5696051Swyllys 	cmds[EXPORT_IDX].synopsis = EXPORT_SYN;
5706051Swyllys 
5716051Swyllys 	cmds[GENCERT_IDX].verb = GENCERT_VERB;
5726051Swyllys 	cmds[GENCERT_IDX].summary = GENCERT_SUMM;
5736051Swyllys 	cmds[GENCERT_IDX].synopsis = GENCERT_SYN;
5746051Swyllys 
5756051Swyllys 	cmds[GENCSR_IDX].verb = GENCSR_VERB;
5766051Swyllys 	cmds[GENCSR_IDX].summary = GENCSR_SUMM;
5776051Swyllys 	cmds[GENCSR_IDX].synopsis = GENCSR_SYN;
5786051Swyllys 
5796051Swyllys 	cmds[DOWNLOAD_IDX].verb = DOWNLOAD_VERB;
5806051Swyllys 	cmds[DOWNLOAD_IDX].summary = DOWNLOAD_SUMM;
5816051Swyllys 	cmds[DOWNLOAD_IDX].synopsis = DOWNLOAD_SYN;
5826051Swyllys 
5836051Swyllys 	cmds[GENKEY_IDX].verb = GENKEY_VERB;
5846051Swyllys 	cmds[GENKEY_IDX].summary = GENKEY_SUMM;
5856051Swyllys 	cmds[GENKEY_IDX].synopsis = GENKEY_SYN;
5866051Swyllys 
5876051Swyllys 	cmds[SIGNCSR_IDX].verb = SIGNCSR_VERB;
5886051Swyllys 	cmds[SIGNCSR_IDX].summary = SIGNCSR_SUMM;
5896051Swyllys 	cmds[SIGNCSR_IDX].synopsis = SIGNCSR_SYN;
5906051Swyllys 
5919126SWyllys.Ingersoll@Sun.COM 	cmds[INITTOKEN_IDX].verb = INITTOKEN_VERB;
5929126SWyllys.Ingersoll@Sun.COM 	cmds[INITTOKEN_IDX].summary = INITTOKEN_SUMM;
5939126SWyllys.Ingersoll@Sun.COM 	cmds[INITTOKEN_IDX].synopsis = INITTOKEN_SYN;
5949126SWyllys.Ingersoll@Sun.COM 
59511973Swyllys.ingersoll@sun.com 	cmds[GENKEYPAIR_IDX].verb = GENKEYPAIR_VERB;
59611973Swyllys.ingersoll@sun.com 	cmds[GENKEYPAIR_IDX].summary = GENKEYPAIR_SUMM;
59711973Swyllys.ingersoll@sun.com 	cmds[GENKEYPAIR_IDX].synopsis = GENKEYPAIR_SYN;
59811973Swyllys.ingersoll@sun.com 
5996051Swyllys 	cmds[HELP_IDX].verb = HELP_VERB;
6006051Swyllys 	cmds[HELP_IDX].summary = HELP_SUMM;
6016051Swyllys 	cmds[HELP_IDX].synopsis = HELP_SYN;
6026051Swyllys }
6036051Swyllys 
6040Sstevel@tonic-gate /*
6050Sstevel@tonic-gate  * Usage information.  This function must be updated when new verbs or
6060Sstevel@tonic-gate  * options are added.
6070Sstevel@tonic-gate  */
6080Sstevel@tonic-gate static void
usage(int idx)6093089Swyllys usage(int idx)
6100Sstevel@tonic-gate {
61117Sdinak 	int	i;
61217Sdinak 
61317Sdinak 	/* Display this block only in command-line mode. */
61417Sdinak 	(void) fprintf(stdout, gettext("Usage:\n"));
6153501Swyllys 	(void) fprintf(stdout, gettext("   %s -?\t(help and usage)\n"),
6164829Shylee 	    prog);
6173501Swyllys 	(void) fprintf(stdout, gettext("   %s -f option_file\n"), prog);
6183501Swyllys 	(void) fprintf(stdout, gettext("   %s subcommand [options...]\n"),
6194829Shylee 	    prog);
62017Sdinak 	(void) fprintf(stdout, gettext("where subcommands may be:\n"));
62117Sdinak 
62217Sdinak 	/* Display only those verbs that match the current tool mode. */
6233089Swyllys 	if (idx == -1) {
6243089Swyllys 		for (i = 0; i < num_cmds; i++) {
6253089Swyllys 			/* Do NOT i18n/l10n. */
6263501Swyllys 			(void) fprintf(stdout, "   %-8s	- %s\n",
6274829Shylee 			    cmds[i].verb, cmds[i].summary);
6283089Swyllys 		}
6296354Swyllys 		(void) fprintf(stdout, "%s \'help\'.\n"
6306354Swyllys 		    "Ex: pktool gencert help\n\n",
6316354Swyllys 		    gettext("\nFurther details on the "
6326354Swyllys 		    "subcommands can be found by adding"));
6333089Swyllys 	} else {
6343089Swyllys 		(void) fprintf(stdout, "\t%s\n", cmds[idx].synopsis);
63517Sdinak 	}
63617Sdinak }
63717Sdinak 
63817Sdinak /*
63917Sdinak  * Provide help, in the form of displaying the usage.
64017Sdinak  */
64117Sdinak static int
pk_help(int argc,char * argv[])64217Sdinak pk_help(int argc, char *argv[])
64317Sdinak /* ARGSUSED */
64417Sdinak {
6453089Swyllys 	usage(-1);
6463089Swyllys 	return (0);
6473089Swyllys }
6483089Swyllys 
6493089Swyllys /*
6503089Swyllys  * Process arguments from the argfile and create a new
6513089Swyllys  * argv/argc list to be processed later.
6523089Swyllys  */
6533089Swyllys static int
process_arg_file(char * argfile,char *** argv,int * argc)6543089Swyllys process_arg_file(char *argfile, char ***argv, int *argc)
6553089Swyllys {
6563089Swyllys 	FILE *fp;
6573089Swyllys 	char argline[2 * BUFSIZ]; /* 2048 bytes should be plenty */
6583089Swyllys 	char *p;
6593089Swyllys 	int nargs = 0;
6603089Swyllys 
6613089Swyllys 	if ((fp = fopen(argfile, "rF")) == NULL) {
6623089Swyllys 		(void) fprintf(stderr,
6634829Shylee 		    gettext("Cannot read argfile %s: %s\n"),
6644829Shylee 		    argfile, strerror(errno));
6653089Swyllys 		return (errno);
6663089Swyllys 	}
66717Sdinak 
6683089Swyllys 	while (fgets(argline, sizeof (argline), fp) != NULL) {
6693089Swyllys 		int j;
6703089Swyllys 		/* remove trailing whitespace */
6713089Swyllys 		j = strlen(argline) - 1;
6723089Swyllys 		while (j >= 0 && isspace(argline[j])) {
6733089Swyllys 			argline[j] = 0;
6743089Swyllys 			j--;
6753089Swyllys 		}
6763089Swyllys 		/* If it was a blank line, get the next one. */
6773089Swyllys 		if (!strlen(argline))
6783089Swyllys 			continue;
6793089Swyllys 
6805051Swyllys 		(*argv) = realloc((*argv),
6815051Swyllys 		    (nargs + 1) * sizeof (char *));
6823089Swyllys 		if ((*argv) == NULL) {
6833089Swyllys 			perror("memory error");
6843089Swyllys 			(void) fclose(fp);
6853089Swyllys 			return (errno);
6863089Swyllys 		}
6873089Swyllys 		p = (char *)strdup(argline);
6883089Swyllys 		if (p == NULL) {
6893089Swyllys 			perror("memory error");
6903089Swyllys 			(void) fclose(fp);
6913089Swyllys 			return (errno);
6923089Swyllys 		}
6933089Swyllys 		(*argv)[nargs] = p;
6943089Swyllys 		nargs++;
6953089Swyllys 	}
6963089Swyllys 	*argc = nargs;
6973089Swyllys 	(void) fclose(fp);
69817Sdinak 	return (0);
6990Sstevel@tonic-gate }
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate /*
7020Sstevel@tonic-gate  * MAIN() -- where all the action is
7030Sstevel@tonic-gate  */
7040Sstevel@tonic-gate int
main(int argc,char * argv[],char * envp[])7050Sstevel@tonic-gate main(int argc, char *argv[], char *envp[])
7060Sstevel@tonic-gate /* ARGSUSED2 */
7070Sstevel@tonic-gate {
7080Sstevel@tonic-gate 	int	i, found = -1;
7090Sstevel@tonic-gate 	int	rv;
7100Sstevel@tonic-gate 	int	pk_argc = 0;
7110Sstevel@tonic-gate 	char	**pk_argv = NULL;
71217Sdinak 	int	save_errno = 0;
7130Sstevel@tonic-gate 
7140Sstevel@tonic-gate 	/* Set up for i18n/l10n. */
7150Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
7160Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)		/* Should be defined by cc -D. */
7170Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it isn't. */
7180Sstevel@tonic-gate #endif
7190Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
7200Sstevel@tonic-gate 
7216051Swyllys 	init_command_list();
7226051Swyllys 
7230Sstevel@tonic-gate 	/* Get program base name and move pointer over 0th arg. */
7240Sstevel@tonic-gate 	prog = basename(argv[0]);
7250Sstevel@tonic-gate 	argv++, argc--;
7260Sstevel@tonic-gate 
7270Sstevel@tonic-gate 	/* Set up for debug and error output. */
7280Sstevel@tonic-gate 	if (argc == 0) {
7293089Swyllys 		usage(-1);
7300Sstevel@tonic-gate 		return (1);
7310Sstevel@tonic-gate 	}
7320Sstevel@tonic-gate 
73317Sdinak 	/* Check for help options.  For CLIP-compliance. */
7343089Swyllys 	if (strcmp(argv[0], "-?") == 0) {
7353089Swyllys 		return (pk_help(argc, argv));
7363089Swyllys 	} else if (strcmp(argv[0], "-f") == 0 && argc == 2) {
7373089Swyllys 		rv = process_arg_file(argv[1], &pk_argv, &pk_argc);
7383089Swyllys 		if (rv)
7393089Swyllys 			return (rv);
7403089Swyllys 	} else if (argc >= 1 && argv[0][0] == '-') {
7413089Swyllys 		usage(-1);
7423089Swyllys 		return (1);
74317Sdinak 	}
74417Sdinak 
74517Sdinak 	/* Always turns off Metaslot so that we can see softtoken. */
7460Sstevel@tonic-gate 	if (setenv("METASLOT_ENABLED", "false", 1) < 0) {
74717Sdinak 		save_errno = errno;
7480Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
74917Sdinak 		    gettext("Disabling Metaslot failed (%s)."),
75017Sdinak 		    strerror(save_errno));
7510Sstevel@tonic-gate 		return (1);
7520Sstevel@tonic-gate 	}
7530Sstevel@tonic-gate 
7540Sstevel@tonic-gate 	/* Begin parsing command line. */
7553089Swyllys 	if (pk_argc == 0 && pk_argv == NULL) {
7563089Swyllys 		pk_argc = argc;
7573089Swyllys 		pk_argv = argv;
7583089Swyllys 	}
7590Sstevel@tonic-gate 
76017Sdinak 	/* Check for valid verb (or an abbreviation of it). */
7610Sstevel@tonic-gate 	found = -1;
7620Sstevel@tonic-gate 	for (i = 0; i < num_cmds; i++) {
7630Sstevel@tonic-gate 		if (strcmp(cmds[i].verb, pk_argv[0]) == 0) {
7640Sstevel@tonic-gate 			if (found < 0) {
7650Sstevel@tonic-gate 				found = i;
7660Sstevel@tonic-gate 				break;
7670Sstevel@tonic-gate 			}
7680Sstevel@tonic-gate 		}
7690Sstevel@tonic-gate 	}
7700Sstevel@tonic-gate 	/* Stop here if no valid verb found. */
7710Sstevel@tonic-gate 	if (found < 0) {
77217Sdinak 		cryptoerror(LOG_STDERR, gettext("Invalid verb: %s"),
77317Sdinak 		    pk_argv[0]);
7740Sstevel@tonic-gate 		return (1);
7750Sstevel@tonic-gate 	}
7760Sstevel@tonic-gate 
7770Sstevel@tonic-gate 	/* Get to work! */
7780Sstevel@tonic-gate 	rv = (*cmds[found].action)(pk_argc, pk_argv);
7790Sstevel@tonic-gate 	switch (rv) {
7800Sstevel@tonic-gate 	case PK_ERR_NONE:
7810Sstevel@tonic-gate 		break;		/* Command succeeded, do nothing. */
7820Sstevel@tonic-gate 	case PK_ERR_USAGE:
7833089Swyllys 		usage(found);
7840Sstevel@tonic-gate 		break;
7850Sstevel@tonic-gate 	case PK_ERR_QUIT:
7860Sstevel@tonic-gate 		exit(0);
7870Sstevel@tonic-gate 		/* NOTREACHED */
78817Sdinak 	case PK_ERR_PK11:
78917Sdinak 	case PK_ERR_SYSTEM:
79017Sdinak 	case PK_ERR_OPENSSL:
7913089Swyllys 	case PK_ERR_NSS:
7920Sstevel@tonic-gate 	default:
7930Sstevel@tonic-gate 		break;
7940Sstevel@tonic-gate 	}
7950Sstevel@tonic-gate 	return (rv);
7960Sstevel@tonic-gate }
797