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, "setpin" }, 73 { "list", pk_list, 0, "list [-p] [-P] [-l <label>]" 74 "\n\t\tor list [--public] [--private] [--label[=]<label>]" }, 75 { "delete", pk_delete, 0, 76 "delete { [-p] [-P] [-l <label>] }" 77 "\n\t\tor delete { [--public] [--private] [--label[=]<label>] }" }, 78 { "import", pk_import, 0, "import <file>" }, 79 { "export", pk_export, 0, "export <file>" }, 80 { "-?", pk_help, 0, "--help\t(help and usage)" }, 81 }; 82 static int num_cmds = sizeof (cmds) / sizeof (verbcmd); 83 84 static char *prog; 85 static void usage(void); 86 87 /* 88 * Usage information. This function must be updated when new verbs or 89 * options are added. 90 */ 91 static void 92 usage(void) 93 { 94 int i; 95 96 cryptodebug("inside usage"); 97 98 /* Display this block only in command-line mode. */ 99 (void) fprintf(stdout, gettext("Usage:\n")); 100 (void) fprintf(stdout, gettext("\t%s -?\t(help and usage)\n"), prog); 101 (void) fprintf(stdout, gettext("\t%s subcommand [options...]\n"), prog); 102 (void) fprintf(stdout, gettext("where subcommands may be:\n")); 103 104 /* Display only those verbs that match the current tool mode. */ 105 for (i = 0; i < num_cmds; i++) { 106 /* Do NOT i18n/l10n. */ 107 (void) fprintf(stdout, "\t%s\n", cmds[i].synopsis); 108 } 109 } 110 111 /* 112 * Provide help, in the form of displaying the usage. 113 */ 114 static int 115 pk_help(int argc, char *argv[]) 116 /* ARGSUSED */ 117 { 118 cryptodebug("inside pk_help"); 119 120 usage(); 121 return (0); 122 } 123 124 /* 125 * MAIN() -- where all the action is 126 */ 127 int 128 main(int argc, char *argv[], char *envp[]) 129 /* ARGSUSED2 */ 130 { 131 int i, found = -1; 132 int rv; 133 int pk_argc = 0; 134 char **pk_argv = NULL; 135 int save_errno = 0; 136 137 /* Set up for i18n/l10n. */ 138 (void) setlocale(LC_ALL, ""); 139 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D. */ 140 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it isn't. */ 141 #endif 142 (void) textdomain(TEXT_DOMAIN); 143 144 /* Get program base name and move pointer over 0th arg. */ 145 prog = basename(argv[0]); 146 argv++, argc--; 147 148 /* Set up for debug and error output. */ 149 cryptodebug_init(prog); 150 151 if (argc == 0) { 152 usage(); 153 return (1); 154 } 155 156 /* Check for help options. For CLIP-compliance. */ 157 if (argc == 1 && argv[0][0] == '-') { 158 switch (argv[0][1]) { 159 case '?': 160 return (pk_help(argc, argv)); 161 default: 162 usage(); 163 return (1); 164 } 165 } 166 167 /* Always turns off Metaslot so that we can see softtoken. */ 168 cryptodebug("disabling Metaslot"); 169 if (setenv("METASLOT_ENABLED", "false", 1) < 0) { 170 save_errno = errno; 171 cryptoerror(LOG_STDERR, 172 gettext("Disabling Metaslot failed (%s)."), 173 strerror(save_errno)); 174 return (1); 175 } 176 177 /* Begin parsing command line. */ 178 cryptodebug("begin parsing command line"); 179 pk_argc = argc; 180 pk_argv = argv; 181 182 /* Check for valid verb (or an abbreviation of it). */ 183 found = -1; 184 for (i = 0; i < num_cmds; i++) { 185 if (strcmp(cmds[i].verb, pk_argv[0]) == 0) { 186 if (found < 0) { 187 cryptodebug("found cmd %s", cmds[i].verb); 188 found = i; 189 break; 190 } else { 191 cryptodebug("also found cmd %s, skipping", 192 cmds[i].verb); 193 } 194 } 195 } 196 /* Stop here if no valid verb found. */ 197 if (found < 0) { 198 cryptoerror(LOG_STDERR, gettext("Invalid verb: %s"), 199 pk_argv[0]); 200 return (1); 201 } 202 203 /* Get to work! */ 204 cryptodebug("begin executing cmd action"); 205 rv = (*cmds[found].action)(pk_argc, pk_argv); 206 cryptodebug("end executing cmd action"); 207 switch (rv) { 208 case PK_ERR_NONE: 209 cryptodebug("subcommand succeeded"); 210 break; /* Command succeeded, do nothing. */ 211 case PK_ERR_USAGE: 212 cryptodebug("usage error detected"); 213 usage(); 214 break; 215 case PK_ERR_QUIT: 216 cryptodebug("quit command received"); 217 exit(0); 218 /* NOTREACHED */ 219 case PK_ERR_PK11: 220 cryptoerror(LOG_STDERR, "%s", 221 gettext("Command failed due to PKCS#11 error.")); 222 break; 223 case PK_ERR_SYSTEM: 224 cryptoerror(LOG_STDERR, "%s", 225 gettext("Command failed due to system error.")); 226 break; 227 case PK_ERR_OPENSSL: 228 cryptoerror(LOG_STDERR, "%s", 229 gettext("Command failed due to OpenSSL error.")); 230 break; 231 default: 232 cryptoerror(LOG_STDERR, "%s (%d).", 233 gettext("Unknown error value"), rv); 234 break; 235 } 236 return (rv); 237 } 238