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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * This file comprises the main driver for this tool. 31 * Upon parsing the command verbs from user input, it 32 * branches to the appropriate modules to perform the 33 * requested task. 34 */ 35 36 #include <stdio.h> 37 #include <string.h> 38 #include <ctype.h> 39 #include <malloc.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 *synopsis; 56 } verbcmd; 57 58 /* External declarations for supported verb actions. */ 59 extern int pk_setpin(int argc, char *argv[]); 60 extern int pk_list(int argc, char *argv[]); 61 extern int pk_delete(int argc, char *argv[]); 62 extern int pk_import(int argc, char *argv[]); 63 extern int pk_export(int argc, char *argv[]); 64 extern int pk_tokens(int argc, char *argv[]); 65 66 /* Forward declarations for "built-in" verb actions. */ 67 static int pk_help(int argc, char *argv[]); 68 69 /* Command structure for verbs and their actions. Do NOT i18n/l10n. */ 70 static verbcmd cmds[] = { 71 { "tokens", pk_tokens, 0, "tokens" }, 72 { "setpin", pk_setpin, 0, 73 "setpin [token=<token>[:<manuf>[:<serial>]]]" }, 74 { "list", pk_list, 0, 75 "list [token=<token>[:<manuf>[:<serial>]]] " 76 "[objtype=private|public|both] [label=<label>]" }, 77 { "delete", pk_delete, 0, 78 "delete [token=<token>[:<manuf>[:<serial>]]] " 79 "{ [objtype=private|public|both] [label=<label>] }" }, 80 { "import", pk_import, 0, 81 "import [token=<token>[:<manuf>[:<serial>]]] infile=<file>" }, 82 { "export", pk_export, 0, 83 "export [token=<token>[:<manuf>[:<serial>]]] outfile=<file>" }, 84 { "-?", pk_help, 0, "help\t(help and usage)" }, 85 }; 86 static int num_cmds = sizeof (cmds) / sizeof (verbcmd); 87 88 static char *prog; 89 static void usage(void); 90 91 /* 92 * Usage information. This function must be updated when new verbs or 93 * options are added. 94 */ 95 static void 96 usage(void) 97 { 98 int i; 99 100 cryptodebug("inside usage"); 101 102 /* Display this block only in command-line mode. */ 103 (void) fprintf(stdout, gettext("Usage:\n")); 104 (void) fprintf(stdout, gettext("\t%s -?\t(help and usage)\n"), prog); 105 (void) fprintf(stdout, gettext("\t%s subcommand [options...]\n"), prog); 106 (void) fprintf(stdout, gettext("where subcommands may be:\n")); 107 108 /* Display only those verbs that match the current tool mode. */ 109 for (i = 0; i < num_cmds; i++) { 110 /* Do NOT i18n/l10n. */ 111 (void) fprintf(stdout, "\t%s\n", cmds[i].synopsis); 112 } 113 } 114 115 /* 116 * Provide help, in the form of displaying the usage. 117 */ 118 static int 119 pk_help(int argc, char *argv[]) 120 /* ARGSUSED */ 121 { 122 cryptodebug("inside pk_help"); 123 124 usage(); 125 return (0); 126 } 127 128 /* 129 * MAIN() -- where all the action is 130 */ 131 int 132 main(int argc, char *argv[], char *envp[]) 133 /* ARGSUSED2 */ 134 { 135 int i, found = -1; 136 int rv; 137 int pk_argc = 0; 138 char **pk_argv = NULL; 139 int save_errno = 0; 140 141 /* Set up for i18n/l10n. */ 142 (void) setlocale(LC_ALL, ""); 143 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D. */ 144 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it isn't. */ 145 #endif 146 (void) textdomain(TEXT_DOMAIN); 147 148 /* Get program base name and move pointer over 0th arg. */ 149 prog = basename(argv[0]); 150 argv++, argc--; 151 152 /* Set up for debug and error output. */ 153 cryptodebug_init(prog); 154 155 if (argc == 0) { 156 usage(); 157 return (1); 158 } 159 160 /* Check for help options. For CLIP-compliance. */ 161 if (argc == 1 && argv[0][0] == '-') { 162 switch (argv[0][1]) { 163 case '?': 164 return (pk_help(argc, argv)); 165 default: 166 usage(); 167 return (1); 168 } 169 } 170 171 /* Always turns off Metaslot so that we can see softtoken. */ 172 cryptodebug("disabling Metaslot"); 173 if (setenv("METASLOT_ENABLED", "false", 1) < 0) { 174 save_errno = errno; 175 cryptoerror(LOG_STDERR, 176 gettext("Disabling Metaslot failed (%s)."), 177 strerror(save_errno)); 178 return (1); 179 } 180 181 /* Begin parsing command line. */ 182 cryptodebug("begin parsing command line"); 183 pk_argc = argc; 184 pk_argv = argv; 185 186 /* Check for valid verb (or an abbreviation of it). */ 187 found = -1; 188 for (i = 0; i < num_cmds; i++) { 189 if (strcmp(cmds[i].verb, pk_argv[0]) == 0) { 190 if (found < 0) { 191 cryptodebug("found cmd %s", cmds[i].verb); 192 found = i; 193 break; 194 } else { 195 cryptodebug("also found cmd %s, skipping", 196 cmds[i].verb); 197 } 198 } 199 } 200 /* Stop here if no valid verb found. */ 201 if (found < 0) { 202 cryptoerror(LOG_STDERR, gettext("Invalid verb: %s"), 203 pk_argv[0]); 204 return (1); 205 } 206 207 /* Get to work! */ 208 cryptodebug("begin executing cmd action"); 209 rv = (*cmds[found].action)(pk_argc, pk_argv); 210 cryptodebug("end executing cmd action"); 211 switch (rv) { 212 case PK_ERR_NONE: 213 cryptodebug("subcommand succeeded"); 214 break; /* Command succeeded, do nothing. */ 215 case PK_ERR_USAGE: 216 cryptodebug("usage error detected"); 217 usage(); 218 break; 219 case PK_ERR_QUIT: 220 cryptodebug("quit command received"); 221 exit(0); 222 /* NOTREACHED */ 223 case PK_ERR_PK11: 224 cryptoerror(LOG_STDERR, "%s", 225 gettext("Command failed due to PKCS#11 error.")); 226 break; 227 case PK_ERR_SYSTEM: 228 cryptoerror(LOG_STDERR, "%s", 229 gettext("Command failed due to system error.")); 230 break; 231 case PK_ERR_OPENSSL: 232 cryptoerror(LOG_STDERR, "%s", 233 gettext("Command failed due to OpenSSL error.")); 234 break; 235 default: 236 cryptoerror(LOG_STDERR, "%s (%d).", 237 gettext("Unknown error value"), rv); 238 break; 239 } 240 return (rv); 241 } 242