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 /* 229126SWyllys.Ingersoll@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate /* 270Sstevel@tonic-gate * This file comprises the main driver for this tool. 2817Sdinak * Upon parsing the command verbs from user input, it 2917Sdinak * branches to the appropriate modules to perform the 3017Sdinak * requested task. 310Sstevel@tonic-gate */ 320Sstevel@tonic-gate 330Sstevel@tonic-gate #include <stdio.h> 340Sstevel@tonic-gate #include <string.h> 350Sstevel@tonic-gate #include <ctype.h> 360Sstevel@tonic-gate #include <malloc.h> 376051Swyllys #include <libintl.h> 380Sstevel@tonic-gate #include <libgen.h> 390Sstevel@tonic-gate #include <errno.h> 400Sstevel@tonic-gate #include <cryptoutil.h> 410Sstevel@tonic-gate #include <security/cryptoki.h> 420Sstevel@tonic-gate #include "common.h" 430Sstevel@tonic-gate 440Sstevel@tonic-gate /* 450Sstevel@tonic-gate * The verbcmd construct allows genericizing information about a verb so 460Sstevel@tonic-gate * that it is easier to manipulate. Makes parsing code easier to read, 470Sstevel@tonic-gate * fix, and extend with new verbs. 480Sstevel@tonic-gate */ 490Sstevel@tonic-gate typedef struct verbcmd_s { 500Sstevel@tonic-gate char *verb; 510Sstevel@tonic-gate int (*action)(int, char *[]); 5217Sdinak int mode; 533501Swyllys char *summary; 5417Sdinak char *synopsis; 550Sstevel@tonic-gate } verbcmd; 560Sstevel@tonic-gate 570Sstevel@tonic-gate /* External declarations for supported verb actions. */ 580Sstevel@tonic-gate extern int pk_setpin(int argc, char *argv[]); 5917Sdinak extern int pk_list(int argc, char *argv[]); 6017Sdinak extern int pk_delete(int argc, char *argv[]); 6117Sdinak extern int pk_import(int argc, char *argv[]); 6217Sdinak extern int pk_export(int argc, char *argv[]); 6317Sdinak extern int pk_tokens(int argc, char *argv[]); 643089Swyllys extern int pk_gencert(int argc, char *argv[]); 653089Swyllys extern int pk_gencsr(int argc, char *argv[]); 663089Swyllys extern int pk_download(int argc, char *argv[]); 673089Swyllys extern int pk_genkey(int argc, char *argv[]); 686051Swyllys extern int pk_signcsr(int argc, char *argv[]); 699126SWyllys.Ingersoll@Sun.COM extern int pk_inittoken(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 "[ subject=subject-DN ]\n\t\t" \ 1136051Swyllys "[ label=key-label ]\n\t\t" \ 1146051Swyllys "[ token=token[:manuf[:serial]]]\n\t" \ 1156051Swyllys \ 1166051Swyllys "list keystore=pkcs11 objtype=crl\n\t\t" \ 1176669Swyllys "infile=crl-fn\n\t" \ 1186051Swyllys \ 1196051Swyllys "list keystore=nss objtype=cert\n\t\t" \ 1206051Swyllys "[ subject=subject-DN ]\n\t\t" \ 1216051Swyllys "[ issuer=issuer-DN ]\n\t\t" \ 1226051Swyllys "[ serial=serial number ]\n\t\t" \ 1236051Swyllys "[ nickname=cert-nickname ]\n\t\t" \ 1246051Swyllys "[ token=token[:manuf[:serial]]]\n\t\t" \ 1256051Swyllys "[ dir=directory-path ]\n\t\t" \ 1266051Swyllys "[ prefix=DBprefix ]\n\t\t" \ 1276051Swyllys "[ criteria=valid|expired|both ]\n\t" \ 1286051Swyllys \ 1296051Swyllys "list keystore=nss objtype=key\n\t\t" \ 1306051Swyllys "[ token=token[:manuf[:serial]]]\n\t\t" \ 1316051Swyllys "[ dir=directory-path ]\n\t\t" \ 1326051Swyllys "[ prefix=DBprefix ]\n\t\t" \ 1336051Swyllys "[ nickname=key-nickname ]\n\t" \ 1346051Swyllys \ 1356051Swyllys "list keystore=file objtype=cert\n\t\t" \ 1366051Swyllys "[ subject=subject-DN ]\n\t\t" \ 1376051Swyllys "[ issuer=issuer-DN ]\n\t\t" \ 1386051Swyllys "[ serial=serial number ]\n\t\t" \ 1396051Swyllys "[ infile=cert-fn ]\n\t\t" \ 1406051Swyllys "[ dir=directory-path ]\n\t\t" \ 1416051Swyllys "[ criteria=valid|expired|both ]\n\t" \ 1426051Swyllys \ 1436051Swyllys "list keystore=file objtype=key\n\t\t" \ 1446051Swyllys "[ infile=key-fn ]\n\t\t" \ 1456051Swyllys "[ dir=directory-path ]\n\t" \ 1466051Swyllys \ 1476051Swyllys "list keystore=file objtype=crl\n\t\t" \ 1486669Swyllys "infile=crl-fn\n\t" 1496051Swyllys 1506051Swyllys #define DELETE_IDX 3 1516354Swyllys #define DELETE_VERB "delete" 1526051Swyllys #define DELETE_SUMM gettext("deletes objects in the keystore") 1536354Swyllys #define DELETE_SYN \ 1546051Swyllys "delete [ token=token[:manuf[:serial]]]\n\t\t" \ 1556051Swyllys "[ objtype=private|public|both ]\n\t\t" \ 1566051Swyllys "[ label=object-label ]\n\t" \ 1576051Swyllys \ 1586051Swyllys "delete keystore=nss objtype=cert\n\t\t" \ 1596051Swyllys "[ subject=subject-DN ]\n\t\t" \ 1606051Swyllys "[ issuer=issuer-DN ]\n\t\t" \ 1616051Swyllys "[ serial=serial number ]\n\t\t" \ 1626051Swyllys "[ label=cert-label ]\n\t\t" \ 1636051Swyllys "[ token=token[:manuf[:serial]]]\n\t\t" \ 1646051Swyllys "[ dir=directory-path ]\n\t\t" \ 1656051Swyllys "[ prefix=DBprefix ]\n\t\t" \ 1666051Swyllys "[ criteria=valid|expired|both ]\n\t" \ 1676051Swyllys \ 1686051Swyllys "delete keystore=nss objtype=key\n\t\t" \ 1696051Swyllys "[ token=token[:manuf[:serial]]]\n\t\t" \ 1706051Swyllys "[ dir=directory-path ]\n\t\t" \ 1716051Swyllys "[ prefix=DBprefix ]\n\t\t" \ 1726051Swyllys "[ nickname=key-nickname ]\n\t\t" \ 1736051Swyllys \ 1746051Swyllys "delete keystore=nss objtype=crl\n\t\t" \ 1756051Swyllys "[ nickname=issuer-nickname ]\n\t\t" \ 1766051Swyllys "[ subject=subject-DN ]\n\t\t" \ 1776051Swyllys "[ token=token[:manuf[:serial]]]\n\t\t" \ 1786051Swyllys "[ dir=directory-path ]\n\t\t" \ 1796051Swyllys "[ prefix=DBprefix ]\n\t" \ 1806051Swyllys \ 1816051Swyllys "delete keystore=pkcs11 " \ 1826051Swyllys "objtype=cert[:[public | private | both]]\n\t\t" \ 1836051Swyllys "[ subject=subject-DN ]\n\t\t" \ 1846051Swyllys "[ issuer=issuer-DN ]\n\t\t" \ 1856051Swyllys "[ serial=serial number ]\n\t\t" \ 1866051Swyllys "[ label=cert-label ]\n\t\t" \ 1876051Swyllys "[ token=token[:manuf[:serial]]]\n\t\t" \ 1886051Swyllys "[ criteria=valid|expired|both ]\n\t" \ 1896051Swyllys \ 1906051Swyllys "delete keystore=pkcs11 " \ 1916051Swyllys "objtype=key[:[public | private | both]]\n\t\t" \ 1926051Swyllys "[ subject=subject-DN ]\n\t\t" \ 1936051Swyllys "[ label=key-label ]\n\t\t" \ 1946051Swyllys "[ token=token[:manuf[:serial]]]\n\t" \ 1956051Swyllys \ 1966051Swyllys "delete keystore=pkcs11 objtype=crl\n\t\t" \ 1976669Swyllys "infile=crl-fn\n\t" \ 1986051Swyllys \ 1996051Swyllys "delete keystore=file objtype=cert\n\t\t" \ 2006051Swyllys "[ subject=subject-DN ]\n\t\t" \ 2016051Swyllys "[ issuer=issuer-DN ]\n\t\t" \ 2026051Swyllys "[ serial=serial number ]\n\t\t" \ 2036051Swyllys "[ infile=cert-fn ]\n\t\t" \ 2046051Swyllys "[ dir=directory-path ]\n\t\t" \ 2056051Swyllys "[ criteria=valid|expired|both ]\n\t" \ 2066051Swyllys \ 2076051Swyllys "delete keystore=file objtype=key\n\t\t" \ 2086051Swyllys "[ infile=key-fn ]\n\t\t" \ 2096051Swyllys "[ dir=directory-path ]\n\t" \ 2106051Swyllys \ 2116051Swyllys "delete keystore=file objtype=crl\n\t\t" \ 2126669Swyllys "infile=crl-fn\n\t" 2136051Swyllys 2146051Swyllys #define IMPORT_IDX 4 2156354Swyllys #define IMPORT_VERB "import" 2166051Swyllys #define IMPORT_SUMM gettext("imports objects from an external source") 2176354Swyllys #define IMPORT_SYN \ 2186051Swyllys "import [token=token[:manuf[:serial]]]\n\t\t" \ 2196051Swyllys "infile=input-fn\n\t" \ 2206051Swyllys \ 2216051Swyllys "import keystore=nss objtype=cert\n\t\t" \ 2226051Swyllys "infile=input-fn\n\t\t" \ 2236051Swyllys "label=cert-label\n\t\t" \ 2246051Swyllys "[ trust=trust-value ]\n\t\t" \ 2256051Swyllys "[ token=token[:manuf[:serial]]]\n\t\t" \ 2266051Swyllys "[ dir=directory-path ]\n\t\t" \ 2276051Swyllys "[ prefix=DBprefix ]\n\t" \ 2286051Swyllys \ 2296051Swyllys "import keystore=nss objtype=crl\n\t\t" \ 2306051Swyllys "infile=input-fn\n\t\t" \ 2316051Swyllys "[ verifycrl=y|n ]\n\t\t" \ 2326051Swyllys "[ token=token[:manuf[:serial]]]\n\t\t" \ 2336051Swyllys "[ dir=directory-path ]\n\t\t" \ 2346051Swyllys "[ prefix=DBprefix ]\n\t" \ 2356051Swyllys \ 2366051Swyllys "import keystore=pkcs11\n\t\t" \ 2376051Swyllys "infile=input-fn\n\t\t" \ 2386051Swyllys "label=label\n\t\t" \ 2396051Swyllys "[ objtype=cert|key ]\n\t\t" \ 2406051Swyllys "[ keytype=aes|arcfour|des|3des|generic ]\n\t\t" \ 2416051Swyllys "[ sensitive=y|n ]\n\t\t" \ 2426051Swyllys "[ extractable=y|n ]\n\t\t" \ 2436051Swyllys "[ token=token[:manuf[:serial]]]\n\t" \ 2446051Swyllys \ 2456051Swyllys "import keystore=pkcs11 objtype=crl\n\t\t" \ 2466051Swyllys "infile=input-crl-fn\n\t\t" \ 2476051Swyllys "outcrl=output-crl-fn\n\t\t" \ 2486669Swyllys "outformat=pem|der\n\t" \ 2496051Swyllys \ 2506051Swyllys "import keystore=file\n\t\t" \ 2516051Swyllys "infile=input-fn\n\t\t" \ 2526051Swyllys "outkey=output-key-fn\n\t\t" \ 2536051Swyllys "outcert=output-cert-fn\n\t\t" \ 2546051Swyllys "[ outformat=pem|der|pkcs12 ]\n\t" \ 2556051Swyllys \ 2566051Swyllys "import keystore=file objtype=crl\n\t\t" \ 2576051Swyllys "infile=input-crl-fn\n\t\t" \ 2586051Swyllys "outcrl=output-crl-fn\n\t\t" \ 2596669Swyllys "outformat=pem|der\n\t" 2606051Swyllys 2616051Swyllys #define EXPORT_IDX 5 2626354Swyllys #define EXPORT_VERB "export" 2636051Swyllys #define EXPORT_SUMM gettext("exports objects from the keystore to a file") 2646354Swyllys #define EXPORT_SYN \ 2656051Swyllys "export [token=token[:manuf[:serial]]]\n\t\t" \ 2666051Swyllys "outfile=output-fn\n\t" \ 2676051Swyllys \ 2686051Swyllys "export keystore=nss\n\t\t" \ 2696051Swyllys "outfile=output-fn\n\t\t" \ 2706051Swyllys "[ objtype=cert|key ]\n\t\t" \ 2716051Swyllys "[ subject=subject-DN ]\n\t\t" \ 2726051Swyllys "[ issuer=issuer-DN ]\n\t\t" \ 2736051Swyllys "[ serial=serial number ]\n\t\t" \ 2746051Swyllys "[ nickname=cert-nickname ]\n\t\t" \ 2756051Swyllys "[ token=token[:manuf[:serial]]]\n\t\t" \ 2766051Swyllys "[ dir=directory-path ]\n\t\t" \ 2776051Swyllys "[ prefix=DBPrefix ]\n\t\t" \ 2786051Swyllys "[ outformat=pem|der|pkcs12 ]\n\t" \ 2796051Swyllys \ 2806051Swyllys "export keystore=pkcs11\n\t\t" \ 2816051Swyllys "outfile=output-fn\n\t\t" \ 2826051Swyllys "[ objtype=cert|key ]\n\t\t" \ 2836051Swyllys "[ label=label ]\n\t\t" \ 2846051Swyllys "[ subject=subject-DN ]\n\t\t" \ 2856051Swyllys "[ issuer=issuer-DN ]\n\t\t" \ 2866051Swyllys "[ serial=serial number ]\n\t\t" \ 2876051Swyllys "[ outformat=pem|der|pkcs12|raw ]\n\t\t" \ 2886051Swyllys "[ token=token[:manuf[:serial]]]\n\t" \ 2896051Swyllys \ 2906051Swyllys "export keystore=file\n\t\t" \ 2916051Swyllys "certfile=cert-input-fn\n\t\t" \ 2926051Swyllys "keyfile=key-input-fn\n\t\t" \ 2936669Swyllys "outfile=output-pkcs12-fn\n\t" 2946051Swyllys 2956051Swyllys #define GENCERT_IDX 6 2966354Swyllys #define GENCERT_VERB "gencert" 2976051Swyllys #define GENCERT_SUMM gettext("creates a self-signed X.509v3 certificate") 2986354Swyllys #define GENCERT_SYN \ 299*10241Swyllys.ingersoll@sun.com "gencert keystore=nss\n\t\t" \ 3006051Swyllys "label=cert-nickname\n\t\t" \ 3016051Swyllys "serial=serial number hex string]\n\t\t" \ 302*10241Swyllys.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" \ 3086051Swyllys "[ keytype=rsa|dsa ]\n\t\t" \ 3096051Swyllys "[ keylen=key-size ]\n\t\t" \ 3106051Swyllys "[ trust=trust-value ]\n\t\t" \ 3116051Swyllys "[ eku=[critical:]EKU name,...]\n\t\t" \ 3126051Swyllys "[ lifetime=number-hour|number-day|number-year ]\n\t" \ 3136051Swyllys \ 314*10241Swyllys.ingersoll@sun.com "gencert [ keystore=pkcs11 ]\n\t\t" \ 3156051Swyllys "label=key/cert-label\n\t\t" \ 3166051Swyllys "serial=serial number hex string\n\t\t" \ 317*10241Swyllys.ingersoll@sun.com "[ -i ] | [subject=subject-DN]\n\t\t" \ 3186051Swyllys "[ altname=[critical:]SubjectAltName ]\n\t\t" \ 3196051Swyllys "[ keyusage=[critical:]usage,usage,...]\n\t\t" \ 3206051Swyllys "[ token=token[:manuf[:serial]]]\n\t\t" \ 3216051Swyllys "[ keytype=rsa|dsa ]\n\t\t" \ 3226051Swyllys "[ keylen=key-size ]\n\t\t" \ 3236051Swyllys "[ eku=[critical:]EKU name,...]\n\t\t" \ 3246051Swyllys "[ lifetime=number-hour|number-day|number-year ]\n\t" \ 3256051Swyllys \ 326*10241Swyllys.ingersoll@sun.com "gencert keystore=file\n\t\t" \ 3276051Swyllys "outcert=cert_filename\n\t\t" \ 3286051Swyllys "outkey=key_filename\n\t\t" \ 3296051Swyllys "serial=serial number hex string\n\t\t" \ 330*10241Swyllys.ingersoll@sun.com "[ -i ] | [subject=subject-DN]\n\t\t" \ 3316051Swyllys "[ altname=[critical:]SubjectAltName ]\n\t\t" \ 3326051Swyllys "[ keyusage=[critical:]usage,usage,...]\n\t\t" \ 3336051Swyllys "[ format=der|pem ]\n\t\t" \ 3346051Swyllys "[ prefix=DBprefix ]\n\t\t" \ 3356051Swyllys "[ keytype=rsa|dsa ]\n\t\t" \ 3366051Swyllys "[ keylen=key-size ]\n\t\t" \ 3376051Swyllys "[ eku=[critical:]EKU name,...]\n\t\t" \ 3386354Swyllys "[ lifetime=number-hour|number-day|number-year ]\n\t" 3396051Swyllys 3406051Swyllys #define GENCSR_IDX 7 3416354Swyllys #define GENCSR_VERB "gencsr" 3426051Swyllys #define GENCSR_SUMM gettext("creates a PKCS#10 certificate signing " \ 3436051Swyllys "request file") 3446051Swyllys 3456354Swyllys #define GENCSR_SYN \ 346*10241Swyllys.ingersoll@sun.com "gencsr keystore=nss \n\t\t" \ 3476051Swyllys "nickname=cert-nickname\n\t\t" \ 3486051Swyllys "outcsr=csr-fn\n\t\t" \ 349*10241Swyllys.ingersoll@sun.com "[ -i ] | [subject=subject-DN]\n\t\t" \ 3506051Swyllys "[ altname=[critical:]SubjectAltName ]\n\t\t" \ 3516051Swyllys "[ keyusage=[critical:]usage,usage,...]\n\t\t" \ 3526051Swyllys "[ token=token[:manuf[:serial]]]\n\t\t" \ 3536051Swyllys "[ dir=directory-path ]\n\t\t" \ 3546051Swyllys "[ prefix=DBprefix ]\n\t\t" \ 3556051Swyllys "[ keytype=rsa|dsa ]\n\t\t" \ 3566051Swyllys "[ keylen=key-size ]\n\t\t" \ 3576051Swyllys "[ eku=[critical:]EKU name,...]\n\t\t" \ 3586051Swyllys "[ format=pem|der ]\n\t" \ 3596051Swyllys \ 360*10241Swyllys.ingersoll@sun.com "gencsr [ keystore=pkcs11 ]\n\t\t" \ 3616051Swyllys "label=key-label\n\t\t" \ 3626051Swyllys "outcsr=csr-fn\n\t\t" \ 363*10241Swyllys.ingersoll@sun.com "[ -i ] | [subject=subject-DN]\n\t\t" \ 3646051Swyllys "[ altname=[critical:]SubjectAltName ]\n\t\t" \ 3656051Swyllys "[ keyusage=[critical:]usage,usage,...]\n\t\t" \ 3666051Swyllys "[ token=token[:manuf[:serial]]]\n\t\t" \ 3676051Swyllys "[ keytype=rsa|dsa ]\n\t\t" \ 3686051Swyllys "[ keylen=key-size ]\n\t\t" \ 3696051Swyllys "[ eku=[critical:]EKU name,...]\n\t\t" \ 3706051Swyllys "[ format=pem|der ]]\n\t" \ 3716051Swyllys \ 372*10241Swyllys.ingersoll@sun.com "gencsr keystore=file\n\t\t" \ 3736051Swyllys "outcsr=csr-fn\n\t\t" \ 3746051Swyllys "outkey=key-fn\n\t\t" \ 375*10241Swyllys.ingersoll@sun.com "[ -i ] | [subject=subject-DN]\n\t\t" \ 3766051Swyllys "[ altname=[critical:]SubjectAltName ]\n\t\t" \ 3776051Swyllys "[ keyusage=[critical:]usage,usage,...]\n\t\t" \ 3786051Swyllys "[ keytype=rsa|dsa ]\n\t\t" \ 3796051Swyllys "[ keylen=key-size ]\n\t\t" \ 3806051Swyllys "[ eku=[critical:]EKU name,...]\n\t\t" \ 3816354Swyllys "[ format=pem|der ]\n\t" 3826051Swyllys 3836051Swyllys #define DOWNLOAD_IDX 8 3846354Swyllys #define DOWNLOAD_VERB "download" 3856051Swyllys #define DOWNLOAD_SUMM gettext("downloads a CRL or certificate file " \ 3866051Swyllys "from an external source") 3876354Swyllys #define DOWNLOAD_SYN \ 3886051Swyllys "download url=url_str\n\t\t" \ 3896051Swyllys "[ objtype=crl|cert ]\n\t\t" \ 3906051Swyllys "[ http_proxy=proxy_str ]\n\t\t" \ 3916354Swyllys "[ outfile = outfile ]\n\t" 3926051Swyllys 3936051Swyllys #define GENKEY_IDX 9 3946354Swyllys #define GENKEY_VERB "genkey" 3956051Swyllys #define GENKEY_SUMM gettext("creates a symmetric key in the keystore") 3966354Swyllys #define GENKEY_SYN \ 3976051Swyllys "genkey [ keystore=pkcs11 ]\n\t\t" \ 3986051Swyllys "label=key-label\n\t\t" \ 3996051Swyllys "[ keytype=aes|arcfour|des|3des|generic ]\n\t\t" \ 4006051Swyllys "[ keylen=key-size (AES, ARCFOUR or GENERIC only)]\n\t\t" \ 4016051Swyllys "[ token=token[:manuf[:serial]]]\n\t\t" \ 4026051Swyllys "[ sensitive=y|n ]\n\t\t" \ 4036051Swyllys "[ extractable=y|n ]\n\t\t" \ 4046051Swyllys "[ print=y|n ]\n\t" \ 4056051Swyllys \ 4066051Swyllys "genkey keystore=nss\n\t\t" \ 4076051Swyllys "label=key-label\n\t\t" \ 4086051Swyllys "[ keytype=aes|arcfour|des|3des|generic ]\n\t\t" \ 4096051Swyllys "[ keylen=key-size (AES, ARCFOUR or GENERIC only)]\n\t\t" \ 4106051Swyllys "[ token=token[:manuf[:serial]]]\n\t\t" \ 4116051Swyllys "[ dir=directory-path ]\n\t\t" \ 4126051Swyllys "[ prefix=DBprefix ]\n\t" \ 4136051Swyllys \ 4146051Swyllys "genkey keystore=file\n\t\t" \ 4156051Swyllys "outkey=key-fn\n\t\t" \ 4166051Swyllys "[ keytype=aes|arcfour|des|3des|generic ]\n\t\t" \ 4176051Swyllys "[ keylen=key-size (AES, ARCFOUR or GENERIC only)]\n\t\t" \ 4186354Swyllys "[ print=y|n ]\n\t" 4196051Swyllys 4206051Swyllys #define SIGNCSR_IDX 10 4216354Swyllys #define SIGNCSR_VERB "signcsr" 4226051Swyllys #define SIGNCSR_SUMM gettext("Sign a PKCS#10 Certificate Signing Request") 4236354Swyllys #define SIGNCSR_SYN \ 4246051Swyllys "signcsr keystore=pkcs11\n\t\t" \ 4256051Swyllys "signkey=label (label of signing key)\n\t\t" \ 4266051Swyllys "csr=CSR filename\n\t\t" \ 4276051Swyllys "serial=serial number hex string\n\t\t" \ 4286051Swyllys "outcert=filename for final certificate\n\t\t" \ 4296051Swyllys "issuer=issuer-DN\n\t\t" \ 4306051Swyllys "[ store=y|n ] (store the new cert in NSS DB, default=n)\n\t\t" \ 4316051Swyllys "[ outlabel=certificate label ]\n\t\t" \ 4326051Swyllys "[ format=pem|der ] (output format)\n\t\t" \ 4336051Swyllys "[ subject=subject-DN ] (new subject name)\n\t\t" \ 4346051Swyllys "[ altname=subjectAltName ]\n\t\t" \ 4356051Swyllys "[ keyusage=[critical:]usage,...]\n\t\t" \ 4366051Swyllys "[ eku=[critical:]EKU Name,...]\n\t\t" \ 4376051Swyllys "[ lifetime=number-hour|number-day|number-year ]\n\t\t" \ 4386051Swyllys "[ token=token[:manuf[:serial]]]\n\t" \ 4396051Swyllys \ 4406051Swyllys "signcsr keystore=file\n\t\t" \ 4416051Swyllys "signkey=filename\n\t\t" \ 4426051Swyllys "csr=CSR filename\n\t\t" \ 4436051Swyllys "serial=serial number hex string\n\t\t" \ 4446051Swyllys "outcert=filename for final certificate\n\t\t" \ 4456051Swyllys "issuer=issuer-DN\n\t\t" \ 4466051Swyllys "[ format=pem|der ] (output format)\n\t\t" \ 4476051Swyllys "[ subject=subject-DN ] (new subject name)\n\t\t" \ 4486051Swyllys "[ altname=subjectAltName ]\n\t\t" \ 4496051Swyllys "[ keyusage=[critical:]usage,...]\n\t\t" \ 4506051Swyllys "[ lifetime=number-hour|number-day|number-year ]\n\t\t" \ 4516051Swyllys "[ eku=[critical:]EKU Name,...]\n\t" \ 4526051Swyllys \ 4536051Swyllys "signcsr keystore=nss\n\t\t" \ 4546051Swyllys "signkey=label (label of signing key)\n\t\t" \ 4556051Swyllys "csr=CSR filename\n\t\t" \ 4566051Swyllys "serial=serial number hex string\n\t\t" \ 4576051Swyllys "outcert=filename for final certificate\n\t\t" \ 4586051Swyllys "issuer=issuer-DN\n\t\t" \ 4596051Swyllys "[ store=y|n ] (store the new cert in NSS DB, default=n)\n\t\t" \ 4606051Swyllys "[ outlabel=certificate label ]\n\t\t" \ 4616051Swyllys "[ format=pem|der ] (output format)\n\t\t" \ 4626051Swyllys "[ subject=subject-DN ] (new subject name)\n\t\t" \ 4636051Swyllys "[ altname=subjectAltName ]\n\t\t" \ 4646051Swyllys "[ keyusage=[critical:]usage,...]\n\t\t" \ 4656051Swyllys "[ eku=[critical:]EKU Name,...]\n\t\t" \ 4666051Swyllys "[ lifetime=number-hour|number-day|number-year ]\n\t\t" \ 4676051Swyllys "[ token=token[:manuf[:serial]]]\n\t\t" \ 4686051Swyllys "[ dir=directory-path ]\n\t\t" \ 4696354Swyllys "[ prefix=DBprefix ]\n\t" 4706051Swyllys 4719126SWyllys.Ingersoll@Sun.COM #define INITTOKEN_IDX 11 4729126SWyllys.Ingersoll@Sun.COM #define INITTOKEN_VERB "inittoken" 4739126SWyllys.Ingersoll@Sun.COM #define INITTOKEN_SUMM gettext("Initialize a PKCS11 token") 4749126SWyllys.Ingersoll@Sun.COM #define INITTOKEN_SYN \ 4759126SWyllys.Ingersoll@Sun.COM "inittoken \n\t\t" \ 4769126SWyllys.Ingersoll@Sun.COM "[ currlabel=token[:manuf[:serial]]]\n\t\t" \ 4779126SWyllys.Ingersoll@Sun.COM "[ newlabel=new token label ]\n\t" 4789126SWyllys.Ingersoll@Sun.COM 4799126SWyllys.Ingersoll@Sun.COM #define HELP_IDX 12 4806354Swyllys #define HELP_VERB "help" 4816051Swyllys #define HELP_SUMM gettext("displays help message") 4826354Swyllys #define HELP_SYN "help\t(help and usage)" 4836051Swyllys 4840Sstevel@tonic-gate /* Command structure for verbs and their actions. Do NOT i18n/l10n. */ 4850Sstevel@tonic-gate static verbcmd cmds[] = { 4866051Swyllys { NULL, pk_tokens, 0, NULL, NULL}, 4876051Swyllys { NULL, pk_setpin, 0, NULL, NULL}, 4886051Swyllys { NULL, pk_list, 0, NULL, NULL}, 4896051Swyllys { NULL, pk_delete, 0, NULL, NULL}, 4906051Swyllys { NULL, pk_import, 0, NULL, NULL}, 4916051Swyllys { NULL, pk_export, 0, NULL, NULL}, 4926051Swyllys { NULL, pk_gencert, 0, NULL, NULL}, 4936051Swyllys { NULL, pk_gencsr, 0, NULL, NULL}, 4946051Swyllys { NULL, pk_download, 0, NULL, NULL}, 4956051Swyllys { NULL, pk_genkey, 0, NULL, NULL}, 4966051Swyllys { NULL, pk_signcsr, 0, NULL, NULL}, 4979126SWyllys.Ingersoll@Sun.COM { NULL, pk_inittoken, 0, NULL, NULL}, 4986051Swyllys { NULL, pk_help, 0, NULL, NULL} 4990Sstevel@tonic-gate }; 5003501Swyllys 5010Sstevel@tonic-gate static int num_cmds = sizeof (cmds) / sizeof (verbcmd); 5020Sstevel@tonic-gate 5030Sstevel@tonic-gate static char *prog; 5043089Swyllys static void usage(int); 5050Sstevel@tonic-gate 5066051Swyllys static void 5076051Swyllys init_command_list() 5086051Swyllys { 5096051Swyllys cmds[TOKEN_IDX].verb = TOKEN_VERB; 5106051Swyllys cmds[TOKEN_IDX].summary = TOKEN_SUMM; 5116051Swyllys cmds[TOKEN_IDX].synopsis = TOKEN_SYN; 5126051Swyllys 5136051Swyllys cmds[SETPIN_IDX].verb = SETPIN_VERB; 5146051Swyllys cmds[SETPIN_IDX].summary = SETPIN_SUMM; 5156051Swyllys cmds[SETPIN_IDX].synopsis = SETPIN_SYN; 5166051Swyllys 5176051Swyllys cmds[LIST_IDX].verb = LIST_VERB; 5186051Swyllys cmds[LIST_IDX].summary = LIST_SUMM; 5196051Swyllys cmds[LIST_IDX].synopsis = LIST_SYN; 5206051Swyllys 5216051Swyllys cmds[DELETE_IDX].verb = DELETE_VERB; 5226051Swyllys cmds[DELETE_IDX].summary = DELETE_SUMM; 5236051Swyllys cmds[DELETE_IDX].synopsis = DELETE_SYN; 5246051Swyllys 5256051Swyllys cmds[IMPORT_IDX].verb = IMPORT_VERB; 5266051Swyllys cmds[IMPORT_IDX].summary = IMPORT_SUMM; 5276051Swyllys cmds[IMPORT_IDX].synopsis = IMPORT_SYN; 5286051Swyllys 5296051Swyllys cmds[EXPORT_IDX].verb = EXPORT_VERB; 5306051Swyllys cmds[EXPORT_IDX].summary = EXPORT_SUMM; 5316051Swyllys cmds[EXPORT_IDX].synopsis = EXPORT_SYN; 5326051Swyllys 5336051Swyllys cmds[GENCERT_IDX].verb = GENCERT_VERB; 5346051Swyllys cmds[GENCERT_IDX].summary = GENCERT_SUMM; 5356051Swyllys cmds[GENCERT_IDX].synopsis = GENCERT_SYN; 5366051Swyllys 5376051Swyllys cmds[GENCSR_IDX].verb = GENCSR_VERB; 5386051Swyllys cmds[GENCSR_IDX].summary = GENCSR_SUMM; 5396051Swyllys cmds[GENCSR_IDX].synopsis = GENCSR_SYN; 5406051Swyllys 5416051Swyllys cmds[DOWNLOAD_IDX].verb = DOWNLOAD_VERB; 5426051Swyllys cmds[DOWNLOAD_IDX].summary = DOWNLOAD_SUMM; 5436051Swyllys cmds[DOWNLOAD_IDX].synopsis = DOWNLOAD_SYN; 5446051Swyllys 5456051Swyllys cmds[GENKEY_IDX].verb = GENKEY_VERB; 5466051Swyllys cmds[GENKEY_IDX].summary = GENKEY_SUMM; 5476051Swyllys cmds[GENKEY_IDX].synopsis = GENKEY_SYN; 5486051Swyllys 5496051Swyllys cmds[SIGNCSR_IDX].verb = SIGNCSR_VERB; 5506051Swyllys cmds[SIGNCSR_IDX].summary = SIGNCSR_SUMM; 5516051Swyllys cmds[SIGNCSR_IDX].synopsis = SIGNCSR_SYN; 5526051Swyllys 5539126SWyllys.Ingersoll@Sun.COM cmds[INITTOKEN_IDX].verb = INITTOKEN_VERB; 5549126SWyllys.Ingersoll@Sun.COM cmds[INITTOKEN_IDX].summary = INITTOKEN_SUMM; 5559126SWyllys.Ingersoll@Sun.COM cmds[INITTOKEN_IDX].synopsis = INITTOKEN_SYN; 5569126SWyllys.Ingersoll@Sun.COM 5576051Swyllys cmds[HELP_IDX].verb = HELP_VERB; 5586051Swyllys cmds[HELP_IDX].summary = HELP_SUMM; 5596051Swyllys cmds[HELP_IDX].synopsis = HELP_SYN; 5606051Swyllys } 5616051Swyllys 5620Sstevel@tonic-gate /* 5630Sstevel@tonic-gate * Usage information. This function must be updated when new verbs or 5640Sstevel@tonic-gate * options are added. 5650Sstevel@tonic-gate */ 5660Sstevel@tonic-gate static void 5673089Swyllys usage(int idx) 5680Sstevel@tonic-gate { 56917Sdinak int i; 57017Sdinak 57117Sdinak /* Display this block only in command-line mode. */ 57217Sdinak (void) fprintf(stdout, gettext("Usage:\n")); 5733501Swyllys (void) fprintf(stdout, gettext(" %s -?\t(help and usage)\n"), 5744829Shylee prog); 5753501Swyllys (void) fprintf(stdout, gettext(" %s -f option_file\n"), prog); 5763501Swyllys (void) fprintf(stdout, gettext(" %s subcommand [options...]\n"), 5774829Shylee prog); 57817Sdinak (void) fprintf(stdout, gettext("where subcommands may be:\n")); 57917Sdinak 58017Sdinak /* Display only those verbs that match the current tool mode. */ 5813089Swyllys if (idx == -1) { 5823089Swyllys for (i = 0; i < num_cmds; i++) { 5833089Swyllys /* Do NOT i18n/l10n. */ 5843501Swyllys (void) fprintf(stdout, " %-8s - %s\n", 5854829Shylee cmds[i].verb, cmds[i].summary); 5863089Swyllys } 5876354Swyllys (void) fprintf(stdout, "%s \'help\'.\n" 5886354Swyllys "Ex: pktool gencert help\n\n", 5896354Swyllys gettext("\nFurther details on the " 5906354Swyllys "subcommands can be found by adding")); 5913089Swyllys } else { 5923089Swyllys (void) fprintf(stdout, "\t%s\n", cmds[idx].synopsis); 59317Sdinak } 59417Sdinak } 59517Sdinak 59617Sdinak /* 59717Sdinak * Provide help, in the form of displaying the usage. 59817Sdinak */ 59917Sdinak static int 60017Sdinak pk_help(int argc, char *argv[]) 60117Sdinak /* ARGSUSED */ 60217Sdinak { 6033089Swyllys usage(-1); 6043089Swyllys return (0); 6053089Swyllys } 6063089Swyllys 6073089Swyllys /* 6083089Swyllys * Process arguments from the argfile and create a new 6093089Swyllys * argv/argc list to be processed later. 6103089Swyllys */ 6113089Swyllys static int 6123089Swyllys process_arg_file(char *argfile, char ***argv, int *argc) 6133089Swyllys { 6143089Swyllys FILE *fp; 6153089Swyllys char argline[2 * BUFSIZ]; /* 2048 bytes should be plenty */ 6163089Swyllys char *p; 6173089Swyllys int nargs = 0; 6183089Swyllys 6193089Swyllys if ((fp = fopen(argfile, "rF")) == NULL) { 6203089Swyllys (void) fprintf(stderr, 6214829Shylee gettext("Cannot read argfile %s: %s\n"), 6224829Shylee argfile, strerror(errno)); 6233089Swyllys return (errno); 6243089Swyllys } 62517Sdinak 6263089Swyllys while (fgets(argline, sizeof (argline), fp) != NULL) { 6273089Swyllys int j; 6283089Swyllys /* remove trailing whitespace */ 6293089Swyllys j = strlen(argline) - 1; 6303089Swyllys while (j >= 0 && isspace(argline[j])) { 6313089Swyllys argline[j] = 0; 6323089Swyllys j--; 6333089Swyllys } 6343089Swyllys /* If it was a blank line, get the next one. */ 6353089Swyllys if (!strlen(argline)) 6363089Swyllys continue; 6373089Swyllys 6385051Swyllys (*argv) = realloc((*argv), 6395051Swyllys (nargs + 1) * sizeof (char *)); 6403089Swyllys if ((*argv) == NULL) { 6413089Swyllys perror("memory error"); 6423089Swyllys (void) fclose(fp); 6433089Swyllys return (errno); 6443089Swyllys } 6453089Swyllys p = (char *)strdup(argline); 6463089Swyllys if (p == NULL) { 6473089Swyllys perror("memory error"); 6483089Swyllys (void) fclose(fp); 6493089Swyllys return (errno); 6503089Swyllys } 6513089Swyllys (*argv)[nargs] = p; 6523089Swyllys nargs++; 6533089Swyllys } 6543089Swyllys *argc = nargs; 6553089Swyllys (void) fclose(fp); 65617Sdinak return (0); 6570Sstevel@tonic-gate } 6580Sstevel@tonic-gate 6590Sstevel@tonic-gate /* 6600Sstevel@tonic-gate * MAIN() -- where all the action is 6610Sstevel@tonic-gate */ 6620Sstevel@tonic-gate int 6630Sstevel@tonic-gate main(int argc, char *argv[], char *envp[]) 6640Sstevel@tonic-gate /* ARGSUSED2 */ 6650Sstevel@tonic-gate { 6660Sstevel@tonic-gate int i, found = -1; 6670Sstevel@tonic-gate int rv; 6680Sstevel@tonic-gate int pk_argc = 0; 6690Sstevel@tonic-gate char **pk_argv = NULL; 67017Sdinak int save_errno = 0; 6710Sstevel@tonic-gate 6720Sstevel@tonic-gate /* Set up for i18n/l10n. */ 6730Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 6740Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D. */ 6750Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it isn't. */ 6760Sstevel@tonic-gate #endif 6770Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 6780Sstevel@tonic-gate 6796051Swyllys init_command_list(); 6806051Swyllys 6810Sstevel@tonic-gate /* Get program base name and move pointer over 0th arg. */ 6820Sstevel@tonic-gate prog = basename(argv[0]); 6830Sstevel@tonic-gate argv++, argc--; 6840Sstevel@tonic-gate 6850Sstevel@tonic-gate /* Set up for debug and error output. */ 6860Sstevel@tonic-gate if (argc == 0) { 6873089Swyllys usage(-1); 6880Sstevel@tonic-gate return (1); 6890Sstevel@tonic-gate } 6900Sstevel@tonic-gate 69117Sdinak /* Check for help options. For CLIP-compliance. */ 6923089Swyllys if (strcmp(argv[0], "-?") == 0) { 6933089Swyllys return (pk_help(argc, argv)); 6943089Swyllys } else if (strcmp(argv[0], "-f") == 0 && argc == 2) { 6953089Swyllys rv = process_arg_file(argv[1], &pk_argv, &pk_argc); 6963089Swyllys if (rv) 6973089Swyllys return (rv); 6983089Swyllys } else if (argc >= 1 && argv[0][0] == '-') { 6993089Swyllys usage(-1); 7003089Swyllys return (1); 70117Sdinak } 70217Sdinak 70317Sdinak /* Always turns off Metaslot so that we can see softtoken. */ 7040Sstevel@tonic-gate if (setenv("METASLOT_ENABLED", "false", 1) < 0) { 70517Sdinak save_errno = errno; 7060Sstevel@tonic-gate cryptoerror(LOG_STDERR, 70717Sdinak gettext("Disabling Metaslot failed (%s)."), 70817Sdinak strerror(save_errno)); 7090Sstevel@tonic-gate return (1); 7100Sstevel@tonic-gate } 7110Sstevel@tonic-gate 7120Sstevel@tonic-gate /* Begin parsing command line. */ 7133089Swyllys if (pk_argc == 0 && pk_argv == NULL) { 7143089Swyllys pk_argc = argc; 7153089Swyllys pk_argv = argv; 7163089Swyllys } 7170Sstevel@tonic-gate 71817Sdinak /* Check for valid verb (or an abbreviation of it). */ 7190Sstevel@tonic-gate found = -1; 7200Sstevel@tonic-gate for (i = 0; i < num_cmds; i++) { 7210Sstevel@tonic-gate if (strcmp(cmds[i].verb, pk_argv[0]) == 0) { 7220Sstevel@tonic-gate if (found < 0) { 7230Sstevel@tonic-gate found = i; 7240Sstevel@tonic-gate break; 7250Sstevel@tonic-gate } 7260Sstevel@tonic-gate } 7270Sstevel@tonic-gate } 7280Sstevel@tonic-gate /* Stop here if no valid verb found. */ 7290Sstevel@tonic-gate if (found < 0) { 73017Sdinak cryptoerror(LOG_STDERR, gettext("Invalid verb: %s"), 73117Sdinak pk_argv[0]); 7320Sstevel@tonic-gate return (1); 7330Sstevel@tonic-gate } 7340Sstevel@tonic-gate 7350Sstevel@tonic-gate /* Get to work! */ 7360Sstevel@tonic-gate rv = (*cmds[found].action)(pk_argc, pk_argv); 7370Sstevel@tonic-gate switch (rv) { 7380Sstevel@tonic-gate case PK_ERR_NONE: 7390Sstevel@tonic-gate break; /* Command succeeded, do nothing. */ 7400Sstevel@tonic-gate case PK_ERR_USAGE: 7413089Swyllys usage(found); 7420Sstevel@tonic-gate break; 7430Sstevel@tonic-gate case PK_ERR_QUIT: 7440Sstevel@tonic-gate exit(0); 7450Sstevel@tonic-gate /* NOTREACHED */ 74617Sdinak case PK_ERR_PK11: 74717Sdinak case PK_ERR_SYSTEM: 74817Sdinak case PK_ERR_OPENSSL: 7493089Swyllys case PK_ERR_NSS: 7500Sstevel@tonic-gate default: 7510Sstevel@tonic-gate break; 7520Sstevel@tonic-gate } 7530Sstevel@tonic-gate return (rv); 7540Sstevel@tonic-gate } 755