199ebb4caSwyllys /*
299ebb4caSwyllys  * CDDL HEADER START
399ebb4caSwyllys  *
499ebb4caSwyllys  * The contents of this file are subject to the terms of the
599ebb4caSwyllys  * Common Development and Distribution License (the "License").
699ebb4caSwyllys  * You may not use this file except in compliance with the License.
799ebb4caSwyllys  *
899ebb4caSwyllys  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
999ebb4caSwyllys  * or http://www.opensolaris.org/os/licensing.
1099ebb4caSwyllys  * See the License for the specific language governing permissions
1199ebb4caSwyllys  * and limitations under the License.
1299ebb4caSwyllys  *
1399ebb4caSwyllys  * When distributing Covered Code, include this CDDL HEADER in each
1499ebb4caSwyllys  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1599ebb4caSwyllys  * If applicable, add the following below this CDDL HEADER, with the
1699ebb4caSwyllys  * fields enclosed by brackets "[]" replaced with your own identifying
1799ebb4caSwyllys  * information: Portions Copyright [yyyy] [name of copyright owner]
1899ebb4caSwyllys  *
1999ebb4caSwyllys  * CDDL HEADER END
20269e59f9SJan Pechanec  *
21269e59f9SJan Pechanec  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
2299ebb4caSwyllys  */
2399ebb4caSwyllys 
24*19e768ceSJohn Levon /*
25*19e768ceSJohn Levon  * Copyright (c) 2018, Joyent, Inc.
26*19e768ceSJohn Levon  */
27*19e768ceSJohn Levon 
2899ebb4caSwyllys #include <stdio.h>
2999ebb4caSwyllys #include <strings.h>
3099ebb4caSwyllys #include <ctype.h>
3199ebb4caSwyllys #include <libgen.h>
3299ebb4caSwyllys #include <libintl.h>
3399ebb4caSwyllys #include <locale.h>
3499ebb4caSwyllys 
3599ebb4caSwyllys #include <kmfapiP.h>
3699ebb4caSwyllys 
3799ebb4caSwyllys #include "util.h"
3899ebb4caSwyllys 
3999ebb4caSwyllys /*
4099ebb4caSwyllys  * The verbcmd construct allows genericizing information about a verb so
4199ebb4caSwyllys  * that it is easier to manipulate.  Makes parsing code easier to read,
4299ebb4caSwyllys  * fix, and extend with new verbs.
4399ebb4caSwyllys  */
4499ebb4caSwyllys typedef struct verbcmd_s {
45*19e768ceSJohn Levon 	char		*verb;
4699ebb4caSwyllys 	int		(*action)(int, char *[]);
47*19e768ceSJohn Levon 	char		*synopsis;
4899ebb4caSwyllys } verbcmd;
4999ebb4caSwyllys 
5099ebb4caSwyllys int	kc_list(int argc, char *argv[]);
5199ebb4caSwyllys int	kc_delete(int argc, char *argv[]);
5299ebb4caSwyllys int	kc_create(int argc, char *argv[]);
5399ebb4caSwyllys int	kc_modify(int argc, char *argv[]);
5499ebb4caSwyllys int	kc_export(int argc, char *argv[]);
5599ebb4caSwyllys int	kc_import(int argc, char *argv[]);
56431deaa0Shylee int	kc_install(int argc, char *argv[]);
57431deaa0Shylee int	kc_uninstall(int argc, char *argv[]);
58431deaa0Shylee 
5999ebb4caSwyllys static int	kc_help();
6099ebb4caSwyllys 
6199ebb4caSwyllys static verbcmd cmds[] = {
62431deaa0Shylee 	{ "list",	kc_list,
63431deaa0Shylee 		"list [dbfile=dbfile] [policy=policyname]\n"
64431deaa0Shylee 		"\tlist plugin" },
6599ebb4caSwyllys 	{ "delete",	kc_delete, "delete [dbfile=dbfile] "
6699ebb4caSwyllys 		"policy=policyname" },
6799ebb4caSwyllys 	{ "create",	kc_create,
6899ebb4caSwyllys 		"create [dbfile=dbfile] policy=policyname\n"
6999ebb4caSwyllys 		"\t\t[ignore-date=true|false]\n"
7099ebb4caSwyllys 		"\t\t[ignore-unknown-eku=true|false]\n"
7199ebb4caSwyllys 		"\t\t[ignore-trust-anchor=true|false]\n"
7299ebb4caSwyllys 		"\t\t[validity-adjusttime=adjusttime]\n"
7399ebb4caSwyllys 		"\t\t[ta-name=trust anchor subject DN]\n"
7499ebb4caSwyllys 		"\t\t[ta-serial=trust anchor serial number]\n"
7599ebb4caSwyllys 		"\t\t[ocsp-responder=URL]\n"
7699ebb4caSwyllys 		"\t\t[ocsp-proxy=URL]\n"
7799ebb4caSwyllys 		"\t\t[ocsp-use-cert-responder=true|false]\n"
7899ebb4caSwyllys 		"\t\t[ocsp-response-lifetime=timelimit]\n"
7999ebb4caSwyllys 		"\t\t[ocsp-ignore-response-sign=true|false]\n"
8099ebb4caSwyllys 		"\t\t[ocsp-responder-cert-name=Issuer DN]\n"
8199ebb4caSwyllys 		"\t\t[ocsp-responder-cert-serial=serial number]\n"
8299ebb4caSwyllys 		"\t\t[crl-basefilename=basefilename]\n"
8399ebb4caSwyllys 		"\t\t[crl-directory=directory]\n"
8499ebb4caSwyllys 		"\t\t[crl-get-crl-uri=true|false]\n"
8599ebb4caSwyllys 		"\t\t[crl-proxy=URL]\n"
8699ebb4caSwyllys 		"\t\t[crl-ignore-crl-sign=true|false]\n"
8799ebb4caSwyllys 		"\t\t[crl-ignore-crl-date=true|false]\n"
8899ebb4caSwyllys 		"\t\t[keyusage=digitalSignature|nonRepudiation\n\t"
8999ebb4caSwyllys 		"\t\t|keyEncipherment | dataEncipherment |\n\t"
9099ebb4caSwyllys 		"\t\tkeyAgreement |keyCertSign |\n\t"
9199ebb4caSwyllys 		"\t\tcRLSign | encipherOnly | decipherOnly],[...]\n"
9299ebb4caSwyllys 		"\t\t[ekunames=serverAuth | clientAuth |\n\t"
9399ebb4caSwyllys 		"\t\tcodeSigning | emailProtection |\n\t"
9499ebb4caSwyllys 		"\t\tipsecEndSystem | ipsecTunnel |\n\t"
9599ebb4caSwyllys 		"\t\tipsecUser | timeStamping |\n\t"
9699ebb4caSwyllys 		"\t\tOCSPSigning],[...]\n"
97269e59f9SJan Pechanec 		"\t\t[ekuoids=OID,OID,OID...]\n"
98269e59f9SJan Pechanec 		"\t\t[mapper-name=name of mapper library]\n"
99269e59f9SJan Pechanec 		"\t\t[mapper-directory=dir where mapper library resides]\n"
100269e59f9SJan Pechanec 		"\t\t[mapper-path=full pathname of mapper library]\n"
101269e59f9SJan Pechanec 		"\t\t[mapper-options=mapper options]\n"},
10299ebb4caSwyllys 	{ "modify",	kc_modify,
10399ebb4caSwyllys 		"modify [dbfile=dbfile] policy=policyname\n"
10499ebb4caSwyllys 		"\t\t[ignore-date=true|false]\n"
10599ebb4caSwyllys 		"\t\t[ignore-unknown-eku=true|false]\n"
10699ebb4caSwyllys 		"\t\t[ignore-trust-anchor=true|false]\n"
10799ebb4caSwyllys 		"\t\t[validity-adjusttime=adjusttime]\n"
108fc2613b0SWyllys Ingersoll 		"\t\t[ta-name=trust anchor subject DN | search]\n"
10999ebb4caSwyllys 		"\t\t[ta-serial=trust anchor serial number]\n"
11099ebb4caSwyllys 		"\t\t[ocsp-responder=URL]\n"
11199ebb4caSwyllys 		"\t\t[ocsp-proxy=URL]\n"
11299ebb4caSwyllys 		"\t\t[ocsp-use-cert-responder=true|false]\n"
11399ebb4caSwyllys 		"\t\t[ocsp-response-lifetime=timelimit]\n"
11499ebb4caSwyllys 		"\t\t[ocsp-ignore-response-sign=true|false]\n"
11599ebb4caSwyllys 		"\t\t[ocsp-responder-cert-name=Issuer DN]\n"
11699ebb4caSwyllys 		"\t\t[ocsp-responder-cert-serial=serial number]\n"
11799ebb4caSwyllys 		"\t\t[ocsp-none=true|false]\n"
11899ebb4caSwyllys 		"\t\t[crl-basefilename=basefilename]\n"
11999ebb4caSwyllys 		"\t\t[crl-directory=directory]\n"
12099ebb4caSwyllys 		"\t\t[crl-get-crl-uri=true|false]\n"
12199ebb4caSwyllys 		"\t\t[crl-proxy=URL]\n"
12299ebb4caSwyllys 		"\t\t[crl-ignore-crl-sign=true|false]\n"
12399ebb4caSwyllys 		"\t\t[crl-ignore-crl-date=true|false]\n"
12499ebb4caSwyllys 		"\t\t[crl-none=true|false]\n"
12599ebb4caSwyllys 		"\t\t[keyusage=digitalSignature|nonRepudiation\n\t"
12699ebb4caSwyllys 		"\t\t|keyEncipherment | dataEncipherment |\n\t"
12799ebb4caSwyllys 		"\t\tkeyAgreement |keyCertSign |\n\t"
12899ebb4caSwyllys 		"\t\tcRLSign | encipherOnly | decipherOnly],[...]\n"
12999ebb4caSwyllys 		"\t\t[keyusage-none=true|false]\n"
13099ebb4caSwyllys 		"\t\t[ekunames=serverAuth | clientAuth |\n\t"
13199ebb4caSwyllys 		"\t\tcodeSigning | emailProtection |\n\t"
13299ebb4caSwyllys 		"\t\tipsecEndSystem | ipsecTunnel |\n\t"
13399ebb4caSwyllys 		"\t\tipsecUser | timeStamping |\n\t"
13499ebb4caSwyllys 		"\t\tOCSPSigning],[...]\n"
13599ebb4caSwyllys 		"\t\t[ekuoids=OID,OID,OID...]\n"
136431deaa0Shylee 		"\t\t[eku-none=true|false]\n\n"
137269e59f9SJan Pechanec 		"\t\t[mapper-name=name of mapper library]\n"
138269e59f9SJan Pechanec 		"\t\t[mapper-directory=dir where mapper library resides]\n"
139269e59f9SJan Pechanec 		"\t\t[mapper-path=full pathname of mapper library]\n"
140269e59f9SJan Pechanec 		"\t\t[mapper-options=mapper options]\n"
141431deaa0Shylee 		"\tmodify plugin keystore=keystorename option=optionstring\n"},
142431deaa0Shylee 
14399ebb4caSwyllys 	{ "import",	kc_import, "import [dbfile=dbfile] policy=policyname "
14499ebb4caSwyllys 		"infile=inputdbfile\n" },
14599ebb4caSwyllys 	{ "export",	kc_export, "export [dbfile=dbfile] policy=policyname "
14699ebb4caSwyllys 		"outfile=newdbfile\n" },
147*19e768ceSJohn Levon 	{ "install",	kc_install, "install keystore=keystorename "
148431deaa0Shylee 		"modulepath=path [option=optionstring]\n"},
149*19e768ceSJohn Levon 	{ "uninstall",	kc_uninstall, "uninstall keystore=keystorename\n"},
150*19e768ceSJohn Levon 	{ "-?",		kc_help,	"help"},
151*19e768ceSJohn Levon 	{ "help",	kc_help,	""}
15299ebb4caSwyllys };
15399ebb4caSwyllys 
15499ebb4caSwyllys static int num_cmds = sizeof (cmds) / sizeof (verbcmd);
15599ebb4caSwyllys static char *prog;
15699ebb4caSwyllys 
15799ebb4caSwyllys static void
usage(void)15899ebb4caSwyllys usage(void)
15999ebb4caSwyllys {
16099ebb4caSwyllys 	int i;
16199ebb4caSwyllys 
16299ebb4caSwyllys 	/* Display this block only in command-line mode. */
16399ebb4caSwyllys 	(void) fprintf(stdout, gettext("Usage:\n"));
16499ebb4caSwyllys 	(void) fprintf(stdout, gettext("\t%s -?\t(help and usage)\n"), prog);
16599ebb4caSwyllys 	(void) fprintf(stdout, gettext("\t%s subcommand [options...]\n"), prog);
16699ebb4caSwyllys 	(void) fprintf(stdout, gettext("where subcommands may be:\n"));
16799ebb4caSwyllys 
16899ebb4caSwyllys 	/* Display only those verbs that match the current tool mode. */
16999ebb4caSwyllys 	for (i = 0; i < num_cmds; i++) {
17099ebb4caSwyllys 		/* Do NOT i18n/l10n. */
17199ebb4caSwyllys 		(void) fprintf(stdout, "\t%s\n", cmds[i].synopsis);
17299ebb4caSwyllys 	}
17399ebb4caSwyllys }
17499ebb4caSwyllys 
17599ebb4caSwyllys static int
kc_help()17699ebb4caSwyllys kc_help()
17799ebb4caSwyllys {
17899ebb4caSwyllys 	usage();
17999ebb4caSwyllys 	return (0);
18099ebb4caSwyllys }
18199ebb4caSwyllys 
18299ebb4caSwyllys int
main(int argc,char * argv[])18399ebb4caSwyllys main(int argc, char *argv[])
18499ebb4caSwyllys {
185d0d16abcSToomas Soome 	int ret;
18699ebb4caSwyllys 	int found;
18799ebb4caSwyllys 	int i;
18899ebb4caSwyllys 
18999ebb4caSwyllys 	(void) setlocale(LC_ALL, "");
19099ebb4caSwyllys #if !defined(TEXT_DOMAIN)		/* Should be defined by cc -D. */
19199ebb4caSwyllys #define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it isn't. */
19299ebb4caSwyllys #endif
19399ebb4caSwyllys 	(void) textdomain(TEXT_DOMAIN);
19499ebb4caSwyllys 
19599ebb4caSwyllys 	prog = basename(argv[0]);
196*19e768ceSJohn Levon 	argv++;
197*19e768ceSJohn Levon 	argc--;
19899ebb4caSwyllys 
19999ebb4caSwyllys 	if (argc == 0) {
20099ebb4caSwyllys 		usage();
20199ebb4caSwyllys 		exit(1);
20299ebb4caSwyllys 	}
20399ebb4caSwyllys 
20499ebb4caSwyllys 	if (argc == 1 && argv[0][0] == '-') {
20599ebb4caSwyllys 		switch (argv[0][1]) {
20699ebb4caSwyllys 			case '?':
20799ebb4caSwyllys 				return (kc_help());
20899ebb4caSwyllys 			default:
20999ebb4caSwyllys 				usage();
21099ebb4caSwyllys 				exit(1);
21199ebb4caSwyllys 		}
21299ebb4caSwyllys 	}
21399ebb4caSwyllys 
21499ebb4caSwyllys 	found = -1;
21599ebb4caSwyllys 	for (i = 0; i < num_cmds; i++) {
21699ebb4caSwyllys 		if (strcmp(cmds[i].verb, argv[0]) == 0) {
21799ebb4caSwyllys 			found = i;
21899ebb4caSwyllys 			break;
21999ebb4caSwyllys 		}
22099ebb4caSwyllys 	}
22199ebb4caSwyllys 
22299ebb4caSwyllys 	if (found < 0) {
22399ebb4caSwyllys 		(void) fprintf(stderr, gettext("Invalid command: %s\n"),
22499ebb4caSwyllys 		    argv[0]);
22599ebb4caSwyllys 		exit(1);
22699ebb4caSwyllys 	}
22799ebb4caSwyllys 
228d0d16abcSToomas Soome 	/*
229d0d16abcSToomas Soome 	 * Note the action functions can return values from
230d0d16abcSToomas Soome 	 * the key management framework, and those values can conflict
231d0d16abcSToomas Soome 	 * with the utility error codes.
232d0d16abcSToomas Soome 	 */
23399ebb4caSwyllys 	ret = (*cmds[found].action)(argc, argv);
23499ebb4caSwyllys 
23599ebb4caSwyllys 	switch (ret) {
23699ebb4caSwyllys 		case KC_OK:
23799ebb4caSwyllys 			break;
23899ebb4caSwyllys 		case KC_ERR_USAGE:
23999ebb4caSwyllys 			break;
24099ebb4caSwyllys 		case KC_ERR_LOADDB:
24199ebb4caSwyllys 			(void) fprintf(stderr,
24299ebb4caSwyllys 			    gettext("Error loading database\n"));
24399ebb4caSwyllys 			break;
24499ebb4caSwyllys 		case KC_ERR_FIND_POLICY:
24599ebb4caSwyllys 			break;
24699ebb4caSwyllys 		case KC_ERR_DELETE_POLICY:
24799ebb4caSwyllys 			(void) fprintf(stderr, gettext("Error deleting policy "
24899ebb4caSwyllys 			    "from database.\n"));
24999ebb4caSwyllys 			break;
25099ebb4caSwyllys 		case KC_ERR_ADD_POLICY:
25199ebb4caSwyllys 			break;
25299ebb4caSwyllys 		case KC_ERR_VERIFY_POLICY:
25399ebb4caSwyllys 			break;
25499ebb4caSwyllys 		case KC_ERR_INCOMPLETE_POLICY:
25599ebb4caSwyllys 			break;
25699ebb4caSwyllys 		case KC_ERR_MEMORY:
25799ebb4caSwyllys 			(void) fprintf(stderr, gettext("Out of memory.\n"));
25899ebb4caSwyllys 			break;
25999ebb4caSwyllys 		case KC_ERR_ACCESS:
26099ebb4caSwyllys 			break;
261431deaa0Shylee 		case KC_ERR_INSTALL:
262431deaa0Shylee 			break;
263431deaa0Shylee 		case KC_ERR_UNINSTALL:
264431deaa0Shylee 			break;
26599ebb4caSwyllys 		default:
26699ebb4caSwyllys 			(void) fprintf(stderr, gettext("%s operation failed. "
26799ebb4caSwyllys 			    "error 0x%02x\n"), cmds[found].verb, ret);
26899ebb4caSwyllys 			break;
26999ebb4caSwyllys 	}
27099ebb4caSwyllys 
27199ebb4caSwyllys 	return (ret);
27299ebb4caSwyllys }
273