1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * This file comprises the main driver for this tool. 30 * Upon parsing the command verbs from user input, it 31 * branches to the appropriate modules to perform the 32 * requested task. 33 */ 34 35 #include <stdio.h> 36 #include <string.h> 37 #include <ctype.h> 38 #include <malloc.h> 39 #include <libintl.h> 40 #include <libgen.h> 41 #include <errno.h> 42 #include <cryptoutil.h> 43 #include <security/cryptoki.h> 44 #include "common.h" 45 46 /* 47 * The verbcmd construct allows genericizing information about a verb so 48 * that it is easier to manipulate. Makes parsing code easier to read, 49 * fix, and extend with new verbs. 50 */ 51 typedef struct verbcmd_s { 52 char *verb; 53 int (*action)(int, char *[]); 54 int mode; 55 char *summary; 56 char *synopsis; 57 } verbcmd; 58 59 /* External declarations for supported verb actions. */ 60 extern int pk_setpin(int argc, char *argv[]); 61 extern int pk_list(int argc, char *argv[]); 62 extern int pk_delete(int argc, char *argv[]); 63 extern int pk_import(int argc, char *argv[]); 64 extern int pk_export(int argc, char *argv[]); 65 extern int pk_tokens(int argc, char *argv[]); 66 extern int pk_gencert(int argc, char *argv[]); 67 extern int pk_gencsr(int argc, char *argv[]); 68 extern int pk_download(int argc, char *argv[]); 69 extern int pk_genkey(int argc, char *argv[]); 70 extern int pk_signcsr(int argc, char *argv[]); 71 72 /* Forward declarations for "built-in" verb actions. */ 73 static int pk_help(int argc, char *argv[]); 74 75 #define TOKEN_IDX 0 76 #define TOKEN_VERB "tokens" 77 #define TOKEN_SUMM gettext("lists all visible PKCS#11 tokens") 78 #define TOKEN_SYN "tokens" 79 80 #define SETPIN_IDX 1 81 #define SETPIN_VERB "setpin" 82 #define SETPIN_SUMM gettext("changes user authentication passphrase "\ 83 "for keystore access") 84 #define SETPIN_SYN \ 85 "setpin [ keystore=pkcs11 ]\n\t\t" \ 86 "[ token=token[:manuf[:serial]]]\n\t" \ 87 "setpin keystore=nss\n\t\t" \ 88 "[ token=token ]\n\t\t" \ 89 "[ dir=directory-path ]\n\t\t" \ 90 "[ prefix=DBprefix ]\n\t" 91 92 #define LIST_IDX 2 93 #define LIST_VERB "list" 94 #define LIST_SUMM gettext("lists a summary of objects in the keystore") 95 #define LIST_SYN \ 96 "list [ token=token[:manuf[:serial]]]\n\t\t" \ 97 "[ objtype=private|public|both ]\n\t\t" \ 98 "[ label=label ]\n\t" \ 99 \ 100 "list objtype=cert[:[public | private | both ]]\n\t\t" \ 101 "[ subject=subject-DN ]\n\t\t" \ 102 "[ keystore=pkcs11 ]\n\t\t" \ 103 "[ issuer=issuer-DN ]\n\t\t" \ 104 "[ serial=serial number ]\n\t\t" \ 105 "[ label=cert-label ]\n\t\t" \ 106 "[ token=token[:manuf[:serial]]]\n\t\t" \ 107 "[ criteria=valid|expired|both ]\n\t" \ 108 \ 109 "list objtype=key[:[public | private | both ]]\n\t\t" \ 110 "[ keystore=pkcs11 ]\n\t\t" \ 111 "[ subject=subject-DN ]\n\t\t" \ 112 "[ label=key-label ]\n\t\t" \ 113 "[ token=token[:manuf[:serial]]]\n\t" \ 114 \ 115 "list keystore=pkcs11 objtype=crl\n\t\t" \ 116 "infile=crl-fn\n\t" \ 117 \ 118 "list keystore=nss objtype=cert\n\t\t" \ 119 "[ subject=subject-DN ]\n\t\t" \ 120 "[ issuer=issuer-DN ]\n\t\t" \ 121 "[ serial=serial number ]\n\t\t" \ 122 "[ nickname=cert-nickname ]\n\t\t" \ 123 "[ token=token[:manuf[:serial]]]\n\t\t" \ 124 "[ dir=directory-path ]\n\t\t" \ 125 "[ prefix=DBprefix ]\n\t\t" \ 126 "[ criteria=valid|expired|both ]\n\t" \ 127 \ 128 "list keystore=nss objtype=key\n\t\t" \ 129 "[ token=token[:manuf[:serial]]]\n\t\t" \ 130 "[ dir=directory-path ]\n\t\t" \ 131 "[ prefix=DBprefix ]\n\t\t" \ 132 "[ nickname=key-nickname ]\n\t" \ 133 \ 134 "list keystore=file objtype=cert\n\t\t" \ 135 "[ subject=subject-DN ]\n\t\t" \ 136 "[ issuer=issuer-DN ]\n\t\t" \ 137 "[ serial=serial number ]\n\t\t" \ 138 "[ infile=cert-fn ]\n\t\t" \ 139 "[ dir=directory-path ]\n\t\t" \ 140 "[ criteria=valid|expired|both ]\n\t" \ 141 \ 142 "list keystore=file objtype=key\n\t\t" \ 143 "[ infile=key-fn ]\n\t\t" \ 144 "[ dir=directory-path ]\n\t" \ 145 \ 146 "list keystore=file objtype=crl\n\t\t" \ 147 "infile=crl-fn\n\t" 148 149 #define DELETE_IDX 3 150 #define DELETE_VERB "delete" 151 #define DELETE_SUMM gettext("deletes objects in the keystore") 152 #define DELETE_SYN \ 153 "delete [ token=token[:manuf[:serial]]]\n\t\t" \ 154 "[ objtype=private|public|both ]\n\t\t" \ 155 "[ label=object-label ]\n\t" \ 156 \ 157 "delete keystore=nss objtype=cert\n\t\t" \ 158 "[ subject=subject-DN ]\n\t\t" \ 159 "[ issuer=issuer-DN ]\n\t\t" \ 160 "[ serial=serial number ]\n\t\t" \ 161 "[ label=cert-label ]\n\t\t" \ 162 "[ token=token[:manuf[:serial]]]\n\t\t" \ 163 "[ dir=directory-path ]\n\t\t" \ 164 "[ prefix=DBprefix ]\n\t\t" \ 165 "[ criteria=valid|expired|both ]\n\t" \ 166 \ 167 "delete keystore=nss objtype=key\n\t\t" \ 168 "[ token=token[:manuf[:serial]]]\n\t\t" \ 169 "[ dir=directory-path ]\n\t\t" \ 170 "[ prefix=DBprefix ]\n\t\t" \ 171 "[ nickname=key-nickname ]\n\t\t" \ 172 \ 173 "delete keystore=nss objtype=crl\n\t\t" \ 174 "[ nickname=issuer-nickname ]\n\t\t" \ 175 "[ subject=subject-DN ]\n\t\t" \ 176 "[ token=token[:manuf[:serial]]]\n\t\t" \ 177 "[ dir=directory-path ]\n\t\t" \ 178 "[ prefix=DBprefix ]\n\t" \ 179 \ 180 "delete keystore=pkcs11 " \ 181 "objtype=cert[:[public | private | both]]\n\t\t" \ 182 "[ subject=subject-DN ]\n\t\t" \ 183 "[ issuer=issuer-DN ]\n\t\t" \ 184 "[ serial=serial number ]\n\t\t" \ 185 "[ label=cert-label ]\n\t\t" \ 186 "[ token=token[:manuf[:serial]]]\n\t\t" \ 187 "[ criteria=valid|expired|both ]\n\t" \ 188 \ 189 "delete keystore=pkcs11 " \ 190 "objtype=key[:[public | private | both]]\n\t\t" \ 191 "[ subject=subject-DN ]\n\t\t" \ 192 "[ label=key-label ]\n\t\t" \ 193 "[ token=token[:manuf[:serial]]]\n\t" \ 194 \ 195 "delete keystore=pkcs11 objtype=crl\n\t\t" \ 196 "infile=crl-fn\n\t" \ 197 \ 198 "delete keystore=file objtype=cert\n\t\t" \ 199 "[ subject=subject-DN ]\n\t\t" \ 200 "[ issuer=issuer-DN ]\n\t\t" \ 201 "[ serial=serial number ]\n\t\t" \ 202 "[ infile=cert-fn ]\n\t\t" \ 203 "[ dir=directory-path ]\n\t\t" \ 204 "[ criteria=valid|expired|both ]\n\t" \ 205 \ 206 "delete keystore=file objtype=key\n\t\t" \ 207 "[ infile=key-fn ]\n\t\t" \ 208 "[ dir=directory-path ]\n\t" \ 209 \ 210 "delete keystore=file objtype=crl\n\t\t" \ 211 "infile=crl-fn\n\t" 212 213 #define IMPORT_IDX 4 214 #define IMPORT_VERB "import" 215 #define IMPORT_SUMM gettext("imports objects from an external source") 216 #define IMPORT_SYN \ 217 "import [token=token[:manuf[:serial]]]\n\t\t" \ 218 "infile=input-fn\n\t" \ 219 \ 220 "import keystore=nss objtype=cert\n\t\t" \ 221 "infile=input-fn\n\t\t" \ 222 "label=cert-label\n\t\t" \ 223 "[ trust=trust-value ]\n\t\t" \ 224 "[ token=token[:manuf[:serial]]]\n\t\t" \ 225 "[ dir=directory-path ]\n\t\t" \ 226 "[ prefix=DBprefix ]\n\t" \ 227 \ 228 "import keystore=nss objtype=crl\n\t\t" \ 229 "infile=input-fn\n\t\t" \ 230 "[ verifycrl=y|n ]\n\t\t" \ 231 "[ token=token[:manuf[:serial]]]\n\t\t" \ 232 "[ dir=directory-path ]\n\t\t" \ 233 "[ prefix=DBprefix ]\n\t" \ 234 \ 235 "import keystore=pkcs11\n\t\t" \ 236 "infile=input-fn\n\t\t" \ 237 "label=label\n\t\t" \ 238 "[ objtype=cert|key ]\n\t\t" \ 239 "[ keytype=aes|arcfour|des|3des|generic ]\n\t\t" \ 240 "[ sensitive=y|n ]\n\t\t" \ 241 "[ extractable=y|n ]\n\t\t" \ 242 "[ token=token[:manuf[:serial]]]\n\t" \ 243 \ 244 "import keystore=pkcs11 objtype=crl\n\t\t" \ 245 "infile=input-crl-fn\n\t\t" \ 246 "outcrl=output-crl-fn\n\t\t" \ 247 "outformat=pem|der\n\t" \ 248 \ 249 "import keystore=file\n\t\t" \ 250 "infile=input-fn\n\t\t" \ 251 "outkey=output-key-fn\n\t\t" \ 252 "outcert=output-cert-fn\n\t\t" \ 253 "[ outformat=pem|der|pkcs12 ]\n\t" \ 254 \ 255 "import keystore=file objtype=crl\n\t\t" \ 256 "infile=input-crl-fn\n\t\t" \ 257 "outcrl=output-crl-fn\n\t\t" \ 258 "outformat=pem|der\n\t" 259 260 #define EXPORT_IDX 5 261 #define EXPORT_VERB "export" 262 #define EXPORT_SUMM gettext("exports objects from the keystore to a file") 263 #define EXPORT_SYN \ 264 "export [token=token[:manuf[:serial]]]\n\t\t" \ 265 "outfile=output-fn\n\t" \ 266 \ 267 "export keystore=nss\n\t\t" \ 268 "outfile=output-fn\n\t\t" \ 269 "[ objtype=cert|key ]\n\t\t" \ 270 "[ subject=subject-DN ]\n\t\t" \ 271 "[ issuer=issuer-DN ]\n\t\t" \ 272 "[ serial=serial number ]\n\t\t" \ 273 "[ nickname=cert-nickname ]\n\t\t" \ 274 "[ token=token[:manuf[:serial]]]\n\t\t" \ 275 "[ dir=directory-path ]\n\t\t" \ 276 "[ prefix=DBPrefix ]\n\t\t" \ 277 "[ outformat=pem|der|pkcs12 ]\n\t" \ 278 \ 279 "export keystore=pkcs11\n\t\t" \ 280 "outfile=output-fn\n\t\t" \ 281 "[ objtype=cert|key ]\n\t\t" \ 282 "[ label=label ]\n\t\t" \ 283 "[ subject=subject-DN ]\n\t\t" \ 284 "[ issuer=issuer-DN ]\n\t\t" \ 285 "[ serial=serial number ]\n\t\t" \ 286 "[ outformat=pem|der|pkcs12|raw ]\n\t\t" \ 287 "[ token=token[:manuf[:serial]]]\n\t" \ 288 \ 289 "export keystore=file\n\t\t" \ 290 "certfile=cert-input-fn\n\t\t" \ 291 "keyfile=key-input-fn\n\t\t" \ 292 "outfile=output-pkcs12-fn\n\t" 293 294 #define GENCERT_IDX 6 295 #define GENCERT_VERB "gencert" 296 #define GENCERT_SUMM gettext("creates a self-signed X.509v3 certificate") 297 #define GENCERT_SYN \ 298 "gencert [-i] keystore=nss\n\t\t" \ 299 "label=cert-nickname\n\t\t" \ 300 "serial=serial number hex string]\n\t\t" \ 301 "subject=subject-DN\n\t\t" \ 302 "[ altname=[critical:]SubjectAltName ]\n\t\t" \ 303 "[ keyusage=[critical:]usage,usage,...]\n\t\t" \ 304 "[ token=token[:manuf[:serial]]]\n\t\t" \ 305 "[ dir=directory-path ]\n\t\t" \ 306 "[ prefix=DBprefix ]\n\t\t" \ 307 "[ keytype=rsa|dsa ]\n\t\t" \ 308 "[ keylen=key-size ]\n\t\t" \ 309 "[ trust=trust-value ]\n\t\t" \ 310 "[ eku=[critical:]EKU name,...]\n\t\t" \ 311 "[ lifetime=number-hour|number-day|number-year ]\n\t" \ 312 \ 313 "gencert [-i] [ keystore=pkcs11 ]\n\t\t" \ 314 "label=key/cert-label\n\t\t" \ 315 "subject=subject-DN\n\t\t" \ 316 "serial=serial number hex string\n\t\t" \ 317 "[ altname=[critical:]SubjectAltName ]\n\t\t" \ 318 "[ keyusage=[critical:]usage,usage,...]\n\t\t" \ 319 "[ token=token[:manuf[:serial]]]\n\t\t" \ 320 "[ keytype=rsa|dsa ]\n\t\t" \ 321 "[ keylen=key-size ]\n\t\t" \ 322 "[ eku=[critical:]EKU name,...]\n\t\t" \ 323 "[ lifetime=number-hour|number-day|number-year ]\n\t" \ 324 \ 325 "gencert [-i] keystore=file\n\t\t" \ 326 "outcert=cert_filename\n\t\t" \ 327 "outkey=key_filename\n\t\t" \ 328 "subject=subject-DN\n\t\t" \ 329 "serial=serial number hex string\n\t\t" \ 330 "[ altname=[critical:]SubjectAltName ]\n\t\t" \ 331 "[ keyusage=[critical:]usage,usage,...]\n\t\t" \ 332 "[ format=der|pem ]\n\t\t" \ 333 "[ prefix=DBprefix ]\n\t\t" \ 334 "[ keytype=rsa|dsa ]\n\t\t" \ 335 "[ keylen=key-size ]\n\t\t" \ 336 "[ eku=[critical:]EKU name,...]\n\t\t" \ 337 "[ lifetime=number-hour|number-day|number-year ]\n\t" 338 339 #define GENCSR_IDX 7 340 #define GENCSR_VERB "gencsr" 341 #define GENCSR_SUMM gettext("creates a PKCS#10 certificate signing " \ 342 "request file") 343 344 #define GENCSR_SYN \ 345 "gencsr [-i] keystore=nss \n\t\t" \ 346 "nickname=cert-nickname\n\t\t" \ 347 "outcsr=csr-fn\n\t\t" \ 348 "subject=subject-DN\n\t\t" \ 349 "[ altname=[critical:]SubjectAltName ]\n\t\t" \ 350 "[ keyusage=[critical:]usage,usage,...]\n\t\t" \ 351 "[ token=token[:manuf[:serial]]]\n\t\t" \ 352 "[ dir=directory-path ]\n\t\t" \ 353 "[ prefix=DBprefix ]\n\t\t" \ 354 "[ keytype=rsa|dsa ]\n\t\t" \ 355 "[ keylen=key-size ]\n\t\t" \ 356 "[ eku=[critical:]EKU name,...]\n\t\t" \ 357 "[ format=pem|der ]\n\t" \ 358 \ 359 "gencsr [-i] [ keystore=pkcs11 ]\n\t\t" \ 360 "label=key-label\n\t\t" \ 361 "outcsr=csr-fn\n\t\t" \ 362 "subject=subject-DN\n\t\t" \ 363 "[ altname=[critical:]SubjectAltName ]\n\t\t" \ 364 "[ keyusage=[critical:]usage,usage,...]\n\t\t" \ 365 "[ token=token[:manuf[:serial]]]\n\t\t" \ 366 "[ keytype=rsa|dsa ]\n\t\t" \ 367 "[ keylen=key-size ]\n\t\t" \ 368 "[ eku=[critical:]EKU name,...]\n\t\t" \ 369 "[ format=pem|der ]]\n\t" \ 370 \ 371 "gencsr [-i] keystore=file\n\t\t" \ 372 "outcsr=csr-fn\n\t\t" \ 373 "outkey=key-fn\n\t\t" \ 374 "subject=subject-DN\n\t\t" \ 375 "[ altname=[critical:]SubjectAltName ]\n\t\t" \ 376 "[ keyusage=[critical:]usage,usage,...]\n\t\t" \ 377 "[ keytype=rsa|dsa ]\n\t\t" \ 378 "[ keylen=key-size ]\n\t\t" \ 379 "[ eku=[critical:]EKU name,...]\n\t\t" \ 380 "[ format=pem|der ]\n\t" 381 382 #define DOWNLOAD_IDX 8 383 #define DOWNLOAD_VERB "download" 384 #define DOWNLOAD_SUMM gettext("downloads a CRL or certificate file " \ 385 "from an external source") 386 #define DOWNLOAD_SYN \ 387 "download url=url_str\n\t\t" \ 388 "[ objtype=crl|cert ]\n\t\t" \ 389 "[ http_proxy=proxy_str ]\n\t\t" \ 390 "[ outfile = outfile ]\n\t" 391 392 #define GENKEY_IDX 9 393 #define GENKEY_VERB "genkey" 394 #define GENKEY_SUMM gettext("creates a symmetric key in the keystore") 395 #define GENKEY_SYN \ 396 "genkey [ keystore=pkcs11 ]\n\t\t" \ 397 "label=key-label\n\t\t" \ 398 "[ keytype=aes|arcfour|des|3des|generic ]\n\t\t" \ 399 "[ keylen=key-size (AES, ARCFOUR or GENERIC only)]\n\t\t" \ 400 "[ token=token[:manuf[:serial]]]\n\t\t" \ 401 "[ sensitive=y|n ]\n\t\t" \ 402 "[ extractable=y|n ]\n\t\t" \ 403 "[ print=y|n ]\n\t" \ 404 \ 405 "genkey keystore=nss\n\t\t" \ 406 "label=key-label\n\t\t" \ 407 "[ keytype=aes|arcfour|des|3des|generic ]\n\t\t" \ 408 "[ keylen=key-size (AES, ARCFOUR or GENERIC only)]\n\t\t" \ 409 "[ token=token[:manuf[:serial]]]\n\t\t" \ 410 "[ dir=directory-path ]\n\t\t" \ 411 "[ prefix=DBprefix ]\n\t" \ 412 \ 413 "genkey keystore=file\n\t\t" \ 414 "outkey=key-fn\n\t\t" \ 415 "[ keytype=aes|arcfour|des|3des|generic ]\n\t\t" \ 416 "[ keylen=key-size (AES, ARCFOUR or GENERIC only)]\n\t\t" \ 417 "[ print=y|n ]\n\t" 418 419 #define SIGNCSR_IDX 10 420 #define SIGNCSR_VERB "signcsr" 421 #define SIGNCSR_SUMM gettext("Sign a PKCS#10 Certificate Signing Request") 422 #define SIGNCSR_SYN \ 423 "signcsr keystore=pkcs11\n\t\t" \ 424 "signkey=label (label of signing key)\n\t\t" \ 425 "csr=CSR filename\n\t\t" \ 426 "serial=serial number hex string\n\t\t" \ 427 "outcert=filename for final certificate\n\t\t" \ 428 "issuer=issuer-DN\n\t\t" \ 429 "[ store=y|n ] (store the new cert in NSS DB, default=n)\n\t\t" \ 430 "[ outlabel=certificate label ]\n\t\t" \ 431 "[ format=pem|der ] (output format)\n\t\t" \ 432 "[ subject=subject-DN ] (new subject name)\n\t\t" \ 433 "[ altname=subjectAltName ]\n\t\t" \ 434 "[ keyusage=[critical:]usage,...]\n\t\t" \ 435 "[ eku=[critical:]EKU Name,...]\n\t\t" \ 436 "[ lifetime=number-hour|number-day|number-year ]\n\t\t" \ 437 "[ token=token[:manuf[:serial]]]\n\t" \ 438 \ 439 "signcsr keystore=file\n\t\t" \ 440 "signkey=filename\n\t\t" \ 441 "csr=CSR filename\n\t\t" \ 442 "serial=serial number hex string\n\t\t" \ 443 "outcert=filename for final certificate\n\t\t" \ 444 "issuer=issuer-DN\n\t\t" \ 445 "[ format=pem|der ] (output format)\n\t\t" \ 446 "[ subject=subject-DN ] (new subject name)\n\t\t" \ 447 "[ altname=subjectAltName ]\n\t\t" \ 448 "[ keyusage=[critical:]usage,...]\n\t\t" \ 449 "[ lifetime=number-hour|number-day|number-year ]\n\t\t" \ 450 "[ eku=[critical:]EKU Name,...]\n\t" \ 451 \ 452 "signcsr keystore=nss\n\t\t" \ 453 "signkey=label (label of signing key)\n\t\t" \ 454 "csr=CSR filename\n\t\t" \ 455 "serial=serial number hex string\n\t\t" \ 456 "outcert=filename for final certificate\n\t\t" \ 457 "issuer=issuer-DN\n\t\t" \ 458 "[ store=y|n ] (store the new cert in NSS DB, default=n)\n\t\t" \ 459 "[ outlabel=certificate label ]\n\t\t" \ 460 "[ format=pem|der ] (output format)\n\t\t" \ 461 "[ subject=subject-DN ] (new subject name)\n\t\t" \ 462 "[ altname=subjectAltName ]\n\t\t" \ 463 "[ keyusage=[critical:]usage,...]\n\t\t" \ 464 "[ eku=[critical:]EKU Name,...]\n\t\t" \ 465 "[ lifetime=number-hour|number-day|number-year ]\n\t\t" \ 466 "[ token=token[:manuf[:serial]]]\n\t\t" \ 467 "[ dir=directory-path ]\n\t\t" \ 468 "[ prefix=DBprefix ]\n\t" 469 470 #define HELP_IDX 11 471 #define HELP_VERB "help" 472 #define HELP_SUMM gettext("displays help message") 473 #define HELP_SYN "help\t(help and usage)" 474 475 /* Command structure for verbs and their actions. Do NOT i18n/l10n. */ 476 static verbcmd cmds[] = { 477 { NULL, pk_tokens, 0, NULL, NULL}, 478 { NULL, pk_setpin, 0, NULL, NULL}, 479 { NULL, pk_list, 0, NULL, NULL}, 480 { NULL, pk_delete, 0, NULL, NULL}, 481 { NULL, pk_import, 0, NULL, NULL}, 482 { NULL, pk_export, 0, NULL, NULL}, 483 { NULL, pk_gencert, 0, NULL, NULL}, 484 { NULL, pk_gencsr, 0, NULL, NULL}, 485 { NULL, pk_download, 0, NULL, NULL}, 486 { NULL, pk_genkey, 0, NULL, NULL}, 487 { NULL, pk_signcsr, 0, NULL, NULL}, 488 { NULL, pk_help, 0, NULL, NULL} 489 }; 490 491 static int num_cmds = sizeof (cmds) / sizeof (verbcmd); 492 493 static char *prog; 494 static void usage(int); 495 496 static void 497 init_command_list() 498 { 499 cmds[TOKEN_IDX].verb = TOKEN_VERB; 500 cmds[TOKEN_IDX].summary = TOKEN_SUMM; 501 cmds[TOKEN_IDX].synopsis = TOKEN_SYN; 502 503 cmds[SETPIN_IDX].verb = SETPIN_VERB; 504 cmds[SETPIN_IDX].summary = SETPIN_SUMM; 505 cmds[SETPIN_IDX].synopsis = SETPIN_SYN; 506 507 cmds[LIST_IDX].verb = LIST_VERB; 508 cmds[LIST_IDX].summary = LIST_SUMM; 509 cmds[LIST_IDX].synopsis = LIST_SYN; 510 511 cmds[DELETE_IDX].verb = DELETE_VERB; 512 cmds[DELETE_IDX].summary = DELETE_SUMM; 513 cmds[DELETE_IDX].synopsis = DELETE_SYN; 514 515 cmds[IMPORT_IDX].verb = IMPORT_VERB; 516 cmds[IMPORT_IDX].summary = IMPORT_SUMM; 517 cmds[IMPORT_IDX].synopsis = IMPORT_SYN; 518 519 cmds[EXPORT_IDX].verb = EXPORT_VERB; 520 cmds[EXPORT_IDX].summary = EXPORT_SUMM; 521 cmds[EXPORT_IDX].synopsis = EXPORT_SYN; 522 523 cmds[GENCERT_IDX].verb = GENCERT_VERB; 524 cmds[GENCERT_IDX].summary = GENCERT_SUMM; 525 cmds[GENCERT_IDX].synopsis = GENCERT_SYN; 526 527 cmds[GENCSR_IDX].verb = GENCSR_VERB; 528 cmds[GENCSR_IDX].summary = GENCSR_SUMM; 529 cmds[GENCSR_IDX].synopsis = GENCSR_SYN; 530 531 cmds[DOWNLOAD_IDX].verb = DOWNLOAD_VERB; 532 cmds[DOWNLOAD_IDX].summary = DOWNLOAD_SUMM; 533 cmds[DOWNLOAD_IDX].synopsis = DOWNLOAD_SYN; 534 535 cmds[GENKEY_IDX].verb = GENKEY_VERB; 536 cmds[GENKEY_IDX].summary = GENKEY_SUMM; 537 cmds[GENKEY_IDX].synopsis = GENKEY_SYN; 538 539 cmds[SIGNCSR_IDX].verb = SIGNCSR_VERB; 540 cmds[SIGNCSR_IDX].summary = SIGNCSR_SUMM; 541 cmds[SIGNCSR_IDX].synopsis = SIGNCSR_SYN; 542 543 cmds[HELP_IDX].verb = HELP_VERB; 544 cmds[HELP_IDX].summary = HELP_SUMM; 545 cmds[HELP_IDX].synopsis = HELP_SYN; 546 } 547 548 /* 549 * Usage information. This function must be updated when new verbs or 550 * options are added. 551 */ 552 static void 553 usage(int idx) 554 { 555 int i; 556 557 /* Display this block only in command-line mode. */ 558 (void) fprintf(stdout, gettext("Usage:\n")); 559 (void) fprintf(stdout, gettext(" %s -?\t(help and usage)\n"), 560 prog); 561 (void) fprintf(stdout, gettext(" %s -f option_file\n"), prog); 562 (void) fprintf(stdout, gettext(" %s subcommand [options...]\n"), 563 prog); 564 (void) fprintf(stdout, gettext("where subcommands may be:\n")); 565 566 /* Display only those verbs that match the current tool mode. */ 567 if (idx == -1) { 568 for (i = 0; i < num_cmds; i++) { 569 /* Do NOT i18n/l10n. */ 570 (void) fprintf(stdout, " %-8s - %s\n", 571 cmds[i].verb, cmds[i].summary); 572 } 573 (void) fprintf(stdout, "%s \'help\'.\n" 574 "Ex: pktool gencert help\n\n", 575 gettext("\nFurther details on the " 576 "subcommands can be found by adding")); 577 } else { 578 (void) fprintf(stdout, "\t%s\n", cmds[idx].synopsis); 579 } 580 } 581 582 /* 583 * Provide help, in the form of displaying the usage. 584 */ 585 static int 586 pk_help(int argc, char *argv[]) 587 /* ARGSUSED */ 588 { 589 usage(-1); 590 return (0); 591 } 592 593 /* 594 * Process arguments from the argfile and create a new 595 * argv/argc list to be processed later. 596 */ 597 static int 598 process_arg_file(char *argfile, char ***argv, int *argc) 599 { 600 FILE *fp; 601 char argline[2 * BUFSIZ]; /* 2048 bytes should be plenty */ 602 char *p; 603 int nargs = 0; 604 605 if ((fp = fopen(argfile, "rF")) == NULL) { 606 (void) fprintf(stderr, 607 gettext("Cannot read argfile %s: %s\n"), 608 argfile, strerror(errno)); 609 return (errno); 610 } 611 612 while (fgets(argline, sizeof (argline), fp) != NULL) { 613 int j; 614 /* remove trailing whitespace */ 615 j = strlen(argline) - 1; 616 while (j >= 0 && isspace(argline[j])) { 617 argline[j] = 0; 618 j--; 619 } 620 /* If it was a blank line, get the next one. */ 621 if (!strlen(argline)) 622 continue; 623 624 (*argv) = realloc((*argv), 625 (nargs + 1) * sizeof (char *)); 626 if ((*argv) == NULL) { 627 perror("memory error"); 628 (void) fclose(fp); 629 return (errno); 630 } 631 p = (char *)strdup(argline); 632 if (p == NULL) { 633 perror("memory error"); 634 (void) fclose(fp); 635 return (errno); 636 } 637 (*argv)[nargs] = p; 638 nargs++; 639 } 640 *argc = nargs; 641 (void) fclose(fp); 642 return (0); 643 } 644 645 /* 646 * MAIN() -- where all the action is 647 */ 648 int 649 main(int argc, char *argv[], char *envp[]) 650 /* ARGSUSED2 */ 651 { 652 int i, found = -1; 653 int rv; 654 int pk_argc = 0; 655 char **pk_argv = NULL; 656 int save_errno = 0; 657 658 /* Set up for i18n/l10n. */ 659 (void) setlocale(LC_ALL, ""); 660 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D. */ 661 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it isn't. */ 662 #endif 663 (void) textdomain(TEXT_DOMAIN); 664 665 init_command_list(); 666 667 /* Get program base name and move pointer over 0th arg. */ 668 prog = basename(argv[0]); 669 argv++, argc--; 670 671 /* Set up for debug and error output. */ 672 if (argc == 0) { 673 usage(-1); 674 return (1); 675 } 676 677 /* Check for help options. For CLIP-compliance. */ 678 if (strcmp(argv[0], "-?") == 0) { 679 return (pk_help(argc, argv)); 680 } else if (strcmp(argv[0], "-f") == 0 && argc == 2) { 681 rv = process_arg_file(argv[1], &pk_argv, &pk_argc); 682 if (rv) 683 return (rv); 684 } else if (argc >= 1 && argv[0][0] == '-') { 685 usage(-1); 686 return (1); 687 } 688 689 /* Always turns off Metaslot so that we can see softtoken. */ 690 if (setenv("METASLOT_ENABLED", "false", 1) < 0) { 691 save_errno = errno; 692 cryptoerror(LOG_STDERR, 693 gettext("Disabling Metaslot failed (%s)."), 694 strerror(save_errno)); 695 return (1); 696 } 697 698 /* Begin parsing command line. */ 699 if (pk_argc == 0 && pk_argv == NULL) { 700 pk_argc = argc; 701 pk_argv = argv; 702 } 703 704 /* Check for valid verb (or an abbreviation of it). */ 705 found = -1; 706 for (i = 0; i < num_cmds; i++) { 707 if (strcmp(cmds[i].verb, pk_argv[0]) == 0) { 708 if (found < 0) { 709 found = i; 710 break; 711 } 712 } 713 } 714 /* Stop here if no valid verb found. */ 715 if (found < 0) { 716 cryptoerror(LOG_STDERR, gettext("Invalid verb: %s"), 717 pk_argv[0]); 718 return (1); 719 } 720 721 /* Get to work! */ 722 rv = (*cmds[found].action)(pk_argc, pk_argv); 723 switch (rv) { 724 case PK_ERR_NONE: 725 break; /* Command succeeded, do nothing. */ 726 case PK_ERR_USAGE: 727 usage(found); 728 break; 729 case PK_ERR_QUIT: 730 exit(0); 731 /* NOTREACHED */ 732 case PK_ERR_PK11: 733 case PK_ERR_SYSTEM: 734 case PK_ERR_OPENSSL: 735 case PK_ERR_NSS: 736 default: 737 break; 738 } 739 return (rv); 740 } 741