xref: /onnv-gate/usr/src/cmd/cmd-crypto/kmfcfg/modify.c (revision 12611:d9f75b73c5fd)
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  *
21*12611SJan.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
61*12611SJan.Pechanec@Sun.COM #define	KC_MAPPER_OPTIONS		0x2000000
623089Swyllys 
635626Shylee static int err; /* To store errno which may be overwritten by gettext() */
645626Shylee 
65*12611SJan.Pechanec@Sun.COM #define	UPDATE_IF_DIFFERENT(old, new) \
66*12611SJan.Pechanec@Sun.COM 	if ((old != NULL && new != NULL && strcmp(old, new) != 0) || \
67*12611SJan.Pechanec@Sun.COM 	    (old == NULL && new != NULL)) { \
68*12611SJan.Pechanec@Sun.COM 		if (old != NULL) \
69*12611SJan.Pechanec@Sun.COM 			free(old); \
70*12611SJan.Pechanec@Sun.COM 		old = new; \
71*12611SJan.Pechanec@Sun.COM 	}
725626Shylee 
733089Swyllys int
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;
82*12611SJan.Pechanec@Sun.COM 	char		*mapper_name = NULL;
83*12611SJan.Pechanec@Sun.COM 	char		*mapper_dir = NULL;
84*12611SJan.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)"
125*12611SJan.Pechanec@Sun.COM 	    "m:(mapper-name)"
126*12611SJan.Pechanec@Sun.COM 	    "M:(mapper-directory)"
127*12611SJan.Pechanec@Sun.COM 	    "Q:(mapper-pathname)"
128*12611SJan.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"));
2033089Swyllys 				} else {
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 					}
2163089Swyllys 				}
2173089Swyllys 				break;
2183089Swyllys 			case 's':
2193089Swyllys 				plc.ta_serial = get_string(optarg_av, &rv);
2203089Swyllys 				if (plc.ta_serial == NULL) {
2213089Swyllys 					(void) fprintf(stderr,
2223089Swyllys 					    gettext("Error serial input.\n"));
2233089Swyllys 				} else {
2243089Swyllys 					uchar_t *bytes = NULL;
2253089Swyllys 					size_t bytelen;
2263089Swyllys 
2275051Swyllys 					ret = kmf_hexstr_to_bytes(
2283089Swyllys 					    (uchar_t *)plc.ta_serial,
2293089Swyllys 					    &bytes, &bytelen);
2303089Swyllys 					if (ret != KMF_OK || bytes == NULL) {
2313089Swyllys 						(void) fprintf(stderr,
2323089Swyllys 						    gettext("serial number "
2333089Swyllys 						    "must be specified as a "
2343089Swyllys 						    "hex number "
2353089Swyllys 						    "(ex: 0x0102030405"
2363089Swyllys 						    "ffeeddee)\n"));
2373089Swyllys 						rv = KC_ERR_USAGE;
2383089Swyllys 						break;
2393089Swyllys 					}
2403089Swyllys 					if (bytes != NULL)
2413089Swyllys 						free(bytes);
2423089Swyllys 					flags |= KC_TA_SERIAL;
2433089Swyllys 				}
2443089Swyllys 				break;
2453089Swyllys 			case 'o':
2463089Swyllys 				plc.VAL_OCSP_RESPONDER_URI =
2475051Swyllys 				    get_string(optarg_av, &rv);
2483089Swyllys 				if (plc.VAL_OCSP_RESPONDER_URI == NULL) {
2493089Swyllys 					(void) fprintf(stderr,
2503089Swyllys 					    gettext("Error responder "
2513089Swyllys 					    "input.\n"));
2523089Swyllys 				} else {
2533089Swyllys 					flags |= KC_OCSP_RESPONDER_URI;
2543089Swyllys 					ocsp_set_attr++;
2553089Swyllys 				}
2563089Swyllys 				break;
2573089Swyllys 			case 'P':
2583089Swyllys 				plc.VAL_OCSP_PROXY = get_string(optarg_av, &rv);
2593089Swyllys 				if (plc.VAL_OCSP_PROXY == NULL) {
2603089Swyllys 					(void) fprintf(stderr,
2613089Swyllys 					    gettext("Error proxy input.\n"));
2623089Swyllys 				} else {
2633089Swyllys 					flags |= KC_OCSP_PROXY;
2643089Swyllys 					ocsp_set_attr++;
2653089Swyllys 				}
2663089Swyllys 				break;
2673089Swyllys 			case 'r':
2683089Swyllys 				plc.VAL_OCSP_URI_FROM_CERT =
2693089Swyllys 				    get_boolean(optarg_av);
2703089Swyllys 				if (plc.VAL_OCSP_URI_FROM_CERT == -1) {
2713089Swyllys 					(void) fprintf(stderr,
2723089Swyllys 					    gettext("Error boolean input.\n"));
2733089Swyllys 					rv = KC_ERR_USAGE;
2743089Swyllys 				} else {
2753089Swyllys 					flags |= KC_OCSP_URI_FROM_CERT;
2763089Swyllys 					ocsp_set_attr++;
2773089Swyllys 				}
2783089Swyllys 				break;
2793089Swyllys 			case 'T':
2803089Swyllys 				plc.VAL_OCSP_RESP_LIFETIME =
2813089Swyllys 				    get_string(optarg_av, &rv);
2823089Swyllys 				if (plc.VAL_OCSP_RESP_LIFETIME == NULL) {
2833089Swyllys 					(void) fprintf(stderr,
2843089Swyllys 					    gettext("Error time input.\n"));
2853089Swyllys 				} else {
2863089Swyllys 					uint32_t adj;
2873089Swyllys 					/* for syntax checking */
2883089Swyllys 					if (str2lifetime(
2893089Swyllys 					    plc.VAL_OCSP_RESP_LIFETIME,
2903089Swyllys 					    &adj) < 0) {
2913089Swyllys 						(void) fprintf(stderr,
2923089Swyllys 						    gettext("Error time "
2933089Swyllys 						    "input.\n"));
2943089Swyllys 						rv = KC_ERR_USAGE;
2953089Swyllys 					} else {
2963089Swyllys 						flags |= KC_OCSP_RESP_LIFETIME;
2973089Swyllys 						ocsp_set_attr++;
2983089Swyllys 					}
2993089Swyllys 				}
3003089Swyllys 				break;
3013089Swyllys 			case 'R':
3023089Swyllys 				plc.VAL_OCSP_IGNORE_RESP_SIGN =
3033089Swyllys 				    get_boolean(optarg_av);
3043089Swyllys 				if (plc.VAL_OCSP_IGNORE_RESP_SIGN == -1) {
3053089Swyllys 					(void) fprintf(stderr,
3063089Swyllys 					    gettext("Error boolean input.\n"));
3073089Swyllys 					rv = KC_ERR_USAGE;
3083089Swyllys 				} else {
3093089Swyllys 					flags |= KC_OCSP_IGNORE_RESP_SIGN;
3103089Swyllys 					ocsp_set_attr++;
3113089Swyllys 				}
3123089Swyllys 				break;
3133089Swyllys 			case 'n':
3143089Swyllys 				plc.VAL_OCSP_RESP_CERT_NAME =
3153089Swyllys 				    get_string(optarg_av, &rv);
3163089Swyllys 				if (plc.VAL_OCSP_RESP_CERT_NAME == NULL) {
3173089Swyllys 					(void) fprintf(stderr,
3183089Swyllys 					    gettext("Error name input.\n"));
3193089Swyllys 				} else {
3203089Swyllys 					KMF_X509_NAME respDN;
3213089Swyllys 					/* for syntax checking */
3225051Swyllys 					if (kmf_dn_parser(
3233089Swyllys 					    plc.VAL_OCSP_RESP_CERT_NAME,
3243089Swyllys 					    &respDN) != KMF_OK) {
3253089Swyllys 						(void) fprintf(stderr,
3263089Swyllys 						    gettext("Error name "
3273089Swyllys 						    "input.\n"));
3283089Swyllys 						rv = KC_ERR_USAGE;
3293089Swyllys 					} else {
3305051Swyllys 						kmf_free_dn(&respDN);
3313089Swyllys 						flags |= KC_OCSP_RESP_CERT_NAME;
3323089Swyllys 						ocsp_set_attr++;
3333089Swyllys 					}
3343089Swyllys 				}
3353089Swyllys 				break;
3363089Swyllys 			case 'A':
3373089Swyllys 				plc.VAL_OCSP_RESP_CERT_SERIAL =
3383089Swyllys 				    get_string(optarg_av, &rv);
3393089Swyllys 				if (plc.VAL_OCSP_RESP_CERT_SERIAL == NULL) {
3403089Swyllys 					(void) fprintf(stderr,
3413089Swyllys 					    gettext("Error serial input.\n"));
3423089Swyllys 				} else {
3433089Swyllys 					uchar_t *bytes = NULL;
3443089Swyllys 					size_t bytelen;
3453089Swyllys 
3465051Swyllys 					ret = kmf_hexstr_to_bytes((uchar_t *)
3473089Swyllys 					    plc.VAL_OCSP_RESP_CERT_SERIAL,
3483089Swyllys 					    &bytes, &bytelen);
3493089Swyllys 					if (ret != KMF_OK || bytes == NULL) {
3503089Swyllys 						(void) fprintf(stderr,
3513089Swyllys 						    gettext("serial number "
3523089Swyllys 						    "must be specified as a "
3533089Swyllys 						    "hex number "
3543089Swyllys 						    "(ex: 0x0102030405"
3553089Swyllys 						    "ffeeddee)\n"));
3563089Swyllys 						rv = KC_ERR_USAGE;
3573089Swyllys 						break;
3583089Swyllys 					}
3593089Swyllys 					if (bytes != NULL)
3603089Swyllys 						free(bytes);
3613089Swyllys 					flags |= KC_OCSP_RESP_CERT_SERIAL;
3623089Swyllys 					ocsp_set_attr++;
3633089Swyllys 				}
3643089Swyllys 				break;
3653089Swyllys 			case 'y':
3663089Swyllys 				ocsp_none_opt = get_boolean(optarg_av);
3673089Swyllys 				if (ocsp_none_opt == -1) {
3683089Swyllys 					(void) fprintf(stderr,
3693089Swyllys 					    gettext("Error boolean input.\n"));
3703089Swyllys 					rv = KC_ERR_USAGE;
3713089Swyllys 				} else {
3723089Swyllys 					flags |= KC_OCSP_NONE;
3733089Swyllys 				}
3743089Swyllys 				break;
3753089Swyllys 			case 'c':
3763089Swyllys 				plc.VAL_CRL_BASEFILENAME =
3773089Swyllys 				    get_string(optarg_av, &rv);
3783089Swyllys 				if (plc.VAL_CRL_BASEFILENAME == NULL) {
3793089Swyllys 					(void) fprintf(stderr, gettext(
3803089Swyllys 					    "Error basefilename input.\n"));
3813089Swyllys 				} else {
3823089Swyllys 					flags |= KC_CRL_BASEFILENAME;
3833089Swyllys 					crl_set_attr++;
3843089Swyllys 				}
3853089Swyllys 				break;
3863089Swyllys 			case 'I':
3873089Swyllys 				plc.VAL_CRL_DIRECTORY =
3883089Swyllys 				    get_string(optarg_av, &rv);
3893089Swyllys 				if (plc.VAL_CRL_DIRECTORY == NULL) {
3903089Swyllys 					(void) fprintf(stderr,
3913089Swyllys 					    gettext("Error boolean input.\n"));
3923089Swyllys 				} else {
3933089Swyllys 					flags |= KC_CRL_DIRECTORY;
3943089Swyllys 					crl_set_attr++;
3953089Swyllys 				}
3963089Swyllys 				break;
3973089Swyllys 			case 'g':
3983089Swyllys 				plc.VAL_CRL_GET_URI = get_boolean(optarg_av);
3993089Swyllys 				if (plc.VAL_CRL_GET_URI == -1) {
4003089Swyllys 					(void) fprintf(stderr,
4013089Swyllys 					    gettext("Error boolean input.\n"));
4023089Swyllys 					rv = KC_ERR_USAGE;
4033089Swyllys 				} else {
4043089Swyllys 					flags |= KC_CRL_GET_URI;
4053089Swyllys 					crl_set_attr++;
4063089Swyllys 				}
4073089Swyllys 				break;
4083089Swyllys 			case 'X':
4093089Swyllys 				plc.VAL_CRL_PROXY = get_string(optarg_av, &rv);
4103089Swyllys 				if (plc.VAL_CRL_PROXY == NULL) {
4113089Swyllys 					(void) fprintf(stderr,
4123089Swyllys 					    gettext("Error proxy input.\n"));
4133089Swyllys 				} else {
4143089Swyllys 					flags |= KC_CRL_PROXY;
4153089Swyllys 					crl_set_attr++;
4163089Swyllys 				}
4173089Swyllys 				break;
4183089Swyllys 			case 'S':
4193089Swyllys 				plc.VAL_CRL_IGNORE_SIGN =
4203089Swyllys 				    get_boolean(optarg_av);
4213089Swyllys 				if (plc.VAL_CRL_IGNORE_SIGN == -1) {
4223089Swyllys 					(void) fprintf(stderr,
4233089Swyllys 					    gettext("Error boolean input.\n"));
4243089Swyllys 					rv = KC_ERR_USAGE;
4253089Swyllys 				} else {
4263089Swyllys 					flags |= KC_CRL_IGNORE_SIGN;
4273089Swyllys 					crl_set_attr++;
4283089Swyllys 				}
4293089Swyllys 				break;
4303089Swyllys 			case 'D':
4313089Swyllys 				plc.VAL_CRL_IGNORE_DATE =
4325051Swyllys 				    get_boolean(optarg_av);
4333089Swyllys 				if (plc.VAL_CRL_IGNORE_DATE == -1) {
4343089Swyllys 					(void) fprintf(stderr,
4353089Swyllys 					    gettext("Error boolean input.\n"));
4363089Swyllys 					rv = KC_ERR_USAGE;
4373089Swyllys 				} else {
4383089Swyllys 					flags |= KC_CRL_IGNORE_DATE;
4393089Swyllys 					crl_set_attr++;
4403089Swyllys 				}
4413089Swyllys 				break;
4423089Swyllys 			case 'z':
4433089Swyllys 				crl_none_opt = get_boolean(optarg_av);
4443089Swyllys 				if (crl_none_opt == -1) {
4453089Swyllys 					(void) fprintf(stderr,
4463089Swyllys 					    gettext("Error boolean input.\n"));
4473089Swyllys 					rv = KC_ERR_USAGE;
4483089Swyllys 				} else {
4493089Swyllys 					flags |= KC_CRL_NONE;
4503089Swyllys 				}
4513089Swyllys 				break;
4523089Swyllys 			case 'u':
4533089Swyllys 				plc.ku_bits = parseKUlist(optarg_av);
4543089Swyllys 				if (plc.ku_bits == 0) {
4553089Swyllys 					(void) fprintf(stderr, gettext(
4563089Swyllys 					    "Error keyusage input.\n"));
4573089Swyllys 					rv = KC_ERR_USAGE;
4583089Swyllys 				} else {
4593089Swyllys 					flags |= KC_KEYUSAGE;
4603089Swyllys 				}
4613089Swyllys 				break;
4623089Swyllys 			case 'Y':
4633089Swyllys 				ku_none_opt = get_boolean(optarg_av);
4643089Swyllys 				if (ku_none_opt == -1) {
4653089Swyllys 					(void) fprintf(stderr,
4663089Swyllys 					    gettext("Error boolean input.\n"));
4673089Swyllys 					rv = KC_ERR_USAGE;
4683089Swyllys 				} else {
4693089Swyllys 					flags |= KC_KEYUSAGE_NONE;
4703089Swyllys 				}
4713089Swyllys 				break;
4723089Swyllys 			case 'E':
4733089Swyllys 				if (parseEKUNames(optarg_av, &plc) != 0) {
4743089Swyllys 					(void) fprintf(stderr,
4753089Swyllys 					    gettext("Error EKU input.\n"));
4763089Swyllys 					rv = KC_ERR_USAGE;
4773089Swyllys 				} else {
4783089Swyllys 					flags |= KC_EKUS;
4793089Swyllys 				}
4803089Swyllys 				break;
4813089Swyllys 			case 'O':
4823089Swyllys 				if (parseEKUOIDs(optarg_av, &plc) != 0) {
4833089Swyllys 					(void) fprintf(stderr,
4843089Swyllys 					    gettext("Error EKU OID input.\n"));
4853089Swyllys 					rv = KC_ERR_USAGE;
4863089Swyllys 				} else {
4873089Swyllys 					flags |= KC_EKUS;
4883089Swyllys 				}
4893089Swyllys 				break;
4903089Swyllys 			case 'Z':
4913089Swyllys 				eku_none_opt = get_boolean(optarg_av);
4923089Swyllys 				if (eku_none_opt == -1) {
4933089Swyllys 					(void) fprintf(stderr,
4943089Swyllys 					    gettext("Error boolean input.\n"));
4953089Swyllys 					rv = KC_ERR_USAGE;
4963089Swyllys 				} else {
4973089Swyllys 					flags |= KC_EKUS_NONE;
4983089Swyllys 				}
4993089Swyllys 				break;
500*12611SJan.Pechanec@Sun.COM 			case 'm':
501*12611SJan.Pechanec@Sun.COM 				mapper_name = get_string(optarg_av, &rv);
502*12611SJan.Pechanec@Sun.COM 				if (mapper_name == NULL) {
503*12611SJan.Pechanec@Sun.COM 					(void) fprintf(stderr,
504*12611SJan.Pechanec@Sun.COM 					    gettext("Error mapper-name "
505*12611SJan.Pechanec@Sun.COM 					    "input.\n"));
506*12611SJan.Pechanec@Sun.COM 				}
507*12611SJan.Pechanec@Sun.COM 				break;
508*12611SJan.Pechanec@Sun.COM 			case 'M':
509*12611SJan.Pechanec@Sun.COM 				mapper_dir = get_string(optarg_av, &rv);
510*12611SJan.Pechanec@Sun.COM 				if (mapper_dir == NULL) {
511*12611SJan.Pechanec@Sun.COM 					(void) fprintf(stderr,
512*12611SJan.Pechanec@Sun.COM 					    gettext("Error mapper-directory "
513*12611SJan.Pechanec@Sun.COM 					    "input.\n"));
514*12611SJan.Pechanec@Sun.COM 				}
515*12611SJan.Pechanec@Sun.COM 				break;
516*12611SJan.Pechanec@Sun.COM 			case 'Q':
517*12611SJan.Pechanec@Sun.COM 				mapper_pathname = get_string(optarg_av, &rv);
518*12611SJan.Pechanec@Sun.COM 				if (mapper_pathname == NULL) {
519*12611SJan.Pechanec@Sun.COM 					(void) fprintf(stderr,
520*12611SJan.Pechanec@Sun.COM 					    gettext("Error mapper-pathname "
521*12611SJan.Pechanec@Sun.COM 					    "input.\n"));
522*12611SJan.Pechanec@Sun.COM 				}
523*12611SJan.Pechanec@Sun.COM 				break;
524*12611SJan.Pechanec@Sun.COM 			case 'q':
525*12611SJan.Pechanec@Sun.COM 				plc.mapper.options = get_string(optarg_av, &rv);
526*12611SJan.Pechanec@Sun.COM 				rv = 0; /* its ok for this to be NULL */
527*12611SJan.Pechanec@Sun.COM 				flags |= KC_MAPPER_OPTIONS;
528*12611SJan.Pechanec@Sun.COM 				break;
5293089Swyllys 			default:
5303089Swyllys 				(void) fprintf(stderr,
5313089Swyllys 				    gettext("Error input option.\n"));
5323089Swyllys 				rv = KC_ERR_USAGE;
5333089Swyllys 				break;
5343089Swyllys 		}
5353089Swyllys 		if (rv != KC_OK)
5363089Swyllys 			goto out;
5373089Swyllys 	}
5383089Swyllys 
5393089Swyllys 	/* No additional args allowed. */
5403089Swyllys 	argc -= optind_av;
5413089Swyllys 	if (argc) {
5423089Swyllys 		(void) fprintf(stderr,
5433089Swyllys 		    gettext("Error input option\n"));
5443089Swyllys 		rv = KC_ERR_USAGE;
5453089Swyllys 		goto out;
5463089Swyllys 	}
5473089Swyllys 
5483089Swyllys 	if (filename == NULL) {
5493089Swyllys 		filename = strdup(KMF_DEFAULT_POLICY_FILE);
5503089Swyllys 		if (filename == NULL) {
5513089Swyllys 			rv = KC_ERR_MEMORY;
5523089Swyllys 			goto out;
5533089Swyllys 		}
5543089Swyllys 	}
5553089Swyllys 
5563089Swyllys 	/*
5573089Swyllys 	 * Must have a policy name. The policy name can not be default
5583089Swyllys 	 * if using the default policy file.
5593089Swyllys 	 */
5603089Swyllys 	if (plc.name == NULL) {
5613089Swyllys 		(void) fprintf(stderr,
5623089Swyllys 		    gettext("You must specify a policy name.\n"));
5633089Swyllys 		rv = KC_ERR_USAGE;
5643089Swyllys 		goto out;
5653089Swyllys 	} else if (strcmp(filename, KMF_DEFAULT_POLICY_FILE) == 0 &&
5663089Swyllys 	    strcmp(plc.name, KMF_DEFAULT_POLICY_NAME) == 0) {
5673089Swyllys 		(void) fprintf(stderr,
5683089Swyllys 		    gettext("Can not modify the default policy in the default "
5693089Swyllys 		    "policy file.\n"));
5703089Swyllys 		rv = KC_ERR_USAGE;
5713089Swyllys 		goto out;
5723089Swyllys 	}
5733089Swyllys 
5743089Swyllys 	/* Check the access permission of the policy DB */
5753089Swyllys 	if (access(filename, W_OK) < 0) {
5763089Swyllys 		int err = errno;
5773089Swyllys 		(void) fprintf(stderr,
5783089Swyllys 		    gettext("Cannot access \"%s\" for modify - %s\n"),
5793089Swyllys 		    filename, strerror(err));
5803089Swyllys 		rv = KC_ERR_ACCESS;
5813089Swyllys 		goto out;
5823089Swyllys 	}
5833089Swyllys 
5843089Swyllys 	/* Try to load the named policy from the DB */
5855051Swyllys 	ret = kmf_get_policy(filename, plc.name, &oplc);
5863089Swyllys 	if (ret != KMF_OK) {
5873089Swyllys 		(void) fprintf(stderr,
5883089Swyllys 		    gettext("Error loading policy \"%s\" from %s\n"), filename,
5893089Swyllys 		    plc.name);
5903089Swyllys 		return (KC_ERR_FIND_POLICY);
5913089Swyllys 	}
5923089Swyllys 
5933089Swyllys 	/* Update the general policy attributes. */
5943089Swyllys 	if (flags & KC_IGNORE_DATE)
5953089Swyllys 		oplc.ignore_date = plc.ignore_date;
5963089Swyllys 
5973089Swyllys 	if (flags & KC_IGNORE_UNKNOWN_EKUS)
5983089Swyllys 		oplc.ignore_unknown_ekus = plc.ignore_unknown_ekus;
5993089Swyllys 
6003089Swyllys 	if (flags & KC_IGNORE_TRUST_ANCHOR)
6013089Swyllys 		oplc.ignore_trust_anchor = plc.ignore_trust_anchor;
6023089Swyllys 
6033089Swyllys 	if (flags & KC_VALIDITY_ADJUSTTIME) {
6043089Swyllys 		if (oplc.validity_adjusttime)
6053089Swyllys 			free(oplc.validity_adjusttime);
6063089Swyllys 		oplc.validity_adjusttime =
6075051Swyllys 		    plc.validity_adjusttime;
6083089Swyllys 	}
6093089Swyllys 
6103089Swyllys 	if (flags & KC_TA_NAME) {
6113089Swyllys 		if (oplc.ta_name)
6123089Swyllys 			free(oplc.ta_name);
6133089Swyllys 		oplc.ta_name = plc.ta_name;
6143089Swyllys 	}
6153089Swyllys 	if (flags & KC_TA_SERIAL) {
6163089Swyllys 		if (oplc.ta_serial)
6173089Swyllys 			free(oplc.ta_serial);
6183089Swyllys 		oplc.ta_serial = plc.ta_serial;
6193089Swyllys 	}
6203089Swyllys 
621*12611SJan.Pechanec@Sun.COM 	/*
622*12611SJan.Pechanec@Sun.COM 	 * There are some combinations of attributes that are not valid.
623*12611SJan.Pechanec@Sun.COM 	 *
624*12611SJan.Pechanec@Sun.COM 	 * First, setting mapper-name (with optional mapper-directory) and
625*12611SJan.Pechanec@Sun.COM 	 * mapper-pathname is mutually exclusive.
626*12611SJan.Pechanec@Sun.COM 	 */
627*12611SJan.Pechanec@Sun.COM 	if ((mapper_name != NULL && mapper_pathname != NULL) ||
628*12611SJan.Pechanec@Sun.COM 	    (mapper_name != NULL && oplc.mapper.pathname != NULL) ||
629*12611SJan.Pechanec@Sun.COM 	    (mapper_pathname != NULL && oplc.mapper.mapname != NULL) ||
630*12611SJan.Pechanec@Sun.COM 	    /* Mapper directory can be set only if mapper name is set. */
631*12611SJan.Pechanec@Sun.COM 	    (mapper_dir != NULL && mapper_pathname != NULL) ||
632*12611SJan.Pechanec@Sun.COM 	    (mapper_dir != NULL && mapper_name == NULL &&
633*12611SJan.Pechanec@Sun.COM 	    oplc.mapper.mapname == NULL) ||
634*12611SJan.Pechanec@Sun.COM 	    (mapper_dir != NULL && oplc.mapper.pathname != NULL) ||
635*12611SJan.Pechanec@Sun.COM 	    /* Options can be set only if mapper name or pathname is set. */
636*12611SJan.Pechanec@Sun.COM 	    ((plc.mapper.options != NULL || oplc.mapper.options != NULL) &&
637*12611SJan.Pechanec@Sun.COM 	    (mapper_name == NULL && oplc.mapper.mapname == NULL &&
638*12611SJan.Pechanec@Sun.COM 	    mapper_pathname == NULL && oplc.mapper.pathname == NULL))) {
639*12611SJan.Pechanec@Sun.COM 		(void) fprintf(stderr,
640*12611SJan.Pechanec@Sun.COM 		    gettext("Error in mapper input options\n"));
641*12611SJan.Pechanec@Sun.COM 		if (mapper_name != NULL)
642*12611SJan.Pechanec@Sun.COM 			free(mapper_name);
643*12611SJan.Pechanec@Sun.COM 		if (mapper_pathname != NULL)
644*12611SJan.Pechanec@Sun.COM 			free(mapper_pathname);
645*12611SJan.Pechanec@Sun.COM 		if (mapper_dir != NULL)
646*12611SJan.Pechanec@Sun.COM 			free(mapper_dir);
647*12611SJan.Pechanec@Sun.COM 		if (flags & KC_MAPPER_OPTIONS && plc.mapper.options != NULL)
648*12611SJan.Pechanec@Sun.COM 			free(plc.mapper.options);
649*12611SJan.Pechanec@Sun.COM 		rv = KC_ERR_USAGE;
650*12611SJan.Pechanec@Sun.COM 		goto out;
651*12611SJan.Pechanec@Sun.COM 	} else {
652*12611SJan.Pechanec@Sun.COM 		if (mapper_name != NULL)
653*12611SJan.Pechanec@Sun.COM 			plc.mapper.mapname = mapper_name;
654*12611SJan.Pechanec@Sun.COM 		if (mapper_pathname != NULL)
655*12611SJan.Pechanec@Sun.COM 			plc.mapper.pathname = mapper_pathname;
656*12611SJan.Pechanec@Sun.COM 		if (mapper_dir != NULL)
657*12611SJan.Pechanec@Sun.COM 			plc.mapper.dir = mapper_dir;
658*12611SJan.Pechanec@Sun.COM 	}
659*12611SJan.Pechanec@Sun.COM 
660*12611SJan.Pechanec@Sun.COM 	UPDATE_IF_DIFFERENT(oplc.mapper.mapname, plc.mapper.mapname);
661*12611SJan.Pechanec@Sun.COM 	UPDATE_IF_DIFFERENT(oplc.mapper.pathname, plc.mapper.pathname);
662*12611SJan.Pechanec@Sun.COM 	UPDATE_IF_DIFFERENT(oplc.mapper.dir, plc.mapper.dir);
663*12611SJan.Pechanec@Sun.COM 
664*12611SJan.Pechanec@Sun.COM 	if (flags & KC_MAPPER_OPTIONS) {
665*12611SJan.Pechanec@Sun.COM 		if (oplc.mapper.options != NULL)
666*12611SJan.Pechanec@Sun.COM 			free(oplc.mapper.options);
667*12611SJan.Pechanec@Sun.COM 		oplc.mapper.options = plc.mapper.options;
668*12611SJan.Pechanec@Sun.COM 	}
669*12611SJan.Pechanec@Sun.COM 
6703089Swyllys 	/* Update the OCSP policy */
6713089Swyllys 	if (ocsp_none_opt == B_TRUE) {
6723089Swyllys 		if (ocsp_set_attr > 0) {
6733089Swyllys 			(void) fprintf(stderr,
6743089Swyllys 			    gettext("Can not set ocsp-none=true and other "
6753089Swyllys 			    "OCSP attributes at the same time.\n"));
6763089Swyllys 			rv = KC_ERR_USAGE;
6773089Swyllys 			goto out;
6783089Swyllys 		}
6793089Swyllys 
6803089Swyllys 		/*
6813089Swyllys 		 * If the original policy does not have OCSP checking,
6823089Swyllys 		 * then we do not need to do anything.  If the original
6833089Swyllys 		 * policy has the OCSP checking, then we need to release the
6843089Swyllys 		 * space of OCSP attributes and turn the OCSP checking off.
6853089Swyllys 		 */
6863089Swyllys 		if (oplc.revocation & KMF_REVOCATION_METHOD_OCSP) {
6873089Swyllys 			if (oplc.VAL_OCSP_BASIC.responderURI) {
6883089Swyllys 				free(oplc.VAL_OCSP_BASIC.responderURI);
6893089Swyllys 				oplc.VAL_OCSP_BASIC.responderURI = NULL;
6903089Swyllys 			}
6913089Swyllys 
6923089Swyllys 			if (oplc.VAL_OCSP_BASIC.proxy) {
6933089Swyllys 				free(oplc.VAL_OCSP_BASIC.proxy);
6943089Swyllys 				oplc.VAL_OCSP_BASIC.proxy = NULL;
6953089Swyllys 			}
6963089Swyllys 
6973089Swyllys 			if (oplc.VAL_OCSP_BASIC.response_lifetime) {
6983089Swyllys 				free(oplc.VAL_OCSP_BASIC.response_lifetime);
6993089Swyllys 				oplc.VAL_OCSP_BASIC.response_lifetime = NULL;
7003089Swyllys 			}
7013089Swyllys 
7023089Swyllys 			if (flags & KC_OCSP_RESP_CERT_NAME) {
7033089Swyllys 				free(oplc.VAL_OCSP_RESP_CERT.name);
7043089Swyllys 				oplc.VAL_OCSP_RESP_CERT.name = NULL;
7053089Swyllys 			}
7063089Swyllys 
7073089Swyllys 			if (flags & KC_OCSP_RESP_CERT_SERIAL) {
7083089Swyllys 				free(oplc.VAL_OCSP_RESP_CERT.serial);
7093089Swyllys 				oplc.VAL_OCSP_RESP_CERT.serial = NULL;
7103089Swyllys 			}
7113089Swyllys 
7123089Swyllys 			/* Turn off the OCSP checking */
7133089Swyllys 			oplc.revocation &= ~KMF_REVOCATION_METHOD_OCSP;
7143089Swyllys 		}
7153089Swyllys 
7163089Swyllys 	} else {
7173089Swyllys 		/*
7183089Swyllys 		 * If the "ocsp-none" option is not set or is set to false,
7193089Swyllys 		 * then we only need to do the modification if there is at
7203089Swyllys 		 * least one OCSP attribute is specified.
7213089Swyllys 		 */
7223089Swyllys 		if (ocsp_set_attr > 0) {
7233089Swyllys 			if (flags & KC_OCSP_RESPONDER_URI) {
7243089Swyllys 				if (oplc.VAL_OCSP_RESPONDER_URI)
7253089Swyllys 					free(oplc.VAL_OCSP_RESPONDER_URI);
7263089Swyllys 				oplc.VAL_OCSP_RESPONDER_URI =
7275051Swyllys 				    plc.VAL_OCSP_RESPONDER_URI;
7283089Swyllys 			}
7293089Swyllys 
7303089Swyllys 			if (flags & KC_OCSP_PROXY) {
7313089Swyllys 				if (oplc.VAL_OCSP_PROXY)
7323089Swyllys 					free(oplc.VAL_OCSP_PROXY);
7333089Swyllys 				oplc.VAL_OCSP_PROXY = plc.VAL_OCSP_PROXY;
7343089Swyllys 			}
7353089Swyllys 
7363089Swyllys 			if (flags & KC_OCSP_URI_FROM_CERT)
7373089Swyllys 				oplc.VAL_OCSP_URI_FROM_CERT =
7385051Swyllys 				    plc.VAL_OCSP_URI_FROM_CERT;
7393089Swyllys 
7403089Swyllys 			if (flags & KC_OCSP_RESP_LIFETIME) {
7413089Swyllys 				if (oplc.VAL_OCSP_RESP_LIFETIME)
7423089Swyllys 					free(oplc.VAL_OCSP_RESP_LIFETIME);
7433089Swyllys 				oplc.VAL_OCSP_RESP_LIFETIME =
7445051Swyllys 				    plc.VAL_OCSP_RESP_LIFETIME;
7453089Swyllys 			}
7463089Swyllys 
7473089Swyllys 			if (flags & KC_OCSP_IGNORE_RESP_SIGN)
7483089Swyllys 				oplc.VAL_OCSP_IGNORE_RESP_SIGN =
7495051Swyllys 				    plc.VAL_OCSP_IGNORE_RESP_SIGN;
7503089Swyllys 
7513089Swyllys 			if (flags & KC_OCSP_RESP_CERT_NAME) {
7523089Swyllys 				if (oplc.VAL_OCSP_RESP_CERT_NAME)
7533089Swyllys 					free(oplc.VAL_OCSP_RESP_CERT_NAME);
7543089Swyllys 				oplc.VAL_OCSP_RESP_CERT_NAME =
7555051Swyllys 				    plc.VAL_OCSP_RESP_CERT_NAME;
7563089Swyllys 			}
7573089Swyllys 
7583089Swyllys 			if (flags & KC_OCSP_RESP_CERT_SERIAL) {
7593089Swyllys 				if (oplc.VAL_OCSP_RESP_CERT_SERIAL)
7603089Swyllys 					free(oplc.VAL_OCSP_RESP_CERT_SERIAL);
7613089Swyllys 				oplc.VAL_OCSP_RESP_CERT_SERIAL =
7625051Swyllys 				    plc.VAL_OCSP_RESP_CERT_SERIAL;
7633089Swyllys 			}
7643089Swyllys 
7653089Swyllys 			if (oplc.VAL_OCSP_RESP_CERT_NAME != NULL &&
7663089Swyllys 			    oplc.VAL_OCSP_RESP_CERT_SERIAL != NULL)
7673089Swyllys 				oplc.VAL_OCSP.has_resp_cert = B_TRUE;
7683089Swyllys 			else
7693089Swyllys 				oplc.VAL_OCSP.has_resp_cert = B_FALSE;
7703089Swyllys 
7713089Swyllys 			/* Turn on the OCSP checking */
7723089Swyllys 			oplc.revocation |= KMF_REVOCATION_METHOD_OCSP;
7733089Swyllys 		}
7743089Swyllys 	}
7753089Swyllys 
7763089Swyllys 	/* Update the CRL policy */
7773089Swyllys 	if (crl_none_opt == B_TRUE) {
7783089Swyllys 		if (crl_set_attr > 0) {
7793089Swyllys 			(void) fprintf(stderr,
7803089Swyllys 			    gettext("Can not set crl-none=true and other CRL "
7813089Swyllys 			    "attributes at the same time.\n"));
7823089Swyllys 			rv = KC_ERR_USAGE;
7833089Swyllys 			goto out;
7843089Swyllys 		}
7853089Swyllys 
7863089Swyllys 		/*
7873089Swyllys 		 * If the original policy does not have CRL checking,
7883089Swyllys 		 * then we do not need to do anything.  If the original
7893089Swyllys 		 * policy has the CRL checking, then we need to release the
7903089Swyllys 		 * space of CRL attributes and turn the CRL checking off.
7913089Swyllys 		 */
7923089Swyllys 		if (oplc.revocation & KMF_REVOCATION_METHOD_CRL) {
7933089Swyllys 			if (oplc.VAL_CRL_BASEFILENAME) {
7943089Swyllys 				free(oplc.VAL_CRL_BASEFILENAME);
7953089Swyllys 				oplc.VAL_CRL_BASEFILENAME = NULL;
7963089Swyllys 			}
7973089Swyllys 
7983089Swyllys 			if (oplc.VAL_CRL_DIRECTORY) {
7993089Swyllys 				free(oplc.VAL_CRL_DIRECTORY);
8003089Swyllys 				oplc.VAL_CRL_DIRECTORY = NULL;
8013089Swyllys 			}
8023089Swyllys 
8033089Swyllys 			if (oplc.VAL_CRL_PROXY) {
8043089Swyllys 				free(oplc.VAL_CRL_PROXY);
8053089Swyllys 				oplc.VAL_CRL_PROXY = NULL;
8063089Swyllys 			}
8073089Swyllys 
8083089Swyllys 			/* Turn off the CRL checking */
8093089Swyllys 			oplc.revocation &= ~KMF_REVOCATION_METHOD_CRL;
8103089Swyllys 		}
8113089Swyllys 	} else {
8123089Swyllys 		/*
8133089Swyllys 		 * If the "ocsp-none" option is not set or is set to false,
8143089Swyllys 		 * then we only need to do the modification if there is at
8153089Swyllys 		 * least one CRL attribute is specified.
8163089Swyllys 		 */
8173089Swyllys 		if (crl_set_attr > 0) {
8183089Swyllys 			if (flags & KC_CRL_BASEFILENAME) {
8193089Swyllys 				if (oplc.VAL_CRL_BASEFILENAME)
8203089Swyllys 					free(oplc.VAL_CRL_BASEFILENAME);
8213089Swyllys 				oplc.VAL_CRL_BASEFILENAME =
8223089Swyllys 				    plc.VAL_CRL_BASEFILENAME;
8233089Swyllys 			}
8243089Swyllys 
8253089Swyllys 			if (flags & KC_CRL_DIRECTORY) {
8263089Swyllys 				if (oplc.VAL_CRL_DIRECTORY)
8273089Swyllys 					free(oplc.VAL_CRL_DIRECTORY);
8283089Swyllys 				oplc.VAL_CRL_DIRECTORY = plc.VAL_CRL_DIRECTORY;
8293089Swyllys 			}
8303089Swyllys 
8313089Swyllys 			if (flags & KC_CRL_GET_URI) {
8323089Swyllys 				oplc.VAL_CRL_GET_URI = plc.VAL_CRL_GET_URI;
8333089Swyllys 			}
8343089Swyllys 
8353089Swyllys 			if (flags & KC_CRL_PROXY) {
8363089Swyllys 				if (oplc.VAL_CRL_PROXY)
8373089Swyllys 					free(oplc.VAL_CRL_PROXY);
8383089Swyllys 				oplc.VAL_CRL_PROXY = plc.VAL_CRL_PROXY;
8393089Swyllys 			}
8403089Swyllys 
8413089Swyllys 			if (flags & KC_CRL_IGNORE_SIGN) {
8423089Swyllys 				oplc.VAL_CRL_IGNORE_SIGN =
8433089Swyllys 				    plc.VAL_CRL_IGNORE_SIGN;
8443089Swyllys 			}
8453089Swyllys 
8463089Swyllys 			if (flags & KC_CRL_IGNORE_DATE) {
8473089Swyllys 				oplc.VAL_CRL_IGNORE_DATE =
8483089Swyllys 				    plc.VAL_CRL_IGNORE_DATE;
8493089Swyllys 			}
8503089Swyllys 
8513089Swyllys 			/* Turn on the CRL checking */
8523089Swyllys 			oplc.revocation |= KMF_REVOCATION_METHOD_CRL;
8533089Swyllys 		}
8543089Swyllys 	}
8553089Swyllys 
8563089Swyllys 	/* Update the Key Usage */
8573089Swyllys 	if (ku_none_opt == B_TRUE) {
8583089Swyllys 		if (flags & KC_KEYUSAGE) {
8593089Swyllys 			(void) fprintf(stderr,
8603089Swyllys 			    gettext("Can not set keyusage-none=true and "
8613089Swyllys 			    "modify the keyusage value at the same time.\n"));
8623089Swyllys 			rv = KC_ERR_USAGE;
8633089Swyllys 			goto out;
8643089Swyllys 		}
8653089Swyllys 
8663089Swyllys 		oplc.ku_bits = 0;
8673089Swyllys 	} else {
8683089Swyllys 		/*
8693089Swyllys 		 * If the "keyusage-none" option is not set or is set to
8703089Swyllys 		 * false, then we only need to do the modification if
8713089Swyllys 		 * the keyusage value is specified.
8723089Swyllys 		 */
8733089Swyllys 		if (flags & KC_KEYUSAGE)
8743089Swyllys 			oplc.ku_bits = plc.ku_bits;
8753089Swyllys 	}
8763089Swyllys 
8773089Swyllys 
8783089Swyllys 	/* Update the Extended Key Usage */
8793089Swyllys 	if (eku_none_opt == B_TRUE) {
8803089Swyllys 		if (flags & KC_EKUS) {
8813089Swyllys 			(void) fprintf(stderr,
8823089Swyllys 			    gettext("Can not set eku-none=true and modify "
8833089Swyllys 			    "EKU values at the same time.\n"));
8843089Swyllys 			rv = KC_ERR_USAGE;
8853089Swyllys 			goto out;
8863089Swyllys 		}
8873089Swyllys 
8883089Swyllys 		/* Release current EKU list (if any) */
8893089Swyllys 		if (oplc.eku_set.eku_count > 0) {
8905051Swyllys 			kmf_free_eku_policy(&oplc.eku_set);
8913089Swyllys 			oplc.eku_set.eku_count = 0;
8923089Swyllys 			oplc.eku_set.ekulist = NULL;
8933089Swyllys 		}
8943089Swyllys 	} else {
8953089Swyllys 		/*
8963089Swyllys 		 * If the "eku-none" option is not set or is set to false,
8973089Swyllys 		 * then we only need to do the modification if either
8983089Swyllys 		 * "ekuname" or "ekuoids" is specified.
8993089Swyllys 		 */
9003089Swyllys 		if (flags & KC_EKUS) {
9013089Swyllys 			/* Release current EKU list (if any) */
9025051Swyllys 			kmf_free_eku_policy(&oplc.eku_set);
9033089Swyllys 			oplc.eku_set = plc.eku_set;
9043089Swyllys 		}
9053089Swyllys 	}
9063089Swyllys 
9073089Swyllys 	/* Do a sanity check on the modified policy */
9085051Swyllys 	ret = kmf_verify_policy(&oplc);
9093089Swyllys 	if (ret != KMF_OK) {
9103089Swyllys 		print_sanity_error(ret);
9113089Swyllys 		rv = KC_ERR_VERIFY_POLICY;
9123089Swyllys 		goto out;
9133089Swyllys 	}
9143089Swyllys 
9153089Swyllys 	/* The modify operation is a delete followed by an add */
9165051Swyllys 	ret = kmf_delete_policy_from_db(oplc.name, filename);
9173089Swyllys 	if (ret != KMF_OK) {
9183089Swyllys 		rv = KC_ERR_DELETE_POLICY;
9193089Swyllys 		goto out;
9203089Swyllys 	}
9213089Swyllys 
9223089Swyllys 	/*
9233089Swyllys 	 * Now add the modified policy back to the DB.
9243089Swyllys 	 */
9255051Swyllys 	ret = kmf_add_policy_to_db(&oplc, filename, B_FALSE);
9263089Swyllys 	if (ret != KMF_OK) {
9273089Swyllys 		(void) fprintf(stderr,
9283089Swyllys 		    gettext("Error adding policy to database: 0x%04x\n"), ret);
9293089Swyllys 		rv = KC_ERR_ADD_POLICY;
9303089Swyllys 		goto out;
9313089Swyllys 	}
9323089Swyllys 
9333089Swyllys out:
9343089Swyllys 	if (filename != NULL)
9353089Swyllys 		free(filename);
9363089Swyllys 
9375051Swyllys 	kmf_free_policy_record(&oplc);
9383089Swyllys 
9393089Swyllys 	return (rv);
9403089Swyllys }
9415626Shylee 
9425626Shylee static int
9435626Shylee kc_modify_plugin(int argc, char *argv[])
9445626Shylee {
9455626Shylee 	int 		rv = KC_OK;
9465626Shylee 	int		opt;
9475626Shylee 	extern int	optind_av;
9485626Shylee 	extern char	*optarg_av;
9495626Shylee 	char 		*keystore_name = NULL;
9505626Shylee 	char		*option = NULL;
9515626Shylee 	boolean_t	modify_plugin = B_FALSE;
9525626Shylee 	boolean_t 	has_option_arg = B_FALSE;
9535626Shylee 	conf_entry_t	*entry = NULL;
9545626Shylee 	FILE		*pfile = NULL;
9555626Shylee 	FILE		*pfile_tmp = NULL;
9565626Shylee 	char		tmpfile_name[MAXPATHLEN];
9575626Shylee 	char 		buffer[MAXPATHLEN];
9585626Shylee 	char 		buffer2[MAXPATHLEN];
9595626Shylee 
9605626Shylee 	while ((opt = getopt_av(argc, argv, "p(plugin)k:(keystore)o:(option)"))
9615626Shylee 	    != EOF) {
9625626Shylee 		switch (opt) {
9635626Shylee 		case 'p':
9645626Shylee 			if (modify_plugin) {
9655626Shylee 				(void) fprintf(stderr,
9665626Shylee 				    gettext("duplicate plugin input.\n"));
9675626Shylee 				rv = KC_ERR_USAGE;
9685626Shylee 			} else {
9695626Shylee 				modify_plugin = B_TRUE;
9705626Shylee 			}
9715626Shylee 			break;
9725626Shylee 		case 'k':
9735626Shylee 			if (keystore_name != NULL)
9745626Shylee 				rv = KC_ERR_USAGE;
9755626Shylee 			else {
9765626Shylee 				keystore_name = get_string(optarg_av, &rv);
9775626Shylee 				if (keystore_name == NULL) {
9785626Shylee 					(void) fprintf(stderr, gettext(
9795626Shylee 					    "Error keystore input.\n"));
9805626Shylee 					rv = KC_ERR_USAGE;
9815626Shylee 				}
9825626Shylee 			}
9835626Shylee 			break;
9845626Shylee 		case 'o':
9855626Shylee 			if (has_option_arg) {
9865626Shylee 				(void) fprintf(stderr,
9875626Shylee 				    gettext("duplicate option input.\n"));
9885626Shylee 				rv = KC_ERR_USAGE;
9895626Shylee 			} else {
9905626Shylee 				has_option_arg = B_TRUE;
9915626Shylee 				option = get_string(optarg_av, NULL);
9925626Shylee 			}
9935626Shylee 			break;
9945626Shylee 		default:
9955626Shylee 			(void) fprintf(stderr,
9965626Shylee 			    gettext("Error input option.\n"));
9975626Shylee 			rv = KC_ERR_USAGE;
9985626Shylee 			break;
9995626Shylee 		}
10005626Shylee 
10015626Shylee 		if (rv != KC_OK)
10025626Shylee 			goto out;
10035626Shylee 	}
10045626Shylee 
10055626Shylee 	/* No additional args allowed. */
10065626Shylee 	argc -= optind_av;
10075626Shylee 	if (argc) {
10085626Shylee 		(void) fprintf(stderr,
10095626Shylee 		    gettext("Error input option\n"));
10105626Shylee 		rv = KC_ERR_USAGE;
10115626Shylee 		goto out;
10125626Shylee 	}
10135626Shylee 
10145626Shylee 	if (keystore_name == NULL || has_option_arg == B_FALSE) {
10155626Shylee 		(void) fprintf(stderr,
10165626Shylee 		    gettext("Error input option\n"));
10175626Shylee 		rv = KC_ERR_USAGE;
10185626Shylee 		goto out;
10195626Shylee 	}
10205626Shylee 
10215626Shylee 	if (strcasecmp(keystore_name, "nss") == 0 ||
10225626Shylee 	    strcasecmp(keystore_name, "pkcs11") == 0 ||
10235626Shylee 	    strcasecmp(keystore_name, "file") == 0) {
10245626Shylee 		(void) fprintf(stderr,
10255626Shylee 		    gettext("Can not modify the built-in keystore %s\n"),
10265626Shylee 		    keystore_name);
10275626Shylee 		rv = KC_ERR_USAGE;
10285626Shylee 		goto out;
10295626Shylee 	}
10305626Shylee 
10315626Shylee 	entry = get_keystore_entry(keystore_name);
10325626Shylee 	if (entry == NULL) {
10335626Shylee 		(void) fprintf(stderr, gettext("%s does not exist.\n"),
10345626Shylee 		    keystore_name);
10355626Shylee 		rv = KC_ERR_USAGE;
10365626Shylee 		goto out;
10375626Shylee 	}
10385626Shylee 
10395626Shylee 	if ((entry->option == NULL && option == NULL) ||
10405626Shylee 	    (entry->option != NULL && option != NULL &&
10415626Shylee 	    strcmp(entry->option, option) == 0)) {
10425626Shylee 		(void) fprintf(stderr, gettext("No change - "
10435626Shylee 		    "the new option is same as the old option.\n"));
10445626Shylee 		rv = KC_OK;
10455626Shylee 		goto out;
10465626Shylee 	}
10475626Shylee 
10485626Shylee 	if ((pfile = fopen(_PATH_KMF_CONF, "r+")) == NULL) {
10495626Shylee 		err = errno;
10505626Shylee 		(void) fprintf(stderr,
10515626Shylee 		    gettext("failed to update the configuration - %s\n"),
10525626Shylee 		    strerror(err));
10535626Shylee 		rv = KC_ERR_ACCESS;
10545626Shylee 		goto out;
10555626Shylee 	}
10565626Shylee 
10575626Shylee 	if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
10585626Shylee 		err = errno;
10595626Shylee 		(void) fprintf(stderr,
10605626Shylee 		    gettext("failed to lock the configuration - %s\n"),
10615626Shylee 		    strerror(err));
10625626Shylee 		rv = KC_ERR_MODIFY_PLUGIN;
10635626Shylee 		goto out;
10645626Shylee 	}
10655626Shylee 
10665626Shylee 	/*
10675626Shylee 	 * Create a temporary file in the /etc/crypto directory.
10685626Shylee 	 */
10695626Shylee 	(void) strlcpy(tmpfile_name, CONF_TEMPFILE, sizeof (tmpfile_name));
10705626Shylee 	if (mkstemp(tmpfile_name) == -1) {
10715626Shylee 		err = errno;
10725626Shylee 		(void) fprintf(stderr,
10735626Shylee 		    gettext("failed to create a temporary file - %s\n"),
10745626Shylee 		    strerror(err));
10755626Shylee 		rv = KC_ERR_MODIFY_PLUGIN;
10765626Shylee 		goto out;
10775626Shylee 	}
10785626Shylee 
10795626Shylee 	if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
10805626Shylee 		err = errno;
10815626Shylee 		(void) fprintf(stderr,
10825626Shylee 		    gettext("failed to open %s - %s\n"),
10835626Shylee 		    tmpfile_name, strerror(err));
10845626Shylee 		rv = KC_ERR_MODIFY_PLUGIN;
10855626Shylee 		goto out;
10865626Shylee 	}
10875626Shylee 
10885626Shylee 	/*
10895626Shylee 	 * Loop thru the config file and update the entry.
10905626Shylee 	 */
10915626Shylee 	while (fgets(buffer, MAXPATHLEN, pfile) != NULL) {
10925626Shylee 		char *name;
10935626Shylee 		int len;
10945626Shylee 
10955626Shylee 		if (buffer[0] == '#') {
10965626Shylee 			if (fputs(buffer, pfile_tmp) == EOF) {
10975626Shylee 				rv = KC_ERR_MODIFY_PLUGIN;
10985626Shylee 				goto out;
10995626Shylee 			} else {
11005626Shylee 				continue;
11015626Shylee 			}
11025626Shylee 		}
11035626Shylee 
11045626Shylee 		/*
11055626Shylee 		 * make a copy of the original buffer to buffer2.  Also get
11065626Shylee 		 * rid of the trailing '\n' from buffer2.
11075626Shylee 		 */
11085626Shylee 		(void) strlcpy(buffer2, buffer, MAXPATHLEN);
11095626Shylee 		len = strlen(buffer2);
11105626Shylee 		if (buffer2[len-1] == '\n') {
11115626Shylee 			len--;
11125626Shylee 		}
11135626Shylee 		buffer2[len] = '\0';
11145626Shylee 
11155626Shylee 		if ((name = strtok(buffer2, SEP_COLON)) == NULL) {
11165626Shylee 			rv = KC_ERR_UNINSTALL;
11175626Shylee 			goto out;
11185626Shylee 		}
11195626Shylee 
11205626Shylee 		if (strcmp(name, keystore_name) == 0) {
11215626Shylee 			/* found the entry */
11225626Shylee 			if (option == NULL)
11235626Shylee 				(void) snprintf(buffer, MAXPATHLEN,
11245626Shylee 				    "%s:%s%s\n", keystore_name,
11255626Shylee 				    CONF_MODULEPATH, entry->modulepath);
11265626Shylee 			else
11275626Shylee 				(void) snprintf(buffer, MAXPATHLEN,
11285626Shylee 				    "%s:%s%s;%s%s\n", keystore_name,
11295626Shylee 				    CONF_MODULEPATH, entry->modulepath,
11305626Shylee 				    CONF_OPTION, option);
11315626Shylee 
11325626Shylee 			if (fputs(buffer, pfile_tmp) == EOF) {
11335626Shylee 				err = errno;
11345626Shylee 				(void) fprintf(stderr, gettext(
11355626Shylee 				    "failed to write to %s: %s\n"),
11365626Shylee 				    tmpfile_name, strerror(err));
11375626Shylee 				rv = KC_ERR_MODIFY_PLUGIN;
11385626Shylee 				goto out;
11395626Shylee 			}
11405626Shylee 		} else {
11415626Shylee 
11425626Shylee 			if (fputs(buffer, pfile_tmp) == EOF) {
11435626Shylee 				rv = KC_ERR_UNINSTALL;
11445626Shylee 				goto out;
11455626Shylee 			}
11465626Shylee 		}
11475626Shylee 	}
11485626Shylee 
11495626Shylee 	if (rename(tmpfile_name, _PATH_KMF_CONF) == -1) {
11505626Shylee 		err = errno;
11515626Shylee 		(void) fprintf(stderr, gettext(
11525626Shylee 		    "failed to update the configuration - %s"), strerror(err));
11535626Shylee 		rv = KC_ERR_MODIFY_PLUGIN;
11545626Shylee 		goto out;
11555626Shylee 	}
11565626Shylee 
11575626Shylee 	if (chmod(_PATH_KMF_CONF,
11585626Shylee 	    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
11595626Shylee 		err = errno;
11605626Shylee 		(void) fprintf(stderr, gettext(
11615626Shylee 		    "failed to update the configuration - %s\n"),
11625626Shylee 		    strerror(err));
11635626Shylee 		rv = KC_ERR_MODIFY_PLUGIN;
11645626Shylee 		goto out;
11655626Shylee 	}
11665626Shylee 
11675626Shylee out:
11685626Shylee 	if (entry != NULL)
11695626Shylee 		free_entry(entry);
11705626Shylee 
11715626Shylee 	if (pfile != NULL)
11725626Shylee 		(void) fclose(pfile);
11735626Shylee 
11745626Shylee 	if (rv != KC_OK && pfile_tmp != NULL)
11755626Shylee 		(void) unlink(tmpfile_name);
11765626Shylee 
11775626Shylee 	if (pfile_tmp != NULL)
11785626Shylee 		(void) fclose(pfile_tmp);
11795626Shylee 
11805626Shylee 	return (rv);
11815626Shylee }
11825626Shylee 
11835626Shylee 
11845626Shylee int
11855626Shylee kc_modify(int argc, char *argv[])
11865626Shylee {
11875626Shylee 	if (argc > 2 &&
11885626Shylee 	    strcmp(argv[0], "modify") == 0 &&
11895626Shylee 	    strcmp(argv[1], "plugin") == 0) {
11905626Shylee 		return (kc_modify_plugin(argc, argv));
11915626Shylee 	} else {
11925626Shylee 		return (kc_modify_policy(argc, argv));
11935626Shylee 	}
11945626Shylee }
1195