xref: /onnv-gate/usr/src/cmd/cmd-crypto/kmfcfg/modify.c (revision 5051:cbbb7c8b40a9)
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*5051Swyllys  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
223089Swyllys  * Use is subject to license terms.
233089Swyllys  */
243089Swyllys 
253089Swyllys #pragma ident	"%Z%%M%	%I%	%E% SMI"
263089Swyllys 
273089Swyllys #include <stdio.h>
283089Swyllys #include <strings.h>
293089Swyllys #include <ctype.h>
303089Swyllys #include <libgen.h>
313089Swyllys #include <libintl.h>
323089Swyllys #include <errno.h>
333089Swyllys #include <kmfapiP.h>
343089Swyllys #include <cryptoutil.h>
353089Swyllys #include "util.h"
363089Swyllys 
373089Swyllys #define	KC_IGNORE_DATE			0x0000001
383089Swyllys #define	KC_IGNORE_UNKNOWN_EKUS		0x0000002
393089Swyllys #define	KC_IGNORE_TRUST_ANCHOR		0x0000004
403089Swyllys #define	KC_VALIDITY_ADJUSTTIME		0x0000008
413089Swyllys #define	KC_TA_NAME			0x0000010
423089Swyllys #define	KC_TA_SERIAL			0x0000020
433089Swyllys #define	KC_OCSP_RESPONDER_URI		0x0000040
443089Swyllys #define	KC_OCSP_PROXY			0x0000080
453089Swyllys #define	KC_OCSP_URI_FROM_CERT		0x0000100
463089Swyllys #define	KC_OCSP_RESP_LIFETIME		0x0000200
473089Swyllys #define	KC_OCSP_IGNORE_RESP_SIGN 	0x0000400
483089Swyllys #define	KC_OCSP_RESP_CERT_NAME		0x0000800
493089Swyllys #define	KC_OCSP_RESP_CERT_SERIAL	0x0001000
503089Swyllys #define	KC_OCSP_NONE			0x0002000
513089Swyllys #define	KC_CRL_BASEFILENAME		0x0004000
523089Swyllys #define	KC_CRL_DIRECTORY		0x0008000
533089Swyllys #define	KC_CRL_GET_URI			0x0010000
543089Swyllys #define	KC_CRL_PROXY			0x0020000
553089Swyllys #define	KC_CRL_IGNORE_SIGN		0x0040000
563089Swyllys #define	KC_CRL_IGNORE_DATE		0x0080000
573089Swyllys #define	KC_CRL_NONE			0x0100000
583089Swyllys #define	KC_KEYUSAGE			0x0200000
593089Swyllys #define	KC_KEYUSAGE_NONE		0x0400000
603089Swyllys #define	KC_EKUS				0x0800000
613089Swyllys #define	KC_EKUS_NONE			0x1000000
623089Swyllys 
633089Swyllys int
643089Swyllys kc_modify(int argc, char *argv[])
653089Swyllys {
663089Swyllys 	KMF_RETURN	ret;
673089Swyllys 	int 		rv = KC_OK;
683089Swyllys 	int		opt;
693089Swyllys 	extern int	optind_av;
703089Swyllys 	extern char	*optarg_av;
713089Swyllys 	char		*filename = NULL;
723089Swyllys 	uint32_t	flags = 0;
733089Swyllys 	boolean_t	ocsp_none_opt = B_FALSE;
743089Swyllys 	boolean_t	crl_none_opt = B_FALSE;
753089Swyllys 	boolean_t	ku_none_opt = B_FALSE;
763089Swyllys 	boolean_t	eku_none_opt = B_FALSE;
773089Swyllys 	int		ocsp_set_attr = 0;
783089Swyllys 	int		crl_set_attr = 0;
793089Swyllys 	KMF_POLICY_RECORD oplc, plc;
803089Swyllys 
813089Swyllys 	(void) memset(&plc, 0, sizeof (KMF_POLICY_RECORD));
823089Swyllys 	(void) memset(&oplc, 0, sizeof (KMF_POLICY_RECORD));
833089Swyllys 
843089Swyllys 	while ((opt = getopt_av(argc, argv,
85*5051Swyllys 	    "i:(dbfile)"
86*5051Swyllys 	    "p:(policy)"
87*5051Swyllys 	    "d:(ignore-date)"
88*5051Swyllys 	    "e:(ignore-unknown-eku)"
89*5051Swyllys 	    "a:(ignore-trust-anchor)"
90*5051Swyllys 	    "v:(validity-adjusttime)"
91*5051Swyllys 	    "t:(ta-name)"
92*5051Swyllys 	    "s:(ta-serial)"
93*5051Swyllys 	    "o:(ocsp-responder)"
94*5051Swyllys 	    "P:(ocsp-proxy)"
95*5051Swyllys 	    "r:(ocsp-use-cert-responder)"
96*5051Swyllys 	    "T:(ocsp-response-lifetime)"
97*5051Swyllys 	    "R:(ocsp-ignore-response-sign)"
98*5051Swyllys 	    "n:(ocsp-responder-cert-name)"
99*5051Swyllys 	    "A:(ocsp-responder-cert-serial)"
100*5051Swyllys 	    "y:(ocsp-none)"
101*5051Swyllys 	    "c:(crl-basefilename)"
102*5051Swyllys 	    "I:(crl-directory)"
103*5051Swyllys 	    "g:(crl-get-crl-uri)"
104*5051Swyllys 	    "X:(crl-proxy)"
105*5051Swyllys 	    "S:(crl-ignore-crl-sign)"
106*5051Swyllys 	    "D:(crl-ignore-crl-date)"
107*5051Swyllys 	    "z:(crl-none)"
108*5051Swyllys 	    "u:(keyusage)"
109*5051Swyllys 	    "Y:(keyusage-none)"
110*5051Swyllys 	    "E:(ekunames)"
111*5051Swyllys 	    "O:(ekuoids)"
112*5051Swyllys 	    "Z:(eku-none)")) != EOF) {
1133089Swyllys 		switch (opt) {
1143089Swyllys 			case 'i':
1153089Swyllys 				filename = get_string(optarg_av, &rv);
1163089Swyllys 				if (filename == NULL) {
1173089Swyllys 					(void) fprintf(stderr,
1183089Swyllys 					    gettext("Error dbfile input.\n"));
1193089Swyllys 				}
1203089Swyllys 				break;
1213089Swyllys 			case 'p':
1223089Swyllys 				plc.name = get_string(optarg_av, &rv);
1233089Swyllys 				if (plc.name == NULL) {
1243089Swyllys 					(void) fprintf(stderr,
1253089Swyllys 					    gettext("Error policy name.\n"));
1263089Swyllys 				}
1273089Swyllys 				break;
1283089Swyllys 			case 'd':
1293089Swyllys 				plc.ignore_date = get_boolean(optarg_av);
1303089Swyllys 				if (plc.ignore_date == -1) {
1313089Swyllys 					(void) fprintf(stderr,
1323089Swyllys 					    gettext("Error boolean input.\n"));
1333089Swyllys 					rv = KC_ERR_USAGE;
1343089Swyllys 				} else {
1353089Swyllys 					flags |= KC_IGNORE_DATE;
1363089Swyllys 				}
1373089Swyllys 				break;
1383089Swyllys 			case 'e':
1393089Swyllys 				plc.ignore_unknown_ekus =
1403089Swyllys 				    get_boolean(optarg_av);
1413089Swyllys 				if (plc.ignore_unknown_ekus == -1) {
1423089Swyllys 					(void) fprintf(stderr,
1433089Swyllys 					    gettext("Error boolean input.\n"));
1443089Swyllys 					rv = KC_ERR_USAGE;
1453089Swyllys 				} else {
1463089Swyllys 					flags |= KC_IGNORE_UNKNOWN_EKUS;
1473089Swyllys 				}
1483089Swyllys 				break;
1493089Swyllys 			case 'a':
1503089Swyllys 				plc.ignore_trust_anchor =
1513089Swyllys 				    get_boolean(optarg_av);
1523089Swyllys 				if (plc.ignore_trust_anchor == -1) {
1533089Swyllys 					(void) fprintf(stderr,
1543089Swyllys 					    gettext("Error boolean input.\n"));
1553089Swyllys 					rv = KC_ERR_USAGE;
1563089Swyllys 				} else {
1573089Swyllys 					flags |= KC_IGNORE_TRUST_ANCHOR;
1583089Swyllys 				}
1593089Swyllys 				break;
1603089Swyllys 			case 'v':
1613089Swyllys 				plc.validity_adjusttime =
1623089Swyllys 				    get_string(optarg_av, &rv);
1633089Swyllys 				if (plc.validity_adjusttime == NULL) {
1643089Swyllys 					(void) fprintf(stderr,
1653089Swyllys 					    gettext("Error time input.\n"));
1663089Swyllys 				} else {
1673089Swyllys 					uint32_t adj;
1683089Swyllys 					/* for syntax checking */
1693089Swyllys 					if (str2lifetime(
1703089Swyllys 					    plc.validity_adjusttime,
1713089Swyllys 					    &adj) < 0) {
1723089Swyllys 						(void) fprintf(stderr,
1733089Swyllys 						    gettext("Error time "
1743089Swyllys 						    "input.\n"));
1753089Swyllys 						rv = KC_ERR_USAGE;
1763089Swyllys 					} else {
1773089Swyllys 						flags |= KC_VALIDITY_ADJUSTTIME;
1783089Swyllys 					}
1793089Swyllys 				}
1803089Swyllys 				break;
1813089Swyllys 			case 't':
1823089Swyllys 				plc.ta_name = get_string(optarg_av, &rv);
1833089Swyllys 				if (plc.ta_name == NULL) {
1843089Swyllys 					(void) fprintf(stderr,
1853089Swyllys 					    gettext("Error name input.\n"));
1863089Swyllys 				} else {
1873089Swyllys 					KMF_X509_NAME taDN;
1883089Swyllys 					/* for syntax checking */
189*5051Swyllys 					if (kmf_dn_parser(plc.ta_name,
1903089Swyllys 					    &taDN) != KMF_OK) {
1913089Swyllys 						(void) fprintf(stderr,
1923089Swyllys 						    gettext("Error name "
1933089Swyllys 						    "input.\n"));
1943089Swyllys 						rv = KC_ERR_USAGE;
1953089Swyllys 					} else {
196*5051Swyllys 						kmf_free_dn(&taDN);
1973089Swyllys 						flags |= KC_TA_NAME;
1983089Swyllys 					}
1993089Swyllys 				}
2003089Swyllys 				break;
2013089Swyllys 			case 's':
2023089Swyllys 				plc.ta_serial = get_string(optarg_av, &rv);
2033089Swyllys 				if (plc.ta_serial == NULL) {
2043089Swyllys 					(void) fprintf(stderr,
2053089Swyllys 					    gettext("Error serial input.\n"));
2063089Swyllys 				} else {
2073089Swyllys 					uchar_t *bytes = NULL;
2083089Swyllys 					size_t bytelen;
2093089Swyllys 
210*5051Swyllys 					ret = kmf_hexstr_to_bytes(
2113089Swyllys 					    (uchar_t *)plc.ta_serial,
2123089Swyllys 					    &bytes, &bytelen);
2133089Swyllys 					if (ret != KMF_OK || bytes == NULL) {
2143089Swyllys 						(void) fprintf(stderr,
2153089Swyllys 						    gettext("serial number "
2163089Swyllys 						    "must be specified as a "
2173089Swyllys 						    "hex number "
2183089Swyllys 						    "(ex: 0x0102030405"
2193089Swyllys 						    "ffeeddee)\n"));
2203089Swyllys 						rv = KC_ERR_USAGE;
2213089Swyllys 						break;
2223089Swyllys 					}
2233089Swyllys 					if (bytes != NULL)
2243089Swyllys 						free(bytes);
2253089Swyllys 					flags |= KC_TA_SERIAL;
2263089Swyllys 				}
2273089Swyllys 				break;
2283089Swyllys 			case 'o':
2293089Swyllys 				plc.VAL_OCSP_RESPONDER_URI =
230*5051Swyllys 				    get_string(optarg_av, &rv);
2313089Swyllys 				if (plc.VAL_OCSP_RESPONDER_URI == NULL) {
2323089Swyllys 					(void) fprintf(stderr,
2333089Swyllys 					    gettext("Error responder "
2343089Swyllys 					    "input.\n"));
2353089Swyllys 				} else {
2363089Swyllys 					flags |= KC_OCSP_RESPONDER_URI;
2373089Swyllys 					ocsp_set_attr++;
2383089Swyllys 				}
2393089Swyllys 				break;
2403089Swyllys 			case 'P':
2413089Swyllys 				plc.VAL_OCSP_PROXY = get_string(optarg_av, &rv);
2423089Swyllys 				if (plc.VAL_OCSP_PROXY == NULL) {
2433089Swyllys 					(void) fprintf(stderr,
2443089Swyllys 					    gettext("Error proxy input.\n"));
2453089Swyllys 				} else {
2463089Swyllys 					flags |= KC_OCSP_PROXY;
2473089Swyllys 					ocsp_set_attr++;
2483089Swyllys 				}
2493089Swyllys 				break;
2503089Swyllys 			case 'r':
2513089Swyllys 				plc.VAL_OCSP_URI_FROM_CERT =
2523089Swyllys 				    get_boolean(optarg_av);
2533089Swyllys 				if (plc.VAL_OCSP_URI_FROM_CERT == -1) {
2543089Swyllys 					(void) fprintf(stderr,
2553089Swyllys 					    gettext("Error boolean input.\n"));
2563089Swyllys 					rv = KC_ERR_USAGE;
2573089Swyllys 				} else {
2583089Swyllys 					flags |= KC_OCSP_URI_FROM_CERT;
2593089Swyllys 					ocsp_set_attr++;
2603089Swyllys 				}
2613089Swyllys 				break;
2623089Swyllys 			case 'T':
2633089Swyllys 				plc.VAL_OCSP_RESP_LIFETIME =
2643089Swyllys 				    get_string(optarg_av, &rv);
2653089Swyllys 				if (plc.VAL_OCSP_RESP_LIFETIME == NULL) {
2663089Swyllys 					(void) fprintf(stderr,
2673089Swyllys 					    gettext("Error time input.\n"));
2683089Swyllys 				} else {
2693089Swyllys 					uint32_t adj;
2703089Swyllys 					/* for syntax checking */
2713089Swyllys 					if (str2lifetime(
2723089Swyllys 					    plc.VAL_OCSP_RESP_LIFETIME,
2733089Swyllys 					    &adj) < 0) {
2743089Swyllys 						(void) fprintf(stderr,
2753089Swyllys 						    gettext("Error time "
2763089Swyllys 						    "input.\n"));
2773089Swyllys 						rv = KC_ERR_USAGE;
2783089Swyllys 					} else {
2793089Swyllys 						flags |= KC_OCSP_RESP_LIFETIME;
2803089Swyllys 						ocsp_set_attr++;
2813089Swyllys 					}
2823089Swyllys 				}
2833089Swyllys 				break;
2843089Swyllys 			case 'R':
2853089Swyllys 				plc.VAL_OCSP_IGNORE_RESP_SIGN =
2863089Swyllys 				    get_boolean(optarg_av);
2873089Swyllys 				if (plc.VAL_OCSP_IGNORE_RESP_SIGN == -1) {
2883089Swyllys 					(void) fprintf(stderr,
2893089Swyllys 					    gettext("Error boolean input.\n"));
2903089Swyllys 					rv = KC_ERR_USAGE;
2913089Swyllys 				} else {
2923089Swyllys 					flags |= KC_OCSP_IGNORE_RESP_SIGN;
2933089Swyllys 					ocsp_set_attr++;
2943089Swyllys 				}
2953089Swyllys 				break;
2963089Swyllys 			case 'n':
2973089Swyllys 				plc.VAL_OCSP_RESP_CERT_NAME =
2983089Swyllys 				    get_string(optarg_av, &rv);
2993089Swyllys 				if (plc.VAL_OCSP_RESP_CERT_NAME == NULL) {
3003089Swyllys 					(void) fprintf(stderr,
3013089Swyllys 					    gettext("Error name input.\n"));
3023089Swyllys 				} else {
3033089Swyllys 					KMF_X509_NAME respDN;
3043089Swyllys 					/* for syntax checking */
305*5051Swyllys 					if (kmf_dn_parser(
3063089Swyllys 					    plc.VAL_OCSP_RESP_CERT_NAME,
3073089Swyllys 					    &respDN) != KMF_OK) {
3083089Swyllys 						(void) fprintf(stderr,
3093089Swyllys 						    gettext("Error name "
3103089Swyllys 						    "input.\n"));
3113089Swyllys 						rv = KC_ERR_USAGE;
3123089Swyllys 					} else {
313*5051Swyllys 						kmf_free_dn(&respDN);
3143089Swyllys 						flags |= KC_OCSP_RESP_CERT_NAME;
3153089Swyllys 						ocsp_set_attr++;
3163089Swyllys 					}
3173089Swyllys 				}
3183089Swyllys 				break;
3193089Swyllys 			case 'A':
3203089Swyllys 				plc.VAL_OCSP_RESP_CERT_SERIAL =
3213089Swyllys 				    get_string(optarg_av, &rv);
3223089Swyllys 				if (plc.VAL_OCSP_RESP_CERT_SERIAL == NULL) {
3233089Swyllys 					(void) fprintf(stderr,
3243089Swyllys 					    gettext("Error serial input.\n"));
3253089Swyllys 				} else {
3263089Swyllys 					uchar_t *bytes = NULL;
3273089Swyllys 					size_t bytelen;
3283089Swyllys 
329*5051Swyllys 					ret = kmf_hexstr_to_bytes((uchar_t *)
3303089Swyllys 					    plc.VAL_OCSP_RESP_CERT_SERIAL,
3313089Swyllys 					    &bytes, &bytelen);
3323089Swyllys 					if (ret != KMF_OK || bytes == NULL) {
3333089Swyllys 						(void) fprintf(stderr,
3343089Swyllys 						    gettext("serial number "
3353089Swyllys 						    "must be specified as a "
3363089Swyllys 						    "hex number "
3373089Swyllys 						    "(ex: 0x0102030405"
3383089Swyllys 						    "ffeeddee)\n"));
3393089Swyllys 						rv = KC_ERR_USAGE;
3403089Swyllys 						break;
3413089Swyllys 					}
3423089Swyllys 					if (bytes != NULL)
3433089Swyllys 						free(bytes);
3443089Swyllys 					flags |= KC_OCSP_RESP_CERT_SERIAL;
3453089Swyllys 					ocsp_set_attr++;
3463089Swyllys 				}
3473089Swyllys 				break;
3483089Swyllys 			case 'y':
3493089Swyllys 				ocsp_none_opt = get_boolean(optarg_av);
3503089Swyllys 				if (ocsp_none_opt == -1) {
3513089Swyllys 					(void) fprintf(stderr,
3523089Swyllys 					    gettext("Error boolean input.\n"));
3533089Swyllys 					rv = KC_ERR_USAGE;
3543089Swyllys 				} else {
3553089Swyllys 					flags |= KC_OCSP_NONE;
3563089Swyllys 				}
3573089Swyllys 				break;
3583089Swyllys 			case 'c':
3593089Swyllys 				plc.VAL_CRL_BASEFILENAME =
3603089Swyllys 				    get_string(optarg_av, &rv);
3613089Swyllys 				if (plc.VAL_CRL_BASEFILENAME == NULL) {
3623089Swyllys 					(void) fprintf(stderr, gettext(
3633089Swyllys 					    "Error basefilename input.\n"));
3643089Swyllys 				} else {
3653089Swyllys 					flags |= KC_CRL_BASEFILENAME;
3663089Swyllys 					crl_set_attr++;
3673089Swyllys 				}
3683089Swyllys 				break;
3693089Swyllys 			case 'I':
3703089Swyllys 				plc.VAL_CRL_DIRECTORY =
3713089Swyllys 				    get_string(optarg_av, &rv);
3723089Swyllys 				if (plc.VAL_CRL_DIRECTORY == NULL) {
3733089Swyllys 					(void) fprintf(stderr,
3743089Swyllys 					    gettext("Error boolean input.\n"));
3753089Swyllys 				} else {
3763089Swyllys 					flags |= KC_CRL_DIRECTORY;
3773089Swyllys 					crl_set_attr++;
3783089Swyllys 				}
3793089Swyllys 				break;
3803089Swyllys 			case 'g':
3813089Swyllys 				plc.VAL_CRL_GET_URI = get_boolean(optarg_av);
3823089Swyllys 				if (plc.VAL_CRL_GET_URI == -1) {
3833089Swyllys 					(void) fprintf(stderr,
3843089Swyllys 					    gettext("Error boolean input.\n"));
3853089Swyllys 					rv = KC_ERR_USAGE;
3863089Swyllys 				} else {
3873089Swyllys 					flags |= KC_CRL_GET_URI;
3883089Swyllys 					crl_set_attr++;
3893089Swyllys 				}
3903089Swyllys 				break;
3913089Swyllys 			case 'X':
3923089Swyllys 				plc.VAL_CRL_PROXY = get_string(optarg_av, &rv);
3933089Swyllys 				if (plc.VAL_CRL_PROXY == NULL) {
3943089Swyllys 					(void) fprintf(stderr,
3953089Swyllys 					    gettext("Error proxy input.\n"));
3963089Swyllys 				} else {
3973089Swyllys 					flags |= KC_CRL_PROXY;
3983089Swyllys 					crl_set_attr++;
3993089Swyllys 				}
4003089Swyllys 				break;
4013089Swyllys 			case 'S':
4023089Swyllys 				plc.VAL_CRL_IGNORE_SIGN =
4033089Swyllys 				    get_boolean(optarg_av);
4043089Swyllys 				if (plc.VAL_CRL_IGNORE_SIGN == -1) {
4053089Swyllys 					(void) fprintf(stderr,
4063089Swyllys 					    gettext("Error boolean input.\n"));
4073089Swyllys 					rv = KC_ERR_USAGE;
4083089Swyllys 				} else {
4093089Swyllys 					flags |= KC_CRL_IGNORE_SIGN;
4103089Swyllys 					crl_set_attr++;
4113089Swyllys 				}
4123089Swyllys 				break;
4133089Swyllys 			case 'D':
4143089Swyllys 				plc.VAL_CRL_IGNORE_DATE =
415*5051Swyllys 				    get_boolean(optarg_av);
4163089Swyllys 				if (plc.VAL_CRL_IGNORE_DATE == -1) {
4173089Swyllys 					(void) fprintf(stderr,
4183089Swyllys 					    gettext("Error boolean input.\n"));
4193089Swyllys 					rv = KC_ERR_USAGE;
4203089Swyllys 				} else {
4213089Swyllys 					flags |= KC_CRL_IGNORE_DATE;
4223089Swyllys 					crl_set_attr++;
4233089Swyllys 				}
4243089Swyllys 				break;
4253089Swyllys 			case 'z':
4263089Swyllys 				crl_none_opt = get_boolean(optarg_av);
4273089Swyllys 				if (crl_none_opt == -1) {
4283089Swyllys 					(void) fprintf(stderr,
4293089Swyllys 					    gettext("Error boolean input.\n"));
4303089Swyllys 					rv = KC_ERR_USAGE;
4313089Swyllys 				} else {
4323089Swyllys 					flags |= KC_CRL_NONE;
4333089Swyllys 				}
4343089Swyllys 				break;
4353089Swyllys 			case 'u':
4363089Swyllys 				plc.ku_bits = parseKUlist(optarg_av);
4373089Swyllys 				if (plc.ku_bits == 0) {
4383089Swyllys 					(void) fprintf(stderr, gettext(
4393089Swyllys 					    "Error keyusage input.\n"));
4403089Swyllys 					rv = KC_ERR_USAGE;
4413089Swyllys 				} else {
4423089Swyllys 					flags |= KC_KEYUSAGE;
4433089Swyllys 				}
4443089Swyllys 				break;
4453089Swyllys 			case 'Y':
4463089Swyllys 				ku_none_opt = get_boolean(optarg_av);
4473089Swyllys 				if (ku_none_opt == -1) {
4483089Swyllys 					(void) fprintf(stderr,
4493089Swyllys 					    gettext("Error boolean input.\n"));
4503089Swyllys 					rv = KC_ERR_USAGE;
4513089Swyllys 				} else {
4523089Swyllys 					flags |= KC_KEYUSAGE_NONE;
4533089Swyllys 				}
4543089Swyllys 				break;
4553089Swyllys 			case 'E':
4563089Swyllys 				if (parseEKUNames(optarg_av, &plc) != 0) {
4573089Swyllys 					(void) fprintf(stderr,
4583089Swyllys 					    gettext("Error EKU input.\n"));
4593089Swyllys 					rv = KC_ERR_USAGE;
4603089Swyllys 				} else {
4613089Swyllys 					flags |= KC_EKUS;
4623089Swyllys 				}
4633089Swyllys 				break;
4643089Swyllys 			case 'O':
4653089Swyllys 				if (parseEKUOIDs(optarg_av, &plc) != 0) {
4663089Swyllys 					(void) fprintf(stderr,
4673089Swyllys 					    gettext("Error EKU OID input.\n"));
4683089Swyllys 					rv = KC_ERR_USAGE;
4693089Swyllys 				} else {
4703089Swyllys 					flags |= KC_EKUS;
4713089Swyllys 				}
4723089Swyllys 				break;
4733089Swyllys 			case 'Z':
4743089Swyllys 				eku_none_opt = get_boolean(optarg_av);
4753089Swyllys 				if (eku_none_opt == -1) {
4763089Swyllys 					(void) fprintf(stderr,
4773089Swyllys 					    gettext("Error boolean input.\n"));
4783089Swyllys 					rv = KC_ERR_USAGE;
4793089Swyllys 				} else {
4803089Swyllys 					flags |= KC_EKUS_NONE;
4813089Swyllys 				}
4823089Swyllys 				break;
4833089Swyllys 			default:
4843089Swyllys 				(void) fprintf(stderr,
4853089Swyllys 				    gettext("Error input option.\n"));
4863089Swyllys 				rv = KC_ERR_USAGE;
4873089Swyllys 				break;
4883089Swyllys 		}
4893089Swyllys 		if (rv != KC_OK)
4903089Swyllys 			goto out;
4913089Swyllys 	}
4923089Swyllys 
4933089Swyllys 	/* No additional args allowed. */
4943089Swyllys 	argc -= optind_av;
4953089Swyllys 	if (argc) {
4963089Swyllys 		(void) fprintf(stderr,
4973089Swyllys 		    gettext("Error input option\n"));
4983089Swyllys 		rv = KC_ERR_USAGE;
4993089Swyllys 		goto out;
5003089Swyllys 	}
5013089Swyllys 
5023089Swyllys 	if (filename == NULL) {
5033089Swyllys 		filename = strdup(KMF_DEFAULT_POLICY_FILE);
5043089Swyllys 		if (filename == NULL) {
5053089Swyllys 			rv = KC_ERR_MEMORY;
5063089Swyllys 			goto out;
5073089Swyllys 		}
5083089Swyllys 	}
5093089Swyllys 
5103089Swyllys 	/*
5113089Swyllys 	 * Must have a policy name. The policy name can not be default
5123089Swyllys 	 * if using the default policy file.
5133089Swyllys 	 */
5143089Swyllys 	if (plc.name == NULL) {
5153089Swyllys 		(void) fprintf(stderr,
5163089Swyllys 		    gettext("You must specify a policy name.\n"));
5173089Swyllys 		rv = KC_ERR_USAGE;
5183089Swyllys 		goto out;
5193089Swyllys 	} else if (strcmp(filename, KMF_DEFAULT_POLICY_FILE) == 0 &&
5203089Swyllys 	    strcmp(plc.name, KMF_DEFAULT_POLICY_NAME) == 0) {
5213089Swyllys 		(void) fprintf(stderr,
5223089Swyllys 		    gettext("Can not modify the default policy in the default "
5233089Swyllys 		    "policy file.\n"));
5243089Swyllys 		rv = KC_ERR_USAGE;
5253089Swyllys 		goto out;
5263089Swyllys 	}
5273089Swyllys 
5283089Swyllys 	/* Check the access permission of the policy DB */
5293089Swyllys 	if (access(filename, W_OK) < 0) {
5303089Swyllys 		int err = errno;
5313089Swyllys 		(void) fprintf(stderr,
5323089Swyllys 		    gettext("Cannot access \"%s\" for modify - %s\n"),
5333089Swyllys 		    filename, strerror(err));
5343089Swyllys 		rv = KC_ERR_ACCESS;
5353089Swyllys 		goto out;
5363089Swyllys 	}
5373089Swyllys 
5383089Swyllys 	/* Try to load the named policy from the DB */
539*5051Swyllys 	ret = kmf_get_policy(filename, plc.name, &oplc);
5403089Swyllys 	if (ret != KMF_OK) {
5413089Swyllys 		(void) fprintf(stderr,
5423089Swyllys 		    gettext("Error loading policy \"%s\" from %s\n"), filename,
5433089Swyllys 		    plc.name);
5443089Swyllys 		return (KC_ERR_FIND_POLICY);
5453089Swyllys 	}
5463089Swyllys 
5473089Swyllys 	/* Update the general policy attributes. */
5483089Swyllys 	if (flags & KC_IGNORE_DATE)
5493089Swyllys 		oplc.ignore_date = plc.ignore_date;
5503089Swyllys 
5513089Swyllys 	if (flags & KC_IGNORE_UNKNOWN_EKUS)
5523089Swyllys 		oplc.ignore_unknown_ekus = plc.ignore_unknown_ekus;
5533089Swyllys 
5543089Swyllys 	if (flags & KC_IGNORE_TRUST_ANCHOR)
5553089Swyllys 		oplc.ignore_trust_anchor = plc.ignore_trust_anchor;
5563089Swyllys 
5573089Swyllys 	if (flags & KC_VALIDITY_ADJUSTTIME) {
5583089Swyllys 		if (oplc.validity_adjusttime)
5593089Swyllys 			free(oplc.validity_adjusttime);
5603089Swyllys 		oplc.validity_adjusttime =
561*5051Swyllys 		    plc.validity_adjusttime;
5623089Swyllys 	}
5633089Swyllys 
5643089Swyllys 	if (flags & KC_TA_NAME) {
5653089Swyllys 		if (oplc.ta_name)
5663089Swyllys 			free(oplc.ta_name);
5673089Swyllys 		oplc.ta_name = plc.ta_name;
5683089Swyllys 	}
5693089Swyllys 	if (flags & KC_TA_SERIAL) {
5703089Swyllys 		if (oplc.ta_serial)
5713089Swyllys 			free(oplc.ta_serial);
5723089Swyllys 		oplc.ta_serial = plc.ta_serial;
5733089Swyllys 	}
5743089Swyllys 
5753089Swyllys 	/* Update the OCSP policy */
5763089Swyllys 	if (ocsp_none_opt == B_TRUE) {
5773089Swyllys 		if (ocsp_set_attr > 0) {
5783089Swyllys 			(void) fprintf(stderr,
5793089Swyllys 			    gettext("Can not set ocsp-none=true and other "
5803089Swyllys 			    "OCSP attributes at the same time.\n"));
5813089Swyllys 			rv = KC_ERR_USAGE;
5823089Swyllys 			goto out;
5833089Swyllys 		}
5843089Swyllys 
5853089Swyllys 		/*
5863089Swyllys 		 * If the original policy does not have OCSP checking,
5873089Swyllys 		 * then we do not need to do anything.  If the original
5883089Swyllys 		 * policy has the OCSP checking, then we need to release the
5893089Swyllys 		 * space of OCSP attributes and turn the OCSP checking off.
5903089Swyllys 		 */
5913089Swyllys 		if (oplc.revocation & KMF_REVOCATION_METHOD_OCSP) {
5923089Swyllys 			if (oplc.VAL_OCSP_BASIC.responderURI) {
5933089Swyllys 				free(oplc.VAL_OCSP_BASIC.responderURI);
5943089Swyllys 				oplc.VAL_OCSP_BASIC.responderURI = NULL;
5953089Swyllys 			}
5963089Swyllys 
5973089Swyllys 			if (oplc.VAL_OCSP_BASIC.proxy) {
5983089Swyllys 				free(oplc.VAL_OCSP_BASIC.proxy);
5993089Swyllys 				oplc.VAL_OCSP_BASIC.proxy = NULL;
6003089Swyllys 			}
6013089Swyllys 
6023089Swyllys 			if (oplc.VAL_OCSP_BASIC.response_lifetime) {
6033089Swyllys 				free(oplc.VAL_OCSP_BASIC.response_lifetime);
6043089Swyllys 				oplc.VAL_OCSP_BASIC.response_lifetime = NULL;
6053089Swyllys 			}
6063089Swyllys 
6073089Swyllys 			if (flags & KC_OCSP_RESP_CERT_NAME) {
6083089Swyllys 				free(oplc.VAL_OCSP_RESP_CERT.name);
6093089Swyllys 				oplc.VAL_OCSP_RESP_CERT.name = NULL;
6103089Swyllys 			}
6113089Swyllys 
6123089Swyllys 			if (flags & KC_OCSP_RESP_CERT_SERIAL) {
6133089Swyllys 				free(oplc.VAL_OCSP_RESP_CERT.serial);
6143089Swyllys 				oplc.VAL_OCSP_RESP_CERT.serial = NULL;
6153089Swyllys 			}
6163089Swyllys 
6173089Swyllys 			/* Turn off the OCSP checking */
6183089Swyllys 			oplc.revocation &= ~KMF_REVOCATION_METHOD_OCSP;
6193089Swyllys 		}
6203089Swyllys 
6213089Swyllys 	} else {
6223089Swyllys 		/*
6233089Swyllys 		 * If the "ocsp-none" option is not set or is set to false,
6243089Swyllys 		 * then we only need to do the modification if there is at
6253089Swyllys 		 * least one OCSP attribute is specified.
6263089Swyllys 		 */
6273089Swyllys 		if (ocsp_set_attr > 0) {
6283089Swyllys 			if (flags & KC_OCSP_RESPONDER_URI) {
6293089Swyllys 				if (oplc.VAL_OCSP_RESPONDER_URI)
6303089Swyllys 					free(oplc.VAL_OCSP_RESPONDER_URI);
6313089Swyllys 				oplc.VAL_OCSP_RESPONDER_URI =
632*5051Swyllys 				    plc.VAL_OCSP_RESPONDER_URI;
6333089Swyllys 			}
6343089Swyllys 
6353089Swyllys 			if (flags & KC_OCSP_PROXY) {
6363089Swyllys 				if (oplc.VAL_OCSP_PROXY)
6373089Swyllys 					free(oplc.VAL_OCSP_PROXY);
6383089Swyllys 				oplc.VAL_OCSP_PROXY = plc.VAL_OCSP_PROXY;
6393089Swyllys 			}
6403089Swyllys 
6413089Swyllys 			if (flags & KC_OCSP_URI_FROM_CERT)
6423089Swyllys 				oplc.VAL_OCSP_URI_FROM_CERT =
643*5051Swyllys 				    plc.VAL_OCSP_URI_FROM_CERT;
6443089Swyllys 
6453089Swyllys 			if (flags & KC_OCSP_RESP_LIFETIME) {
6463089Swyllys 				if (oplc.VAL_OCSP_RESP_LIFETIME)
6473089Swyllys 					free(oplc.VAL_OCSP_RESP_LIFETIME);
6483089Swyllys 				oplc.VAL_OCSP_RESP_LIFETIME =
649*5051Swyllys 				    plc.VAL_OCSP_RESP_LIFETIME;
6503089Swyllys 			}
6513089Swyllys 
6523089Swyllys 			if (flags & KC_OCSP_IGNORE_RESP_SIGN)
6533089Swyllys 				oplc.VAL_OCSP_IGNORE_RESP_SIGN =
654*5051Swyllys 				    plc.VAL_OCSP_IGNORE_RESP_SIGN;
6553089Swyllys 
6563089Swyllys 			if (flags & KC_OCSP_RESP_CERT_NAME) {
6573089Swyllys 				if (oplc.VAL_OCSP_RESP_CERT_NAME)
6583089Swyllys 					free(oplc.VAL_OCSP_RESP_CERT_NAME);
6593089Swyllys 				oplc.VAL_OCSP_RESP_CERT_NAME =
660*5051Swyllys 				    plc.VAL_OCSP_RESP_CERT_NAME;
6613089Swyllys 			}
6623089Swyllys 
6633089Swyllys 			if (flags & KC_OCSP_RESP_CERT_SERIAL) {
6643089Swyllys 				if (oplc.VAL_OCSP_RESP_CERT_SERIAL)
6653089Swyllys 					free(oplc.VAL_OCSP_RESP_CERT_SERIAL);
6663089Swyllys 				oplc.VAL_OCSP_RESP_CERT_SERIAL =
667*5051Swyllys 				    plc.VAL_OCSP_RESP_CERT_SERIAL;
6683089Swyllys 			}
6693089Swyllys 
6703089Swyllys 			if (oplc.VAL_OCSP_RESP_CERT_NAME != NULL &&
6713089Swyllys 			    oplc.VAL_OCSP_RESP_CERT_SERIAL != NULL)
6723089Swyllys 				oplc.VAL_OCSP.has_resp_cert = B_TRUE;
6733089Swyllys 			else
6743089Swyllys 				oplc.VAL_OCSP.has_resp_cert = B_FALSE;
6753089Swyllys 
6763089Swyllys 			/* Turn on the OCSP checking */
6773089Swyllys 			oplc.revocation |= KMF_REVOCATION_METHOD_OCSP;
6783089Swyllys 		}
6793089Swyllys 	}
6803089Swyllys 
6813089Swyllys 	/* Update the CRL policy */
6823089Swyllys 	if (crl_none_opt == B_TRUE) {
6833089Swyllys 		if (crl_set_attr > 0) {
6843089Swyllys 			(void) fprintf(stderr,
6853089Swyllys 			    gettext("Can not set crl-none=true and other CRL "
6863089Swyllys 			    "attributes at the same time.\n"));
6873089Swyllys 			rv = KC_ERR_USAGE;
6883089Swyllys 			goto out;
6893089Swyllys 		}
6903089Swyllys 
6913089Swyllys 		/*
6923089Swyllys 		 * If the original policy does not have CRL checking,
6933089Swyllys 		 * then we do not need to do anything.  If the original
6943089Swyllys 		 * policy has the CRL checking, then we need to release the
6953089Swyllys 		 * space of CRL attributes and turn the CRL checking off.
6963089Swyllys 		 */
6973089Swyllys 		if (oplc.revocation & KMF_REVOCATION_METHOD_CRL) {
6983089Swyllys 			if (oplc.VAL_CRL_BASEFILENAME) {
6993089Swyllys 				free(oplc.VAL_CRL_BASEFILENAME);
7003089Swyllys 				oplc.VAL_CRL_BASEFILENAME = NULL;
7013089Swyllys 			}
7023089Swyllys 
7033089Swyllys 			if (oplc.VAL_CRL_DIRECTORY) {
7043089Swyllys 				free(oplc.VAL_CRL_DIRECTORY);
7053089Swyllys 				oplc.VAL_CRL_DIRECTORY = NULL;
7063089Swyllys 			}
7073089Swyllys 
7083089Swyllys 			if (oplc.VAL_CRL_PROXY) {
7093089Swyllys 				free(oplc.VAL_CRL_PROXY);
7103089Swyllys 				oplc.VAL_CRL_PROXY = NULL;
7113089Swyllys 			}
7123089Swyllys 
7133089Swyllys 			/* Turn off the CRL checking */
7143089Swyllys 			oplc.revocation &= ~KMF_REVOCATION_METHOD_CRL;
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 CRL attribute is specified.
7213089Swyllys 		 */
7223089Swyllys 		if (crl_set_attr > 0) {
7233089Swyllys 			if (flags & KC_CRL_BASEFILENAME) {
7243089Swyllys 				if (oplc.VAL_CRL_BASEFILENAME)
7253089Swyllys 					free(oplc.VAL_CRL_BASEFILENAME);
7263089Swyllys 				oplc.VAL_CRL_BASEFILENAME =
7273089Swyllys 				    plc.VAL_CRL_BASEFILENAME;
7283089Swyllys 			}
7293089Swyllys 
7303089Swyllys 			if (flags & KC_CRL_DIRECTORY) {
7313089Swyllys 				if (oplc.VAL_CRL_DIRECTORY)
7323089Swyllys 					free(oplc.VAL_CRL_DIRECTORY);
7333089Swyllys 				oplc.VAL_CRL_DIRECTORY = plc.VAL_CRL_DIRECTORY;
7343089Swyllys 			}
7353089Swyllys 
7363089Swyllys 			if (flags & KC_CRL_GET_URI) {
7373089Swyllys 				oplc.VAL_CRL_GET_URI = plc.VAL_CRL_GET_URI;
7383089Swyllys 			}
7393089Swyllys 
7403089Swyllys 			if (flags & KC_CRL_PROXY) {
7413089Swyllys 				if (oplc.VAL_CRL_PROXY)
7423089Swyllys 					free(oplc.VAL_CRL_PROXY);
7433089Swyllys 				oplc.VAL_CRL_PROXY = plc.VAL_CRL_PROXY;
7443089Swyllys 			}
7453089Swyllys 
7463089Swyllys 			if (flags & KC_CRL_IGNORE_SIGN) {
7473089Swyllys 				oplc.VAL_CRL_IGNORE_SIGN =
7483089Swyllys 				    plc.VAL_CRL_IGNORE_SIGN;
7493089Swyllys 			}
7503089Swyllys 
7513089Swyllys 			if (flags & KC_CRL_IGNORE_DATE) {
7523089Swyllys 				oplc.VAL_CRL_IGNORE_DATE =
7533089Swyllys 				    plc.VAL_CRL_IGNORE_DATE;
7543089Swyllys 			}
7553089Swyllys 
7563089Swyllys 			/* Turn on the CRL checking */
7573089Swyllys 			oplc.revocation |= KMF_REVOCATION_METHOD_CRL;
7583089Swyllys 		}
7593089Swyllys 	}
7603089Swyllys 
7613089Swyllys 	/* Update the Key Usage */
7623089Swyllys 	if (ku_none_opt == B_TRUE) {
7633089Swyllys 		if (flags & KC_KEYUSAGE) {
7643089Swyllys 			(void) fprintf(stderr,
7653089Swyllys 			    gettext("Can not set keyusage-none=true and "
7663089Swyllys 			    "modify the keyusage value at the same time.\n"));
7673089Swyllys 			rv = KC_ERR_USAGE;
7683089Swyllys 			goto out;
7693089Swyllys 		}
7703089Swyllys 
7713089Swyllys 		oplc.ku_bits = 0;
7723089Swyllys 	} else {
7733089Swyllys 		/*
7743089Swyllys 		 * If the "keyusage-none" option is not set or is set to
7753089Swyllys 		 * false, then we only need to do the modification if
7763089Swyllys 		 * the keyusage value is specified.
7773089Swyllys 		 */
7783089Swyllys 		if (flags & KC_KEYUSAGE)
7793089Swyllys 			oplc.ku_bits = plc.ku_bits;
7803089Swyllys 	}
7813089Swyllys 
7823089Swyllys 
7833089Swyllys 	/* Update the Extended Key Usage */
7843089Swyllys 	if (eku_none_opt == B_TRUE) {
7853089Swyllys 		if (flags & KC_EKUS) {
7863089Swyllys 			(void) fprintf(stderr,
7873089Swyllys 			    gettext("Can not set eku-none=true and modify "
7883089Swyllys 			    "EKU values at the same time.\n"));
7893089Swyllys 			rv = KC_ERR_USAGE;
7903089Swyllys 			goto out;
7913089Swyllys 		}
7923089Swyllys 
7933089Swyllys 		/* Release current EKU list (if any) */
7943089Swyllys 		if (oplc.eku_set.eku_count > 0) {
795*5051Swyllys 			kmf_free_eku_policy(&oplc.eku_set);
7963089Swyllys 			oplc.eku_set.eku_count = 0;
7973089Swyllys 			oplc.eku_set.ekulist = NULL;
7983089Swyllys 		}
7993089Swyllys 	} else {
8003089Swyllys 		/*
8013089Swyllys 		 * If the "eku-none" option is not set or is set to false,
8023089Swyllys 		 * then we only need to do the modification if either
8033089Swyllys 		 * "ekuname" or "ekuoids" is specified.
8043089Swyllys 		 */
8053089Swyllys 		if (flags & KC_EKUS) {
8063089Swyllys 			/* Release current EKU list (if any) */
807*5051Swyllys 			kmf_free_eku_policy(&oplc.eku_set);
8083089Swyllys 			oplc.eku_set = plc.eku_set;
8093089Swyllys 		}
8103089Swyllys 	}
8113089Swyllys 
8123089Swyllys 	/* Do a sanity check on the modified policy */
813*5051Swyllys 	ret = kmf_verify_policy(&oplc);
8143089Swyllys 	if (ret != KMF_OK) {
8153089Swyllys 		print_sanity_error(ret);
8163089Swyllys 		rv = KC_ERR_VERIFY_POLICY;
8173089Swyllys 		goto out;
8183089Swyllys 	}
8193089Swyllys 
8203089Swyllys 	/* The modify operation is a delete followed by an add */
821*5051Swyllys 	ret = kmf_delete_policy_from_db(oplc.name, filename);
8223089Swyllys 	if (ret != KMF_OK) {
8233089Swyllys 		rv = KC_ERR_DELETE_POLICY;
8243089Swyllys 		goto out;
8253089Swyllys 	}
8263089Swyllys 
8273089Swyllys 	/*
8283089Swyllys 	 * Now add the modified policy back to the DB.
8293089Swyllys 	 */
830*5051Swyllys 	ret = kmf_add_policy_to_db(&oplc, filename, B_FALSE);
8313089Swyllys 	if (ret != KMF_OK) {
8323089Swyllys 		(void) fprintf(stderr,
8333089Swyllys 		    gettext("Error adding policy to database: 0x%04x\n"), ret);
8343089Swyllys 		rv = KC_ERR_ADD_POLICY;
8353089Swyllys 		goto out;
8363089Swyllys 	}
8373089Swyllys 
8383089Swyllys out:
8393089Swyllys 	if (filename != NULL)
8403089Swyllys 		free(filename);
8413089Swyllys 
842*5051Swyllys 	kmf_free_policy_record(&oplc);
8433089Swyllys 
8443089Swyllys 	return (rv);
8453089Swyllys }
846