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