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