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