xref: /illumos-gate/usr/src/cmd/cmd-crypto/pktool/pktool.c (revision 7711facfe58561dd91d6ece0f5f41150c3956c83)
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