xref: /onnv-gate/usr/src/cmd/cmd-crypto/kmfcfg/modify.c (revision 12919:db25553c7f2e)
13089Swyllys /*
23089Swyllys  * CDDL HEADER START
33089Swyllys  *
43089Swyllys  * The contents of this file are subject to the terms of the
53089Swyllys  * Common Development and Distribution License (the "License").
63089Swyllys  * You may not use this file except in compliance with the License.
73089Swyllys  *
83089Swyllys  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93089Swyllys  * or http://www.opensolaris.org/os/licensing.
103089Swyllys  * See the License for the specific language governing permissions
113089Swyllys  * and limitations under the License.
123089Swyllys  *
133089Swyllys  * When distributing Covered Code, include this CDDL HEADER in each
143089Swyllys  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153089Swyllys  * If applicable, add the following below this CDDL HEADER, with the
163089Swyllys  * fields enclosed by brackets "[]" replaced with your own identifying
173089Swyllys  * information: Portions Copyright [yyyy] [name of copyright owner]
183089Swyllys  *
193089Swyllys  * CDDL HEADER END
203089Swyllys  *
2112611SJan.Pechanec@Sun.COM  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
223089Swyllys  */
233089Swyllys 
243089Swyllys #include <stdio.h>
253089Swyllys #include <strings.h>
263089Swyllys #include <ctype.h>
273089Swyllys #include <libgen.h>
283089Swyllys #include <libintl.h>
293089Swyllys #include <errno.h>
303089Swyllys #include <kmfapiP.h>
313089Swyllys #include <cryptoutil.h>
325626Shylee #include <sys/stat.h>
335626Shylee #include <sys/param.h>
343089Swyllys #include "util.h"
353089Swyllys 
363089Swyllys #define	KC_IGNORE_DATE			0x0000001
373089Swyllys #define	KC_IGNORE_UNKNOWN_EKUS		0x0000002
383089Swyllys #define	KC_IGNORE_TRUST_ANCHOR		0x0000004
393089Swyllys #define	KC_VALIDITY_ADJUSTTIME		0x0000008
403089Swyllys #define	KC_TA_NAME			0x0000010
413089Swyllys #define	KC_TA_SERIAL			0x0000020
423089Swyllys #define	KC_OCSP_RESPONDER_URI		0x0000040
433089Swyllys #define	KC_OCSP_PROXY			0x0000080
443089Swyllys #define	KC_OCSP_URI_FROM_CERT		0x0000100
453089Swyllys #define	KC_OCSP_RESP_LIFETIME		0x0000200
463089Swyllys #define	KC_OCSP_IGNORE_RESP_SIGN 	0x0000400
473089Swyllys #define	KC_OCSP_RESP_CERT_NAME		0x0000800
483089Swyllys #define	KC_OCSP_RESP_CERT_SERIAL	0x0001000
493089Swyllys #define	KC_OCSP_NONE			0x0002000
503089Swyllys #define	KC_CRL_BASEFILENAME		0x0004000
513089Swyllys #define	KC_CRL_DIRECTORY		0x0008000
523089Swyllys #define	KC_CRL_GET_URI			0x0010000
533089Swyllys #define	KC_CRL_PROXY			0x0020000
543089Swyllys #define	KC_CRL_IGNORE_SIGN		0x0040000
553089Swyllys #define	KC_CRL_IGNORE_DATE		0x0080000
563089Swyllys #define	KC_CRL_NONE			0x0100000
573089Swyllys #define	KC_KEYUSAGE			0x0200000
583089Swyllys #define	KC_KEYUSAGE_NONE		0x0400000
593089Swyllys #define	KC_EKUS				0x0800000
603089Swyllys #define	KC_EKUS_NONE			0x1000000
6112611SJan.Pechanec@Sun.COM #define	KC_MAPPER_OPTIONS		0x2000000
623089Swyllys 
635626Shylee static int err; /* To store errno which may be overwritten by gettext() */
645626Shylee 
6512611SJan.Pechanec@Sun.COM #define	UPDATE_IF_DIFFERENT(old, new) \
6612611SJan.Pechanec@Sun.COM 	if ((old != NULL && new != NULL && strcmp(old, new) != 0) || \
6712611SJan.Pechanec@Sun.COM 	    (old == NULL && new != NULL)) { \
6812611SJan.Pechanec@Sun.COM 		if (old != NULL) \
6912611SJan.Pechanec@Sun.COM 			free(old); \
7012611SJan.Pechanec@Sun.COM 		old = new; \
7112611SJan.Pechanec@Sun.COM 	}
725626Shylee 
733089Swyllys int
kc_modify_policy(int argc,char * argv[])745626Shylee kc_modify_policy(int argc, char *argv[])
753089Swyllys {
763089Swyllys 	KMF_RETURN	ret;
773089Swyllys 	int 		rv = KC_OK;
783089Swyllys 	int		opt;
793089Swyllys 	extern int	optind_av;
803089Swyllys 	extern char	*optarg_av;
813089Swyllys 	char		*filename = NULL;
8212611SJan.Pechanec@Sun.COM 	char		*mapper_name = NULL;
8312611SJan.Pechanec@Sun.COM 	char		*mapper_dir = NULL;
8412611SJan.Pechanec@Sun.COM 	char		*mapper_pathname = NULL;
853089Swyllys 	uint32_t	flags = 0;
863089Swyllys 	boolean_t	ocsp_none_opt = B_FALSE;
873089Swyllys 	boolean_t	crl_none_opt = B_FALSE;
883089Swyllys 	boolean_t	ku_none_opt = B_FALSE;
893089Swyllys 	boolean_t	eku_none_opt = B_FALSE;
903089Swyllys 	int		ocsp_set_attr = 0;
913089Swyllys 	int		crl_set_attr = 0;
923089Swyllys 	KMF_POLICY_RECORD oplc, plc;
933089Swyllys 
943089Swyllys 	(void) memset(&plc, 0, sizeof (KMF_POLICY_RECORD));
953089Swyllys 	(void) memset(&oplc, 0, sizeof (KMF_POLICY_RECORD));
963089Swyllys 
973089Swyllys 	while ((opt = getopt_av(argc, argv,
985051Swyllys 	    "i:(dbfile)"
995051Swyllys 	    "p:(policy)"
1005051Swyllys 	    "d:(ignore-date)"
1015051Swyllys 	    "e:(ignore-unknown-eku)"
1025051Swyllys 	    "a:(ignore-trust-anchor)"
1035051Swyllys 	    "v:(validity-adjusttime)"
1045051Swyllys 	    "t:(ta-name)"
1055051Swyllys 	    "s:(ta-serial)"
1065051Swyllys 	    "o:(ocsp-responder)"
1075051Swyllys 	    "P:(ocsp-proxy)"
1085051Swyllys 	    "r:(ocsp-use-cert-responder)"
1095051Swyllys 	    "T:(ocsp-response-lifetime)"
1105051Swyllys 	    "R:(ocsp-ignore-response-sign)"
1115051Swyllys 	    "n:(ocsp-responder-cert-name)"
1125051Swyllys 	    "A:(ocsp-responder-cert-serial)"
1135051Swyllys 	    "y:(ocsp-none)"
1145051Swyllys 	    "c:(crl-basefilename)"
1155051Swyllys 	    "I:(crl-directory)"
1165051Swyllys 	    "g:(crl-get-crl-uri)"
1175051Swyllys 	    "X:(crl-proxy)"
1185051Swyllys 	    "S:(crl-ignore-crl-sign)"
1195051Swyllys 	    "D:(crl-ignore-crl-date)"
1205051Swyllys 	    "z:(crl-none)"
1215051Swyllys 	    "u:(keyusage)"
1225051Swyllys 	    "Y:(keyusage-none)"
1235051Swyllys 	    "E:(ekunames)"
1245051Swyllys 	    "O:(ekuoids)"
12512611SJan.Pechanec@Sun.COM 	    "m:(mapper-name)"
12612611SJan.Pechanec@Sun.COM 	    "M:(mapper-directory)"
12712611SJan.Pechanec@Sun.COM 	    "Q:(mapper-pathname)"
12812611SJan.Pechanec@Sun.COM 	    "q:(mapper-options)"
1295051Swyllys 	    "Z:(eku-none)")) != EOF) {
1303089Swyllys 		switch (opt) {
1313089Swyllys 			case 'i':
1323089Swyllys 				filename = get_string(optarg_av, &rv);
1333089Swyllys 				if (filename == NULL) {
1343089Swyllys 					(void) fprintf(stderr,
1353089Swyllys 					    gettext("Error dbfile input.\n"));
1363089Swyllys 				}
1373089Swyllys 				break;
1383089Swyllys 			case 'p':
1393089Swyllys 				plc.name = get_string(optarg_av, &rv);
1403089Swyllys 				if (plc.name == NULL) {
1413089Swyllys 					(void) fprintf(stderr,
1423089Swyllys 					    gettext("Error policy name.\n"));
1433089Swyllys 				}
1443089Swyllys 				break;
1453089Swyllys 			case 'd':
1463089Swyllys 				plc.ignore_date = get_boolean(optarg_av);
1473089Swyllys 				if (plc.ignore_date == -1) {
1483089Swyllys 					(void) fprintf(stderr,
1493089Swyllys 					    gettext("Error boolean input.\n"));
1503089Swyllys 					rv = KC_ERR_USAGE;
1513089Swyllys 				} else {
1523089Swyllys 					flags |= KC_IGNORE_DATE;
1533089Swyllys 				}
1543089Swyllys 				break;
1553089Swyllys 			case 'e':
1563089Swyllys 				plc.ignore_unknown_ekus =
1573089Swyllys 				    get_boolean(optarg_av);
1583089Swyllys 				if (plc.ignore_unknown_ekus == -1) {
1593089Swyllys 					(void) fprintf(stderr,
1603089Swyllys 					    gettext("Error boolean input.\n"));
1613089Swyllys 					rv = KC_ERR_USAGE;
1623089Swyllys 				} else {
1633089Swyllys 					flags |= KC_IGNORE_UNKNOWN_EKUS;
1643089Swyllys 				}
1653089Swyllys 				break;
1663089Swyllys 			case 'a':
1673089Swyllys 				plc.ignore_trust_anchor =
1683089Swyllys 				    get_boolean(optarg_av);
1693089Swyllys 				if (plc.ignore_trust_anchor == -1) {
1703089Swyllys 					(void) fprintf(stderr,
1713089Swyllys 					    gettext("Error boolean input.\n"));
1723089Swyllys 					rv = KC_ERR_USAGE;
1733089Swyllys 				} else {
1743089Swyllys 					flags |= KC_IGNORE_TRUST_ANCHOR;
1753089Swyllys 				}
1763089Swyllys 				break;
1773089Swyllys 			case 'v':
1783089Swyllys 				plc.validity_adjusttime =
1793089Swyllys 				    get_string(optarg_av, &rv);
1803089Swyllys 				if (plc.validity_adjusttime == NULL) {
1813089Swyllys 					(void) fprintf(stderr,
1823089Swyllys 					    gettext("Error time input.\n"));
1833089Swyllys 				} else {
1843089Swyllys 					uint32_t adj;
1853089Swyllys 					/* for syntax checking */
1863089Swyllys 					if (str2lifetime(
1873089Swyllys 					    plc.validity_adjusttime,
1883089Swyllys 					    &adj) < 0) {
1893089Swyllys 						(void) fprintf(stderr,
1903089Swyllys 						    gettext("Error time "
1913089Swyllys 						    "input.\n"));
1923089Swyllys 						rv = KC_ERR_USAGE;
1933089Swyllys 					} else {
1943089Swyllys 						flags |= KC_VALIDITY_ADJUSTTIME;
1953089Swyllys 					}
1963089Swyllys 				}
1973089Swyllys 				break;
1983089Swyllys 			case 't':
1993089Swyllys 				plc.ta_name = get_string(optarg_av, &rv);
2003089Swyllys 				if (plc.ta_name == NULL) {
2013089Swyllys 					(void) fprintf(stderr,
2023089Swyllys 					    gettext("Error name input.\n"));
203*12919Swyllys.ingersoll@sun.com 				} else if (strcasecmp(plc.ta_name, "search")) {
2043089Swyllys 					KMF_X509_NAME taDN;
2053089Swyllys 					/* for syntax checking */
2065051Swyllys 					if (kmf_dn_parser(plc.ta_name,
2073089Swyllys 					    &taDN) != KMF_OK) {
2083089Swyllys 						(void) fprintf(stderr,
2093089Swyllys 						    gettext("Error name "
2103089Swyllys 						    "input.\n"));
2113089Swyllys 						rv = KC_ERR_USAGE;
2123089Swyllys 					} else {
2135051Swyllys 						kmf_free_dn(&taDN);
2143089Swyllys 						flags |= KC_TA_NAME;
2153089Swyllys 					}
216*12919Swyllys.ingersoll@sun.com 				} else {
217*12919Swyllys.ingersoll@sun.com 					flags |= KC_TA_NAME;
2183089Swyllys 				}
2193089Swyllys 				break;
2203089Swyllys 			case 's':
2213089Swyllys 				plc.ta_serial = get_string(optarg_av, &rv);
2223089Swyllys 				if (plc.ta_serial == NULL) {
2233089Swyllys 					(void) fprintf(stderr,
2243089Swyllys 					    gettext("Error serial input.\n"));
2253089Swyllys 				} else {
2263089Swyllys 					uchar_t *bytes = NULL;
2273089Swyllys 					size_t bytelen;
2283089Swyllys 
2295051Swyllys 					ret = kmf_hexstr_to_bytes(
2303089Swyllys 					    (uchar_t *)plc.ta_serial,
2313089Swyllys 					    &bytes, &bytelen);
2323089Swyllys 					if (ret != KMF_OK || bytes == NULL) {
2333089Swyllys 						(void) fprintf(stderr,
2343089Swyllys 						    gettext("serial number "
2353089Swyllys 						    "must be specified as a "
2363089Swyllys 						    "hex number "
2373089Swyllys 						    "(ex: 0x0102030405"
2383089Swyllys 						    "ffeeddee)\n"));
2393089Swyllys 						rv = KC_ERR_USAGE;
2403089Swyllys 						break;
2413089Swyllys 					}
2423089Swyllys 					if (bytes != NULL)
2433089Swyllys 						free(bytes);
2443089Swyllys 					flags |= KC_TA_SERIAL;
2453089Swyllys 				}
2463089Swyllys 				break;
2473089Swyllys 			case 'o':
2483089Swyllys 				plc.VAL_OCSP_RESPONDER_URI =
2495051Swyllys 				    get_string(optarg_av, &rv);
2503089Swyllys 				if (plc.VAL_OCSP_RESPONDER_URI == NULL) {
2513089Swyllys 					(void) fprintf(stderr,
2523089Swyllys 					    gettext("Error responder "
2533089Swyllys 					    "input.\n"));
2543089Swyllys 				} else {
2553089Swyllys 					flags |= KC_OCSP_RESPONDER_URI;
2563089Swyllys 					ocsp_set_attr++;
2573089Swyllys 				}
2583089Swyllys 				break;
2593089Swyllys 			case 'P':
2603089Swyllys 				plc.VAL_OCSP_PROXY = get_string(optarg_av, &rv);
2613089Swyllys 				if (plc.VAL_OCSP_PROXY == NULL) {
2623089Swyllys 					(void) fprintf(stderr,
2633089Swyllys 					    gettext("Error proxy input.\n"));
2643089Swyllys 				} else {
2653089Swyllys 					flags |= KC_OCSP_PROXY;
2663089Swyllys 					ocsp_set_attr++;
2673089Swyllys 				}
2683089Swyllys 				break;
2693089Swyllys 			case 'r':
2703089Swyllys 				plc.VAL_OCSP_URI_FROM_CERT =
2713089Swyllys 				    get_boolean(optarg_av);
2723089Swyllys 				if (plc.VAL_OCSP_URI_FROM_CERT == -1) {
2733089Swyllys 					(void) fprintf(stderr,
2743089Swyllys 					    gettext("Error boolean input.\n"));
2753089Swyllys 					rv = KC_ERR_USAGE;
2763089Swyllys 				} else {
2773089Swyllys 					flags |= KC_OCSP_URI_FROM_CERT;
2783089Swyllys 					ocsp_set_attr++;
2793089Swyllys 				}
2803089Swyllys 				break;
2813089Swyllys 			case 'T':
2823089Swyllys 				plc.VAL_OCSP_RESP_LIFETIME =
2833089Swyllys 				    get_string(optarg_av, &rv);
2843089Swyllys 				if (plc.VAL_OCSP_RESP_LIFETIME == NULL) {
2853089Swyllys 					(void) fprintf(stderr,
2863089Swyllys 					    gettext("Error time input.\n"));
2873089Swyllys 				} else {
2883089Swyllys 					uint32_t adj;
2893089Swyllys 					/* for syntax checking */
2903089Swyllys 					if (str2lifetime(
2913089Swyllys 					    plc.VAL_OCSP_RESP_LIFETIME,
2923089Swyllys 					    &adj) < 0) {
2933089Swyllys 						(void) fprintf(stderr,
2943089Swyllys 						    gettext("Error time "
2953089Swyllys 						    "input.\n"));
2963089Swyllys 						rv = KC_ERR_USAGE;
2973089Swyllys 					} else {
2983089Swyllys 						flags |= KC_OCSP_RESP_LIFETIME;
2993089Swyllys 						ocsp_set_attr++;
3003089Swyllys 					}
3013089Swyllys 				}
3023089Swyllys 				break;
3033089Swyllys 			case 'R':
3043089Swyllys 				plc.VAL_OCSP_IGNORE_RESP_SIGN =
3053089Swyllys 				    get_boolean(optarg_av);
3063089Swyllys 				if (plc.VAL_OCSP_IGNORE_RESP_SIGN == -1) {
3073089Swyllys 					(void) fprintf(stderr,
3083089Swyllys 					    gettext("Error boolean input.\n"));
3093089Swyllys 					rv = KC_ERR_USAGE;
3103089Swyllys 				} else {
3113089Swyllys 					flags |= KC_OCSP_IGNORE_RESP_SIGN;
3123089Swyllys 					ocsp_set_attr++;
3133089Swyllys 				}
3143089Swyllys 				break;
3153089Swyllys 			case 'n':
3163089Swyllys 				plc.VAL_OCSP_RESP_CERT_NAME =
3173089Swyllys 				    get_string(optarg_av, &rv);
3183089Swyllys 				if (plc.VAL_OCSP_RESP_CERT_NAME == NULL) {
3193089Swyllys 					(void) fprintf(stderr,
3203089Swyllys 					    gettext("Error name input.\n"));
3213089Swyllys 				} else {
3223089Swyllys 					KMF_X509_NAME respDN;
3233089Swyllys 					/* for syntax checking */
3245051Swyllys 					if (kmf_dn_parser(
3253089Swyllys 					    plc.VAL_OCSP_RESP_CERT_NAME,
3263089Swyllys 					    &respDN) != KMF_OK) {
3273089Swyllys 						(void) fprintf(stderr,
3283089Swyllys 						    gettext("Error name "
3293089Swyllys 						    "input.\n"));
3303089Swyllys 						rv = KC_ERR_USAGE;
3313089Swyllys 					} else {
3325051Swyllys 						kmf_free_dn(&respDN);
3333089Swyllys 						flags |= KC_OCSP_RESP_CERT_NAME;
3343089Swyllys 						ocsp_set_attr++;
3353089Swyllys 					}
3363089Swyllys 				}
3373089Swyllys 				break;
3383089Swyllys 			case 'A':
3393089Swyllys 				plc.VAL_OCSP_RESP_CERT_SERIAL =
3403089Swyllys 				    get_string(optarg_av, &rv);
3413089Swyllys 				if (plc.VAL_OCSP_RESP_CERT_SERIAL == NULL) {
3423089Swyllys 					(void) fprintf(stderr,
3433089Swyllys 					    gettext("Error serial input.\n"));
3443089Swyllys 				} else {
3453089Swyllys 					uchar_t *bytes = NULL;
3463089Swyllys 					size_t bytelen;
3473089Swyllys 
3485051Swyllys 					ret = kmf_hexstr_to_bytes((uchar_t *)
3493089Swyllys 					    plc.VAL_OCSP_RESP_CERT_SERIAL,
3503089Swyllys 					    &bytes, &bytelen);
3513089Swyllys 					if (ret != KMF_OK || bytes == NULL) {
3523089Swyllys 						(void) fprintf(stderr,
3533089Swyllys 						    gettext("serial number "
3543089Swyllys 						    "must be specified as a "
3553089Swyllys 						    "hex number "
3563089Swyllys 						    "(ex: 0x0102030405"
3573089Swyllys 						    "ffeeddee)\n"));
3583089Swyllys 						rv = KC_ERR_USAGE;
3593089Swyllys 						break;
3603089Swyllys 					}
3613089Swyllys 					if (bytes != NULL)
3623089Swyllys 						free(bytes);
3633089Swyllys 					flags |= KC_OCSP_RESP_CERT_SERIAL;
3643089Swyllys 					ocsp_set_attr++;
3653089Swyllys 				}
3663089Swyllys 				break;
3673089Swyllys 			case 'y':
3683089Swyllys 				ocsp_none_opt = get_boolean(optarg_av);
3693089Swyllys 				if (ocsp_none_opt == -1) {
3703089Swyllys 					(void) fprintf(stderr,
3713089Swyllys 					    gettext("Error boolean input.\n"));
3723089Swyllys 					rv = KC_ERR_USAGE;
3733089Swyllys 				} else {
3743089Swyllys 					flags |= KC_OCSP_NONE;
3753089Swyllys 				}
3763089Swyllys 				break;
3773089Swyllys 			case 'c':
3783089Swyllys 				plc.VAL_CRL_BASEFILENAME =
3793089Swyllys 				    get_string(optarg_av, &rv);
3803089Swyllys 				if (plc.VAL_CRL_BASEFILENAME == NULL) {
3813089Swyllys 					(void) fprintf(stderr, gettext(
3823089Swyllys 					    "Error basefilename input.\n"));
3833089Swyllys 				} else {
3843089Swyllys 					flags |= KC_CRL_BASEFILENAME;
3853089Swyllys 					crl_set_attr++;
3863089Swyllys 				}
3873089Swyllys 				break;
3883089Swyllys 			case 'I':
3893089Swyllys 				plc.VAL_CRL_DIRECTORY =
3903089Swyllys 				    get_string(optarg_av, &rv);
3913089Swyllys 				if (plc.VAL_CRL_DIRECTORY == NULL) {
3923089Swyllys 					(void) fprintf(stderr,
3933089Swyllys 					    gettext("Error boolean input.\n"));
3943089Swyllys 				} else {
3953089Swyllys 					flags |= KC_CRL_DIRECTORY;
3963089Swyllys 					crl_set_attr++;
3973089Swyllys 				}
3983089Swyllys 				break;
3993089Swyllys 			case 'g':
4003089Swyllys 				plc.VAL_CRL_GET_URI = get_boolean(optarg_av);
4013089Swyllys 				if (plc.VAL_CRL_GET_URI == -1) {
4023089Swyllys 					(void) fprintf(stderr,
4033089Swyllys 					    gettext("Error boolean input.\n"));
4043089Swyllys 					rv = KC_ERR_USAGE;
4053089Swyllys 				} else {
4063089Swyllys 					flags |= KC_CRL_GET_URI;
4073089Swyllys 					crl_set_attr++;
4083089Swyllys 				}
4093089Swyllys 				break;
4103089Swyllys 			case 'X':
4113089Swyllys 				plc.VAL_CRL_PROXY = get_string(optarg_av, &rv);
4123089Swyllys 				if (plc.VAL_CRL_PROXY == NULL) {
4133089Swyllys 					(void) fprintf(stderr,
4143089Swyllys 					    gettext("Error proxy input.\n"));
4153089Swyllys 				} else {
4163089Swyllys 					flags |= KC_CRL_PROXY;
4173089Swyllys 					crl_set_attr++;
4183089Swyllys 				}
4193089Swyllys 				break;
4203089Swyllys 			case 'S':
4213089Swyllys 				plc.VAL_CRL_IGNORE_SIGN =
4223089Swyllys 				    get_boolean(optarg_av);
4233089Swyllys 				if (plc.VAL_CRL_IGNORE_SIGN == -1) {
4243089Swyllys 					(void) fprintf(stderr,
4253089Swyllys 					    gettext("Error boolean input.\n"));
4263089Swyllys 					rv = KC_ERR_USAGE;
4273089Swyllys 				} else {
4283089Swyllys 					flags |= KC_CRL_IGNORE_SIGN;
4293089Swyllys 					crl_set_attr++;
4303089Swyllys 				}
4313089Swyllys 				break;
4323089Swyllys 			case 'D':
4333089Swyllys 				plc.VAL_CRL_IGNORE_DATE =
4345051Swyllys 				    get_boolean(optarg_av);
4353089Swyllys 				if (plc.VAL_CRL_IGNORE_DATE == -1) {
4363089Swyllys 					(void) fprintf(stderr,
4373089Swyllys 					    gettext("Error boolean input.\n"));
4383089Swyllys 					rv = KC_ERR_USAGE;
4393089Swyllys 				} else {
4403089Swyllys 					flags |= KC_CRL_IGNORE_DATE;
4413089Swyllys 					crl_set_attr++;
4423089Swyllys 				}
4433089Swyllys 				break;
4443089Swyllys 			case 'z':
4453089Swyllys 				crl_none_opt = get_boolean(optarg_av);
4463089Swyllys 				if (crl_none_opt == -1) {
4473089Swyllys 					(void) fprintf(stderr,
4483089Swyllys 					    gettext("Error boolean input.\n"));
4493089Swyllys 					rv = KC_ERR_USAGE;
4503089Swyllys 				} else {
4513089Swyllys 					flags |= KC_CRL_NONE;
4523089Swyllys 				}
4533089Swyllys 				break;
4543089Swyllys 			case 'u':
4553089Swyllys 				plc.ku_bits = parseKUlist(optarg_av);
4563089Swyllys 				if (plc.ku_bits == 0) {
4573089Swyllys 					(void) fprintf(stderr, gettext(
4583089Swyllys 					    "Error keyusage input.\n"));
4593089Swyllys 					rv = KC_ERR_USAGE;
4603089Swyllys 				} else {
4613089Swyllys 					flags |= KC_KEYUSAGE;
4623089Swyllys 				}
4633089Swyllys 				break;
4643089Swyllys 			case 'Y':
4653089Swyllys 				ku_none_opt = get_boolean(optarg_av);
4663089Swyllys 				if (ku_none_opt == -1) {
4673089Swyllys 					(void) fprintf(stderr,
4683089Swyllys 					    gettext("Error boolean input.\n"));
4693089Swyllys 					rv = KC_ERR_USAGE;
4703089Swyllys 				} else {
4713089Swyllys 					flags |= KC_KEYUSAGE_NONE;
4723089Swyllys 				}
4733089Swyllys 				break;
4743089Swyllys 			case 'E':
4753089Swyllys 				if (parseEKUNames(optarg_av, &plc) != 0) {
4763089Swyllys 					(void) fprintf(stderr,
4773089Swyllys 					    gettext("Error EKU input.\n"));
4783089Swyllys 					rv = KC_ERR_USAGE;
4793089Swyllys 				} else {
4803089Swyllys 					flags |= KC_EKUS;
4813089Swyllys 				}
4823089Swyllys 				break;
4833089Swyllys 			case 'O':
4843089Swyllys 				if (parseEKUOIDs(optarg_av, &plc) != 0) {
4853089Swyllys 					(void) fprintf(stderr,
4863089Swyllys 					    gettext("Error EKU OID input.\n"));
4873089Swyllys 					rv = KC_ERR_USAGE;
4883089Swyllys 				} else {
4893089Swyllys 					flags |= KC_EKUS;
4903089Swyllys 				}
4913089Swyllys 				break;
4923089Swyllys 			case 'Z':
4933089Swyllys 				eku_none_opt = get_boolean(optarg_av);
4943089Swyllys 				if (eku_none_opt == -1) {
4953089Swyllys 					(void) fprintf(stderr,
4963089Swyllys 					    gettext("Error boolean input.\n"));
4973089Swyllys 					rv = KC_ERR_USAGE;
4983089Swyllys 				} else {
4993089Swyllys 					flags |= KC_EKUS_NONE;
5003089Swyllys 				}
5013089Swyllys 				break;
50212611SJan.Pechanec@Sun.COM 			case 'm':
50312611SJan.Pechanec@Sun.COM 				mapper_name = get_string(optarg_av, &rv);
50412611SJan.Pechanec@Sun.COM 				if (mapper_name == NULL) {
50512611SJan.Pechanec@Sun.COM 					(void) fprintf(stderr,
50612611SJan.Pechanec@Sun.COM 					    gettext("Error mapper-name "
50712611SJan.Pechanec@Sun.COM 					    "input.\n"));
50812611SJan.Pechanec@Sun.COM 				}
50912611SJan.Pechanec@Sun.COM 				break;
51012611SJan.Pechanec@Sun.COM 			case 'M':
51112611SJan.Pechanec@Sun.COM 				mapper_dir = get_string(optarg_av, &rv);
51212611SJan.Pechanec@Sun.COM 				if (mapper_dir == NULL) {
51312611SJan.Pechanec@Sun.COM 					(void) fprintf(stderr,
51412611SJan.Pechanec@Sun.COM 					    gettext("Error mapper-directory "
51512611SJan.Pechanec@Sun.COM 					    "input.\n"));
51612611SJan.Pechanec@Sun.COM 				}
51712611SJan.Pechanec@Sun.COM 				break;
51812611SJan.Pechanec@Sun.COM 			case 'Q':
51912611SJan.Pechanec@Sun.COM 				mapper_pathname = get_string(optarg_av, &rv);
52012611SJan.Pechanec@Sun.COM 				if (mapper_pathname == NULL) {
52112611SJan.Pechanec@Sun.COM 					(void) fprintf(stderr,
52212611SJan.Pechanec@Sun.COM 					    gettext("Error mapper-pathname "
52312611SJan.Pechanec@Sun.COM 					    "input.\n"));
52412611SJan.Pechanec@Sun.COM 				}
52512611SJan.Pechanec@Sun.COM 				break;
52612611SJan.Pechanec@Sun.COM 			case 'q':
52712611SJan.Pechanec@Sun.COM 				plc.mapper.options = get_string(optarg_av, &rv);
52812611SJan.Pechanec@Sun.COM 				rv = 0; /* its ok for this to be NULL */
52912611SJan.Pechanec@Sun.COM 				flags |= KC_MAPPER_OPTIONS;
53012611SJan.Pechanec@Sun.COM 				break;
5313089Swyllys 			default:
5323089Swyllys 				(void) fprintf(stderr,
5333089Swyllys 				    gettext("Error input option.\n"));
5343089Swyllys 				rv = KC_ERR_USAGE;
5353089Swyllys 				break;
5363089Swyllys 		}
5373089Swyllys 		if (rv != KC_OK)
5383089Swyllys 			goto out;
5393089Swyllys 	}
5403089Swyllys 
5413089Swyllys 	/* No additional args allowed. */
5423089Swyllys 	argc -= optind_av;
5433089Swyllys 	if (argc) {
5443089Swyllys 		(void) fprintf(stderr,
5453089Swyllys 		    gettext("Error input option\n"));
5463089Swyllys 		rv = KC_ERR_USAGE;
5473089Swyllys 		goto out;
5483089Swyllys 	}
5493089Swyllys 
5503089Swyllys 	if (filename == NULL) {
5513089Swyllys 		filename = strdup(KMF_DEFAULT_POLICY_FILE);
5523089Swyllys 		if (filename == NULL) {
5533089Swyllys 			rv = KC_ERR_MEMORY;
5543089Swyllys 			goto out;
5553089Swyllys 		}
5563089Swyllys 	}
5573089Swyllys 
5583089Swyllys 	/*
5593089Swyllys 	 * Must have a policy name. The policy name can not be default
5603089Swyllys 	 * if using the default policy file.
5613089Swyllys 	 */
5623089Swyllys 	if (plc.name == NULL) {
5633089Swyllys 		(void) fprintf(stderr,
5643089Swyllys 		    gettext("You must specify a policy name.\n"));
5653089Swyllys 		rv = KC_ERR_USAGE;
5663089Swyllys 		goto out;
5673089Swyllys 	} else if (strcmp(filename, KMF_DEFAULT_POLICY_FILE) == 0 &&
5683089Swyllys 	    strcmp(plc.name, KMF_DEFAULT_POLICY_NAME) == 0) {
5693089Swyllys 		(void) fprintf(stderr,
5703089Swyllys 		    gettext("Can not modify the default policy in the default "
5713089Swyllys 		    "policy file.\n"));
5723089Swyllys 		rv = KC_ERR_USAGE;
5733089Swyllys 		goto out;
5743089Swyllys 	}
5753089Swyllys 
5763089Swyllys 	/* Check the access permission of the policy DB */
5773089Swyllys 	if (access(filename, W_OK) < 0) {
5783089Swyllys 		int err = errno;
5793089Swyllys 		(void) fprintf(stderr,
5803089Swyllys 		    gettext("Cannot access \"%s\" for modify - %s\n"),
5813089Swyllys 		    filename, strerror(err));
5823089Swyllys 		rv = KC_ERR_ACCESS;
5833089Swyllys 		goto out;
5843089Swyllys 	}
5853089Swyllys 
5863089Swyllys 	/* Try to load the named policy from the DB */
5875051Swyllys 	ret = kmf_get_policy(filename, plc.name, &oplc);
5883089Swyllys 	if (ret != KMF_OK) {
5893089Swyllys 		(void) fprintf(stderr,
5903089Swyllys 		    gettext("Error loading policy \"%s\" from %s\n"), filename,
5913089Swyllys 		    plc.name);
5923089Swyllys 		return (KC_ERR_FIND_POLICY);
5933089Swyllys 	}
5943089Swyllys 
5953089Swyllys 	/* Update the general policy attributes. */
5963089Swyllys 	if (flags & KC_IGNORE_DATE)
5973089Swyllys 		oplc.ignore_date = plc.ignore_date;
5983089Swyllys 
5993089Swyllys 	if (flags & KC_IGNORE_UNKNOWN_EKUS)
6003089Swyllys 		oplc.ignore_unknown_ekus = plc.ignore_unknown_ekus;
6013089Swyllys 
6023089Swyllys 	if (flags & KC_IGNORE_TRUST_ANCHOR)
6033089Swyllys 		oplc.ignore_trust_anchor = plc.ignore_trust_anchor;
6043089Swyllys 
6053089Swyllys 	if (flags & KC_VALIDITY_ADJUSTTIME) {
6063089Swyllys 		if (oplc.validity_adjusttime)
6073089Swyllys 			free(oplc.validity_adjusttime);
6083089Swyllys 		oplc.validity_adjusttime =
6095051Swyllys 		    plc.validity_adjusttime;
6103089Swyllys 	}
6113089Swyllys 
6123089Swyllys 	if (flags & KC_TA_NAME) {
6133089Swyllys 		if (oplc.ta_name)
6143089Swyllys 			free(oplc.ta_name);
6153089Swyllys 		oplc.ta_name = plc.ta_name;
6163089Swyllys 	}
6173089Swyllys 	if (flags & KC_TA_SERIAL) {
6183089Swyllys 		if (oplc.ta_serial)
6193089Swyllys 			free(oplc.ta_serial);
6203089Swyllys 		oplc.ta_serial = plc.ta_serial;
6213089Swyllys 	}
6223089Swyllys 
62312611SJan.Pechanec@Sun.COM 	/*
62412611SJan.Pechanec@Sun.COM 	 * There are some combinations of attributes that are not valid.
62512611SJan.Pechanec@Sun.COM 	 *
62612611SJan.Pechanec@Sun.COM 	 * First, setting mapper-name (with optional mapper-directory) and
62712611SJan.Pechanec@Sun.COM 	 * mapper-pathname is mutually exclusive.
62812611SJan.Pechanec@Sun.COM 	 */
62912611SJan.Pechanec@Sun.COM 	if ((mapper_name != NULL && mapper_pathname != NULL) ||
63012611SJan.Pechanec@Sun.COM 	    (mapper_name != NULL && oplc.mapper.pathname != NULL) ||
63112611SJan.Pechanec@Sun.COM 	    (mapper_pathname != NULL && oplc.mapper.mapname != NULL) ||
63212611SJan.Pechanec@Sun.COM 	    /* Mapper directory can be set only if mapper name is set. */
63312611SJan.Pechanec@Sun.COM 	    (mapper_dir != NULL && mapper_pathname != NULL) ||
63412611SJan.Pechanec@Sun.COM 	    (mapper_dir != NULL && mapper_name == NULL &&
63512611SJan.Pechanec@Sun.COM 	    oplc.mapper.mapname == NULL) ||
63612611SJan.Pechanec@Sun.COM 	    (mapper_dir != NULL && oplc.mapper.pathname != NULL) ||
63712611SJan.Pechanec@Sun.COM 	    /* Options can be set only if mapper name or pathname is set. */
63812611SJan.Pechanec@Sun.COM 	    ((plc.mapper.options != NULL || oplc.mapper.options != NULL) &&
63912611SJan.Pechanec@Sun.COM 	    (mapper_name == NULL && oplc.mapper.mapname == NULL &&
64012611SJan.Pechanec@Sun.COM 	    mapper_pathname == NULL && oplc.mapper.pathname == NULL))) {
64112611SJan.Pechanec@Sun.COM 		(void) fprintf(stderr,
64212611SJan.Pechanec@Sun.COM 		    gettext("Error in mapper input options\n"));
64312611SJan.Pechanec@Sun.COM 		if (mapper_name != NULL)
64412611SJan.Pechanec@Sun.COM 			free(mapper_name);
64512611SJan.Pechanec@Sun.COM 		if (mapper_pathname != NULL)
64612611SJan.Pechanec@Sun.COM 			free(mapper_pathname);
64712611SJan.Pechanec@Sun.COM 		if (mapper_dir != NULL)
64812611SJan.Pechanec@Sun.COM 			free(mapper_dir);
64912611SJan.Pechanec@Sun.COM 		if (flags & KC_MAPPER_OPTIONS && plc.mapper.options != NULL)
65012611SJan.Pechanec@Sun.COM 			free(plc.mapper.options);
65112611SJan.Pechanec@Sun.COM 		rv = KC_ERR_USAGE;
65212611SJan.Pechanec@Sun.COM 		goto out;
65312611SJan.Pechanec@Sun.COM 	} else {
65412611SJan.Pechanec@Sun.COM 		if (mapper_name != NULL)
65512611SJan.Pechanec@Sun.COM 			plc.mapper.mapname = mapper_name;
65612611SJan.Pechanec@Sun.COM 		if (mapper_pathname != NULL)
65712611SJan.Pechanec@Sun.COM 			plc.mapper.pathname = mapper_pathname;
65812611SJan.Pechanec@Sun.COM 		if (mapper_dir != NULL)
65912611SJan.Pechanec@Sun.COM 			plc.mapper.dir = mapper_dir;
66012611SJan.Pechanec@Sun.COM 	}
66112611SJan.Pechanec@Sun.COM 
66212611SJan.Pechanec@Sun.COM 	UPDATE_IF_DIFFERENT(oplc.mapper.mapname, plc.mapper.mapname);
66312611SJan.Pechanec@Sun.COM 	UPDATE_IF_DIFFERENT(oplc.mapper.pathname, plc.mapper.pathname);
66412611SJan.Pechanec@Sun.COM 	UPDATE_IF_DIFFERENT(oplc.mapper.dir, plc.mapper.dir);
66512611SJan.Pechanec@Sun.COM 
66612611SJan.Pechanec@Sun.COM 	if (flags & KC_MAPPER_OPTIONS) {
66712611SJan.Pechanec@Sun.COM 		if (oplc.mapper.options != NULL)
66812611SJan.Pechanec@Sun.COM 			free(oplc.mapper.options);
66912611SJan.Pechanec@Sun.COM 		oplc.mapper.options = plc.mapper.options;
67012611SJan.Pechanec@Sun.COM 	}
67112611SJan.Pechanec@Sun.COM 
6723089Swyllys 	/* Update the OCSP policy */
6733089Swyllys 	if (ocsp_none_opt == B_TRUE) {
6743089Swyllys 		if (ocsp_set_attr > 0) {
6753089Swyllys 			(void) fprintf(stderr,
6763089Swyllys 			    gettext("Can not set ocsp-none=true and other "
6773089Swyllys 			    "OCSP attributes at the same time.\n"));
6783089Swyllys 			rv = KC_ERR_USAGE;
6793089Swyllys 			goto out;
6803089Swyllys 		}
6813089Swyllys 
6823089Swyllys 		/*
6833089Swyllys 		 * If the original policy does not have OCSP checking,
6843089Swyllys 		 * then we do not need to do anything.  If the original
6853089Swyllys 		 * policy has the OCSP checking, then we need to release the
6863089Swyllys 		 * space of OCSP attributes and turn the OCSP checking off.
6873089Swyllys 		 */
6883089Swyllys 		if (oplc.revocation & KMF_REVOCATION_METHOD_OCSP) {
6893089Swyllys 			if (oplc.VAL_OCSP_BASIC.responderURI) {
6903089Swyllys 				free(oplc.VAL_OCSP_BASIC.responderURI);
6913089Swyllys 				oplc.VAL_OCSP_BASIC.responderURI = NULL;
6923089Swyllys 			}
6933089Swyllys 
6943089Swyllys 			if (oplc.VAL_OCSP_BASIC.proxy) {
6953089Swyllys 				free(oplc.VAL_OCSP_BASIC.proxy);
6963089Swyllys 				oplc.VAL_OCSP_BASIC.proxy = NULL;
6973089Swyllys 			}
6983089Swyllys 
6993089Swyllys 			if (oplc.VAL_OCSP_BASIC.response_lifetime) {
7003089Swyllys 				free(oplc.VAL_OCSP_BASIC.response_lifetime);
7013089Swyllys 				oplc.VAL_OCSP_BASIC.response_lifetime = NULL;
7023089Swyllys 			}
7033089Swyllys 
7043089Swyllys 			if (flags & KC_OCSP_RESP_CERT_NAME) {
7053089Swyllys 				free(oplc.VAL_OCSP_RESP_CERT.name);
7063089Swyllys 				oplc.VAL_OCSP_RESP_CERT.name = NULL;
7073089Swyllys 			}
7083089Swyllys 
7093089Swyllys 			if (flags & KC_OCSP_RESP_CERT_SERIAL) {
7103089Swyllys 				free(oplc.VAL_OCSP_RESP_CERT.serial);
7113089Swyllys 				oplc.VAL_OCSP_RESP_CERT.serial = NULL;
7123089Swyllys 			}
7133089Swyllys 
7143089Swyllys 			/* Turn off the OCSP checking */
7153089Swyllys 			oplc.revocation &= ~KMF_REVOCATION_METHOD_OCSP;
7163089Swyllys 		}
7173089Swyllys 
7183089Swyllys 	} else {
7193089Swyllys 		/*
7203089Swyllys 		 * If the "ocsp-none" option is not set or is set to false,
7213089Swyllys 		 * then we only need to do the modification if there is at
7223089Swyllys 		 * least one OCSP attribute is specified.
7233089Swyllys 		 */
7243089Swyllys 		if (ocsp_set_attr > 0) {
7253089Swyllys 			if (flags & KC_OCSP_RESPONDER_URI) {
7263089Swyllys 				if (oplc.VAL_OCSP_RESPONDER_URI)
7273089Swyllys 					free(oplc.VAL_OCSP_RESPONDER_URI);
7283089Swyllys 				oplc.VAL_OCSP_RESPONDER_URI =
7295051Swyllys 				    plc.VAL_OCSP_RESPONDER_URI;
7303089Swyllys 			}
7313089Swyllys 
7323089Swyllys 			if (flags & KC_OCSP_PROXY) {
7333089Swyllys 				if (oplc.VAL_OCSP_PROXY)
7343089Swyllys 					free(oplc.VAL_OCSP_PROXY);
7353089Swyllys 				oplc.VAL_OCSP_PROXY = plc.VAL_OCSP_PROXY;
7363089Swyllys 			}
7373089Swyllys 
7383089Swyllys 			if (flags & KC_OCSP_URI_FROM_CERT)
7393089Swyllys 				oplc.VAL_OCSP_URI_FROM_CERT =
7405051Swyllys 				    plc.VAL_OCSP_URI_FROM_CERT;
7413089Swyllys 
7423089Swyllys 			if (flags & KC_OCSP_RESP_LIFETIME) {
7433089Swyllys 				if (oplc.VAL_OCSP_RESP_LIFETIME)
7443089Swyllys 					free(oplc.VAL_OCSP_RESP_LIFETIME);
7453089Swyllys 				oplc.VAL_OCSP_RESP_LIFETIME =
7465051Swyllys 				    plc.VAL_OCSP_RESP_LIFETIME;
7473089Swyllys 			}
7483089Swyllys 
7493089Swyllys 			if (flags & KC_OCSP_IGNORE_RESP_SIGN)
7503089Swyllys 				oplc.VAL_OCSP_IGNORE_RESP_SIGN =
7515051Swyllys 				    plc.VAL_OCSP_IGNORE_RESP_SIGN;
7523089Swyllys 
7533089Swyllys 			if (flags & KC_OCSP_RESP_CERT_NAME) {
7543089Swyllys 				if (oplc.VAL_OCSP_RESP_CERT_NAME)
7553089Swyllys 					free(oplc.VAL_OCSP_RESP_CERT_NAME);
7563089Swyllys 				oplc.VAL_OCSP_RESP_CERT_NAME =
7575051Swyllys 				    plc.VAL_OCSP_RESP_CERT_NAME;
7583089Swyllys 			}
7593089Swyllys 
7603089Swyllys 			if (flags & KC_OCSP_RESP_CERT_SERIAL) {
7613089Swyllys 				if (oplc.VAL_OCSP_RESP_CERT_SERIAL)
7623089Swyllys 					free(oplc.VAL_OCSP_RESP_CERT_SERIAL);
7633089Swyllys 				oplc.VAL_OCSP_RESP_CERT_SERIAL =
7645051Swyllys 				    plc.VAL_OCSP_RESP_CERT_SERIAL;
7653089Swyllys 			}
7663089Swyllys 
7673089Swyllys 			if (oplc.VAL_OCSP_RESP_CERT_NAME != NULL &&
7683089Swyllys 			    oplc.VAL_OCSP_RESP_CERT_SERIAL != NULL)
7693089Swyllys 				oplc.VAL_OCSP.has_resp_cert = B_TRUE;
7703089Swyllys 			else
7713089Swyllys 				oplc.VAL_OCSP.has_resp_cert = B_FALSE;
7723089Swyllys 
7733089Swyllys 			/* Turn on the OCSP checking */
7743089Swyllys 			oplc.revocation |= KMF_REVOCATION_METHOD_OCSP;
7753089Swyllys 		}
7763089Swyllys 	}
7773089Swyllys 
7783089Swyllys 	/* Update the CRL policy */
7793089Swyllys 	if (crl_none_opt == B_TRUE) {
7803089Swyllys 		if (crl_set_attr > 0) {
7813089Swyllys 			(void) fprintf(stderr,
7823089Swyllys 			    gettext("Can not set crl-none=true and other CRL "
7833089Swyllys 			    "attributes at the same time.\n"));
7843089Swyllys 			rv = KC_ERR_USAGE;
7853089Swyllys 			goto out;
7863089Swyllys 		}
7873089Swyllys 
7883089Swyllys 		/*
7893089Swyllys 		 * If the original policy does not have CRL checking,
7903089Swyllys 		 * then we do not need to do anything.  If the original
7913089Swyllys 		 * policy has the CRL checking, then we need to release the
7923089Swyllys 		 * space of CRL attributes and turn the CRL checking off.
7933089Swyllys 		 */
7943089Swyllys 		if (oplc.revocation & KMF_REVOCATION_METHOD_CRL) {
7953089Swyllys 			if (oplc.VAL_CRL_BASEFILENAME) {
7963089Swyllys 				free(oplc.VAL_CRL_BASEFILENAME);
7973089Swyllys 				oplc.VAL_CRL_BASEFILENAME = NULL;
7983089Swyllys 			}
7993089Swyllys 
8003089Swyllys 			if (oplc.VAL_CRL_DIRECTORY) {
8013089Swyllys 				free(oplc.VAL_CRL_DIRECTORY);
8023089Swyllys 				oplc.VAL_CRL_DIRECTORY = NULL;
8033089Swyllys 			}
8043089Swyllys 
8053089Swyllys 			if (oplc.VAL_CRL_PROXY) {
8063089Swyllys 				free(oplc.VAL_CRL_PROXY);
8073089Swyllys 				oplc.VAL_CRL_PROXY = NULL;
8083089Swyllys 			}
8093089Swyllys 
8103089Swyllys 			/* Turn off the CRL checking */
8113089Swyllys 			oplc.revocation &= ~KMF_REVOCATION_METHOD_CRL;
8123089Swyllys 		}
8133089Swyllys 	} else {
8143089Swyllys 		/*
8153089Swyllys 		 * If the "ocsp-none" option is not set or is set to false,
8163089Swyllys 		 * then we only need to do the modification if there is at
8173089Swyllys 		 * least one CRL attribute is specified.
8183089Swyllys 		 */
8193089Swyllys 		if (crl_set_attr > 0) {
8203089Swyllys 			if (flags & KC_CRL_BASEFILENAME) {
8213089Swyllys 				if (oplc.VAL_CRL_BASEFILENAME)
8223089Swyllys 					free(oplc.VAL_CRL_BASEFILENAME);
8233089Swyllys 				oplc.VAL_CRL_BASEFILENAME =
8243089Swyllys 				    plc.VAL_CRL_BASEFILENAME;
8253089Swyllys 			}
8263089Swyllys 
8273089Swyllys 			if (flags & KC_CRL_DIRECTORY) {
8283089Swyllys 				if (oplc.VAL_CRL_DIRECTORY)
8293089Swyllys 					free(oplc.VAL_CRL_DIRECTORY);
8303089Swyllys 				oplc.VAL_CRL_DIRECTORY = plc.VAL_CRL_DIRECTORY;
8313089Swyllys 			}
8323089Swyllys 
8333089Swyllys 			if (flags & KC_CRL_GET_URI) {
8343089Swyllys 				oplc.VAL_CRL_GET_URI = plc.VAL_CRL_GET_URI;
8353089Swyllys 			}
8363089Swyllys 
8373089Swyllys 			if (flags & KC_CRL_PROXY) {
8383089Swyllys 				if (oplc.VAL_CRL_PROXY)
8393089Swyllys 					free(oplc.VAL_CRL_PROXY);
8403089Swyllys 				oplc.VAL_CRL_PROXY = plc.VAL_CRL_PROXY;
8413089Swyllys 			}
8423089Swyllys 
8433089Swyllys 			if (flags & KC_CRL_IGNORE_SIGN) {
8443089Swyllys 				oplc.VAL_CRL_IGNORE_SIGN =
8453089Swyllys 				    plc.VAL_CRL_IGNORE_SIGN;
8463089Swyllys 			}
8473089Swyllys 
8483089Swyllys 			if (flags & KC_CRL_IGNORE_DATE) {
8493089Swyllys 				oplc.VAL_CRL_IGNORE_DATE =
8503089Swyllys 				    plc.VAL_CRL_IGNORE_DATE;
8513089Swyllys 			}
8523089Swyllys 
8533089Swyllys 			/* Turn on the CRL checking */
8543089Swyllys 			oplc.revocation |= KMF_REVOCATION_METHOD_CRL;
8553089Swyllys 		}
8563089Swyllys 	}
8573089Swyllys 
8583089Swyllys 	/* Update the Key Usage */
8593089Swyllys 	if (ku_none_opt == B_TRUE) {
8603089Swyllys 		if (flags & KC_KEYUSAGE) {
8613089Swyllys 			(void) fprintf(stderr,
8623089Swyllys 			    gettext("Can not set keyusage-none=true and "
8633089Swyllys 			    "modify the keyusage value at the same time.\n"));
8643089Swyllys 			rv = KC_ERR_USAGE;
8653089Swyllys 			goto out;
8663089Swyllys 		}
8673089Swyllys 
8683089Swyllys 		oplc.ku_bits = 0;
8693089Swyllys 	} else {
8703089Swyllys 		/*
8713089Swyllys 		 * If the "keyusage-none" option is not set or is set to
8723089Swyllys 		 * false, then we only need to do the modification if
8733089Swyllys 		 * the keyusage value is specified.
8743089Swyllys 		 */
8753089Swyllys 		if (flags & KC_KEYUSAGE)
8763089Swyllys 			oplc.ku_bits = plc.ku_bits;
8773089Swyllys 	}
8783089Swyllys 
8793089Swyllys 
8803089Swyllys 	/* Update the Extended Key Usage */
8813089Swyllys 	if (eku_none_opt == B_TRUE) {
8823089Swyllys 		if (flags & KC_EKUS) {
8833089Swyllys 			(void) fprintf(stderr,
8843089Swyllys 			    gettext("Can not set eku-none=true and modify "
8853089Swyllys 			    "EKU values at the same time.\n"));
8863089Swyllys 			rv = KC_ERR_USAGE;
8873089Swyllys 			goto out;
8883089Swyllys 		}
8893089Swyllys 
8903089Swyllys 		/* Release current EKU list (if any) */
8913089Swyllys 		if (oplc.eku_set.eku_count > 0) {
8925051Swyllys 			kmf_free_eku_policy(&oplc.eku_set);
8933089Swyllys 			oplc.eku_set.eku_count = 0;
8943089Swyllys 			oplc.eku_set.ekulist = NULL;
8953089Swyllys 		}
8963089Swyllys 	} else {
8973089Swyllys 		/*
8983089Swyllys 		 * If the "eku-none" option is not set or is set to false,
8993089Swyllys 		 * then we only need to do the modification if either
9003089Swyllys 		 * "ekuname" or "ekuoids" is specified.
9013089Swyllys 		 */
9023089Swyllys 		if (flags & KC_EKUS) {
9033089Swyllys 			/* Release current EKU list (if any) */
9045051Swyllys 			kmf_free_eku_policy(&oplc.eku_set);
9053089Swyllys 			oplc.eku_set = plc.eku_set;
9063089Swyllys 		}
9073089Swyllys 	}
9083089Swyllys 
9093089Swyllys 	/* Do a sanity check on the modified policy */
9105051Swyllys 	ret = kmf_verify_policy(&oplc);
9113089Swyllys 	if (ret != KMF_OK) {
9123089Swyllys 		print_sanity_error(ret);
9133089Swyllys 		rv = KC_ERR_VERIFY_POLICY;
9143089Swyllys 		goto out;
9153089Swyllys 	}
9163089Swyllys 
9173089Swyllys 	/* The modify operation is a delete followed by an add */
9185051Swyllys 	ret = kmf_delete_policy_from_db(oplc.name, filename);
9193089Swyllys 	if (ret != KMF_OK) {
9203089Swyllys 		rv = KC_ERR_DELETE_POLICY;
9213089Swyllys 		goto out;
9223089Swyllys 	}
9233089Swyllys 
9243089Swyllys 	/*
9253089Swyllys 	 * Now add the modified policy back to the DB.
9263089Swyllys 	 */
9275051Swyllys 	ret = kmf_add_policy_to_db(&oplc, filename, B_FALSE);
9283089Swyllys 	if (ret != KMF_OK) {
9293089Swyllys 		(void) fprintf(stderr,
9303089Swyllys 		    gettext("Error adding policy to database: 0x%04x\n"), ret);
9313089Swyllys 		rv = KC_ERR_ADD_POLICY;
9323089Swyllys 		goto out;
9333089Swyllys 	}
9343089Swyllys 
9353089Swyllys out:
9363089Swyllys 	if (filename != NULL)
9373089Swyllys 		free(filename);
9383089Swyllys 
9395051Swyllys 	kmf_free_policy_record(&oplc);
9403089Swyllys 
9413089Swyllys 	return (rv);
9423089Swyllys }
9435626Shylee 
9445626Shylee static int
kc_modify_plugin(int argc,char * argv[])9455626Shylee kc_modify_plugin(int argc, char *argv[])
9465626Shylee {
9475626Shylee 	int 		rv = KC_OK;
9485626Shylee 	int		opt;
9495626Shylee 	extern int	optind_av;
9505626Shylee 	extern char	*optarg_av;
9515626Shylee 	char 		*keystore_name = NULL;
9525626Shylee 	char		*option = NULL;
9535626Shylee 	boolean_t	modify_plugin = B_FALSE;
9545626Shylee 	boolean_t 	has_option_arg = B_FALSE;
9555626Shylee 	conf_entry_t	*entry = NULL;
9565626Shylee 	FILE		*pfile = NULL;
9575626Shylee 	FILE		*pfile_tmp = NULL;
9585626Shylee 	char		tmpfile_name[MAXPATHLEN];
9595626Shylee 	char 		buffer[MAXPATHLEN];
9605626Shylee 	char 		buffer2[MAXPATHLEN];
9615626Shylee 
9625626Shylee 	while ((opt = getopt_av(argc, argv, "p(plugin)k:(keystore)o:(option)"))
9635626Shylee 	    != EOF) {
9645626Shylee 		switch (opt) {
9655626Shylee 		case 'p':
9665626Shylee 			if (modify_plugin) {
9675626Shylee 				(void) fprintf(stderr,
9685626Shylee 				    gettext("duplicate plugin input.\n"));
9695626Shylee 				rv = KC_ERR_USAGE;
9705626Shylee 			} else {
9715626Shylee 				modify_plugin = B_TRUE;
9725626Shylee 			}
9735626Shylee 			break;
9745626Shylee 		case 'k':
9755626Shylee 			if (keystore_name != NULL)
9765626Shylee 				rv = KC_ERR_USAGE;
9775626Shylee 			else {
9785626Shylee 				keystore_name = get_string(optarg_av, &rv);
9795626Shylee 				if (keystore_name == NULL) {
9805626Shylee 					(void) fprintf(stderr, gettext(
9815626Shylee 					    "Error keystore input.\n"));
9825626Shylee 					rv = KC_ERR_USAGE;
9835626Shylee 				}
9845626Shylee 			}
9855626Shylee 			break;
9865626Shylee 		case 'o':
9875626Shylee 			if (has_option_arg) {
9885626Shylee 				(void) fprintf(stderr,
9895626Shylee 				    gettext("duplicate option input.\n"));
9905626Shylee 				rv = KC_ERR_USAGE;
9915626Shylee 			} else {
9925626Shylee 				has_option_arg = B_TRUE;
9935626Shylee 				option = get_string(optarg_av, NULL);
9945626Shylee 			}
9955626Shylee 			break;
9965626Shylee 		default:
9975626Shylee 			(void) fprintf(stderr,
9985626Shylee 			    gettext("Error input option.\n"));
9995626Shylee 			rv = KC_ERR_USAGE;
10005626Shylee 			break;
10015626Shylee 		}
10025626Shylee 
10035626Shylee 		if (rv != KC_OK)
10045626Shylee 			goto out;
10055626Shylee 	}
10065626Shylee 
10075626Shylee 	/* No additional args allowed. */
10085626Shylee 	argc -= optind_av;
10095626Shylee 	if (argc) {
10105626Shylee 		(void) fprintf(stderr,
10115626Shylee 		    gettext("Error input option\n"));
10125626Shylee 		rv = KC_ERR_USAGE;
10135626Shylee 		goto out;
10145626Shylee 	}
10155626Shylee 
10165626Shylee 	if (keystore_name == NULL || has_option_arg == B_FALSE) {
10175626Shylee 		(void) fprintf(stderr,
10185626Shylee 		    gettext("Error input option\n"));
10195626Shylee 		rv = KC_ERR_USAGE;
10205626Shylee 		goto out;
10215626Shylee 	}
10225626Shylee 
10235626Shylee 	if (strcasecmp(keystore_name, "nss") == 0 ||
10245626Shylee 	    strcasecmp(keystore_name, "pkcs11") == 0 ||
10255626Shylee 	    strcasecmp(keystore_name, "file") == 0) {
10265626Shylee 		(void) fprintf(stderr,
10275626Shylee 		    gettext("Can not modify the built-in keystore %s\n"),
10285626Shylee 		    keystore_name);
10295626Shylee 		rv = KC_ERR_USAGE;
10305626Shylee 		goto out;
10315626Shylee 	}
10325626Shylee 
10335626Shylee 	entry = get_keystore_entry(keystore_name);
10345626Shylee 	if (entry == NULL) {
10355626Shylee 		(void) fprintf(stderr, gettext("%s does not exist.\n"),
10365626Shylee 		    keystore_name);
10375626Shylee 		rv = KC_ERR_USAGE;
10385626Shylee 		goto out;
10395626Shylee 	}
10405626Shylee 
10415626Shylee 	if ((entry->option == NULL && option == NULL) ||
10425626Shylee 	    (entry->option != NULL && option != NULL &&
10435626Shylee 	    strcmp(entry->option, option) == 0)) {
10445626Shylee 		(void) fprintf(stderr, gettext("No change - "
10455626Shylee 		    "the new option is same as the old option.\n"));
10465626Shylee 		rv = KC_OK;
10475626Shylee 		goto out;
10485626Shylee 	}
10495626Shylee 
10505626Shylee 	if ((pfile = fopen(_PATH_KMF_CONF, "r+")) == NULL) {
10515626Shylee 		err = errno;
10525626Shylee 		(void) fprintf(stderr,
10535626Shylee 		    gettext("failed to update the configuration - %s\n"),
10545626Shylee 		    strerror(err));
10555626Shylee 		rv = KC_ERR_ACCESS;
10565626Shylee 		goto out;
10575626Shylee 	}
10585626Shylee 
10595626Shylee 	if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
10605626Shylee 		err = errno;
10615626Shylee 		(void) fprintf(stderr,
10625626Shylee 		    gettext("failed to lock the configuration - %s\n"),
10635626Shylee 		    strerror(err));
10645626Shylee 		rv = KC_ERR_MODIFY_PLUGIN;
10655626Shylee 		goto out;
10665626Shylee 	}
10675626Shylee 
10685626Shylee 	/*
10695626Shylee 	 * Create a temporary file in the /etc/crypto directory.
10705626Shylee 	 */
10715626Shylee 	(void) strlcpy(tmpfile_name, CONF_TEMPFILE, sizeof (tmpfile_name));
10725626Shylee 	if (mkstemp(tmpfile_name) == -1) {
10735626Shylee 		err = errno;
10745626Shylee 		(void) fprintf(stderr,
10755626Shylee 		    gettext("failed to create a temporary file - %s\n"),
10765626Shylee 		    strerror(err));
10775626Shylee 		rv = KC_ERR_MODIFY_PLUGIN;
10785626Shylee 		goto out;
10795626Shylee 	}
10805626Shylee 
10815626Shylee 	if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
10825626Shylee 		err = errno;
10835626Shylee 		(void) fprintf(stderr,
10845626Shylee 		    gettext("failed to open %s - %s\n"),
10855626Shylee 		    tmpfile_name, strerror(err));
10865626Shylee 		rv = KC_ERR_MODIFY_PLUGIN;
10875626Shylee 		goto out;
10885626Shylee 	}
10895626Shylee 
10905626Shylee 	/*
10915626Shylee 	 * Loop thru the config file and update the entry.
10925626Shylee 	 */
10935626Shylee 	while (fgets(buffer, MAXPATHLEN, pfile) != NULL) {
10945626Shylee 		char *name;
10955626Shylee 		int len;
10965626Shylee 
10975626Shylee 		if (buffer[0] == '#') {
10985626Shylee 			if (fputs(buffer, pfile_tmp) == EOF) {
10995626Shylee 				rv = KC_ERR_MODIFY_PLUGIN;
11005626Shylee 				goto out;
11015626Shylee 			} else {
11025626Shylee 				continue;
11035626Shylee 			}
11045626Shylee 		}
11055626Shylee 
11065626Shylee 		/*
11075626Shylee 		 * make a copy of the original buffer to buffer2.  Also get
11085626Shylee 		 * rid of the trailing '\n' from buffer2.
11095626Shylee 		 */
11105626Shylee 		(void) strlcpy(buffer2, buffer, MAXPATHLEN);
11115626Shylee 		len = strlen(buffer2);
11125626Shylee 		if (buffer2[len-1] == '\n') {
11135626Shylee 			len--;
11145626Shylee 		}
11155626Shylee 		buffer2[len] = '\0';
11165626Shylee 
11175626Shylee 		if ((name = strtok(buffer2, SEP_COLON)) == NULL) {
11185626Shylee 			rv = KC_ERR_UNINSTALL;
11195626Shylee 			goto out;
11205626Shylee 		}
11215626Shylee 
11225626Shylee 		if (strcmp(name, keystore_name) == 0) {
11235626Shylee 			/* found the entry */
11245626Shylee 			if (option == NULL)
11255626Shylee 				(void) snprintf(buffer, MAXPATHLEN,
11265626Shylee 				    "%s:%s%s\n", keystore_name,
11275626Shylee 				    CONF_MODULEPATH, entry->modulepath);
11285626Shylee 			else
11295626Shylee 				(void) snprintf(buffer, MAXPATHLEN,
11305626Shylee 				    "%s:%s%s;%s%s\n", keystore_name,
11315626Shylee 				    CONF_MODULEPATH, entry->modulepath,
11325626Shylee 				    CONF_OPTION, option);
11335626Shylee 
11345626Shylee 			if (fputs(buffer, pfile_tmp) == EOF) {
11355626Shylee 				err = errno;
11365626Shylee 				(void) fprintf(stderr, gettext(
11375626Shylee 				    "failed to write to %s: %s\n"),
11385626Shylee 				    tmpfile_name, strerror(err));
11395626Shylee 				rv = KC_ERR_MODIFY_PLUGIN;
11405626Shylee 				goto out;
11415626Shylee 			}
11425626Shylee 		} else {
11435626Shylee 
11445626Shylee 			if (fputs(buffer, pfile_tmp) == EOF) {
11455626Shylee 				rv = KC_ERR_UNINSTALL;
11465626Shylee 				goto out;
11475626Shylee 			}
11485626Shylee 		}
11495626Shylee 	}
11505626Shylee 
11515626Shylee 	if (rename(tmpfile_name, _PATH_KMF_CONF) == -1) {
11525626Shylee 		err = errno;
11535626Shylee 		(void) fprintf(stderr, gettext(
11545626Shylee 		    "failed to update the configuration - %s"), strerror(err));
11555626Shylee 		rv = KC_ERR_MODIFY_PLUGIN;
11565626Shylee 		goto out;
11575626Shylee 	}
11585626Shylee 
11595626Shylee 	if (chmod(_PATH_KMF_CONF,
11605626Shylee 	    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
11615626Shylee 		err = errno;
11625626Shylee 		(void) fprintf(stderr, gettext(
11635626Shylee 		    "failed to update the configuration - %s\n"),
11645626Shylee 		    strerror(err));
11655626Shylee 		rv = KC_ERR_MODIFY_PLUGIN;
11665626Shylee 		goto out;
11675626Shylee 	}
11685626Shylee 
11695626Shylee out:
11705626Shylee 	if (entry != NULL)
11715626Shylee 		free_entry(entry);
11725626Shylee 
11735626Shylee 	if (pfile != NULL)
11745626Shylee 		(void) fclose(pfile);
11755626Shylee 
11765626Shylee 	if (rv != KC_OK && pfile_tmp != NULL)
11775626Shylee 		(void) unlink(tmpfile_name);
11785626Shylee 
11795626Shylee 	if (pfile_tmp != NULL)
11805626Shylee 		(void) fclose(pfile_tmp);
11815626Shylee 
11825626Shylee 	return (rv);
11835626Shylee }
11845626Shylee 
11855626Shylee 
11865626Shylee int
kc_modify(int argc,char * argv[])11875626Shylee kc_modify(int argc, char *argv[])
11885626Shylee {
11895626Shylee 	if (argc > 2 &&
11905626Shylee 	    strcmp(argv[0], "modify") == 0 &&
11915626Shylee 	    strcmp(argv[1], "plugin") == 0) {
11925626Shylee 		return (kc_modify_plugin(argc, argv));
11935626Shylee 	} else {
11945626Shylee 		return (kc_modify_policy(argc, argv));
11955626Shylee 	}
11965626Shylee }
1197