1*3089Swyllys /* 2*3089Swyllys * CDDL HEADER START 3*3089Swyllys * 4*3089Swyllys * The contents of this file are subject to the terms of the 5*3089Swyllys * Common Development and Distribution License (the "License"). 6*3089Swyllys * You may not use this file except in compliance with the License. 7*3089Swyllys * 8*3089Swyllys * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*3089Swyllys * or http://www.opensolaris.org/os/licensing. 10*3089Swyllys * See the License for the specific language governing permissions 11*3089Swyllys * and limitations under the License. 12*3089Swyllys * 13*3089Swyllys * When distributing Covered Code, include this CDDL HEADER in each 14*3089Swyllys * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*3089Swyllys * If applicable, add the following below this CDDL HEADER, with the 16*3089Swyllys * fields enclosed by brackets "[]" replaced with your own identifying 17*3089Swyllys * information: Portions Copyright [yyyy] [name of copyright owner] 18*3089Swyllys * 19*3089Swyllys * CDDL HEADER END 20*3089Swyllys * 21*3089Swyllys * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 22*3089Swyllys * Use is subject to license terms. 23*3089Swyllys */ 24*3089Swyllys 25*3089Swyllys #pragma ident "%Z%%M% %I% %E% SMI" 26*3089Swyllys 27*3089Swyllys #include <stdio.h> 28*3089Swyllys #include <strings.h> 29*3089Swyllys #include <ctype.h> 30*3089Swyllys #include <libgen.h> 31*3089Swyllys #include <libintl.h> 32*3089Swyllys #include <errno.h> 33*3089Swyllys #include <kmfapiP.h> 34*3089Swyllys #include <cryptoutil.h> 35*3089Swyllys #include "util.h" 36*3089Swyllys 37*3089Swyllys #define KC_IGNORE_DATE 0x0000001 38*3089Swyllys #define KC_IGNORE_UNKNOWN_EKUS 0x0000002 39*3089Swyllys #define KC_IGNORE_TRUST_ANCHOR 0x0000004 40*3089Swyllys #define KC_VALIDITY_ADJUSTTIME 0x0000008 41*3089Swyllys #define KC_TA_NAME 0x0000010 42*3089Swyllys #define KC_TA_SERIAL 0x0000020 43*3089Swyllys #define KC_OCSP_RESPONDER_URI 0x0000040 44*3089Swyllys #define KC_OCSP_PROXY 0x0000080 45*3089Swyllys #define KC_OCSP_URI_FROM_CERT 0x0000100 46*3089Swyllys #define KC_OCSP_RESP_LIFETIME 0x0000200 47*3089Swyllys #define KC_OCSP_IGNORE_RESP_SIGN 0x0000400 48*3089Swyllys #define KC_OCSP_RESP_CERT_NAME 0x0000800 49*3089Swyllys #define KC_OCSP_RESP_CERT_SERIAL 0x0001000 50*3089Swyllys #define KC_OCSP_NONE 0x0002000 51*3089Swyllys #define KC_CRL_BASEFILENAME 0x0004000 52*3089Swyllys #define KC_CRL_DIRECTORY 0x0008000 53*3089Swyllys #define KC_CRL_GET_URI 0x0010000 54*3089Swyllys #define KC_CRL_PROXY 0x0020000 55*3089Swyllys #define KC_CRL_IGNORE_SIGN 0x0040000 56*3089Swyllys #define KC_CRL_IGNORE_DATE 0x0080000 57*3089Swyllys #define KC_CRL_NONE 0x0100000 58*3089Swyllys #define KC_KEYUSAGE 0x0200000 59*3089Swyllys #define KC_KEYUSAGE_NONE 0x0400000 60*3089Swyllys #define KC_EKUS 0x0800000 61*3089Swyllys #define KC_EKUS_NONE 0x1000000 62*3089Swyllys 63*3089Swyllys int 64*3089Swyllys kc_modify(int argc, char *argv[]) 65*3089Swyllys { 66*3089Swyllys KMF_RETURN ret; 67*3089Swyllys int rv = KC_OK; 68*3089Swyllys int opt; 69*3089Swyllys extern int optind_av; 70*3089Swyllys extern char *optarg_av; 71*3089Swyllys char *filename = NULL; 72*3089Swyllys uint32_t flags = 0; 73*3089Swyllys boolean_t ocsp_none_opt = B_FALSE; 74*3089Swyllys boolean_t crl_none_opt = B_FALSE; 75*3089Swyllys boolean_t ku_none_opt = B_FALSE; 76*3089Swyllys boolean_t eku_none_opt = B_FALSE; 77*3089Swyllys int ocsp_set_attr = 0; 78*3089Swyllys int crl_set_attr = 0; 79*3089Swyllys KMF_POLICY_RECORD oplc, plc; 80*3089Swyllys 81*3089Swyllys (void) memset(&plc, 0, sizeof (KMF_POLICY_RECORD)); 82*3089Swyllys (void) memset(&oplc, 0, sizeof (KMF_POLICY_RECORD)); 83*3089Swyllys 84*3089Swyllys while ((opt = getopt_av(argc, argv, 85*3089Swyllys "i:(dbfile)" 86*3089Swyllys "p:(policy)" 87*3089Swyllys "d:(ignore-date)" 88*3089Swyllys "e:(ignore-unknown-eku)" 89*3089Swyllys "a:(ignore-trust-anchor)" 90*3089Swyllys "v:(validity-adjusttime)" 91*3089Swyllys "t:(ta-name)" 92*3089Swyllys "s:(ta-serial)" 93*3089Swyllys "o:(ocsp-responder)" 94*3089Swyllys "P:(ocsp-proxy)" 95*3089Swyllys "r:(ocsp-use-cert-responder)" 96*3089Swyllys "T:(ocsp-response-lifetime)" 97*3089Swyllys "R:(ocsp-ignore-response-sign)" 98*3089Swyllys "n:(ocsp-responder-cert-name)" 99*3089Swyllys "A:(ocsp-responder-cert-serial)" 100*3089Swyllys "y:(ocsp-none)" 101*3089Swyllys "c:(crl-basefilename)" 102*3089Swyllys "I:(crl-directory)" 103*3089Swyllys "g:(crl-get-crl-uri)" 104*3089Swyllys "X:(crl-proxy)" 105*3089Swyllys "S:(crl-ignore-crl-sign)" 106*3089Swyllys "D:(crl-ignore-crl-date)" 107*3089Swyllys "z:(crl-none)" 108*3089Swyllys "u:(keyusage)" 109*3089Swyllys "Y:(keyusage-none)" 110*3089Swyllys "E:(ekunames)" 111*3089Swyllys "O:(ekuoids)" 112*3089Swyllys "Z:(eku-none)")) != EOF) { 113*3089Swyllys switch (opt) { 114*3089Swyllys case 'i': 115*3089Swyllys filename = get_string(optarg_av, &rv); 116*3089Swyllys if (filename == NULL) { 117*3089Swyllys (void) fprintf(stderr, 118*3089Swyllys gettext("Error dbfile input.\n")); 119*3089Swyllys } 120*3089Swyllys break; 121*3089Swyllys case 'p': 122*3089Swyllys plc.name = get_string(optarg_av, &rv); 123*3089Swyllys if (plc.name == NULL) { 124*3089Swyllys (void) fprintf(stderr, 125*3089Swyllys gettext("Error policy name.\n")); 126*3089Swyllys } 127*3089Swyllys break; 128*3089Swyllys case 'd': 129*3089Swyllys plc.ignore_date = get_boolean(optarg_av); 130*3089Swyllys if (plc.ignore_date == -1) { 131*3089Swyllys (void) fprintf(stderr, 132*3089Swyllys gettext("Error boolean input.\n")); 133*3089Swyllys rv = KC_ERR_USAGE; 134*3089Swyllys } else { 135*3089Swyllys flags |= KC_IGNORE_DATE; 136*3089Swyllys } 137*3089Swyllys break; 138*3089Swyllys case 'e': 139*3089Swyllys plc.ignore_unknown_ekus = 140*3089Swyllys get_boolean(optarg_av); 141*3089Swyllys if (plc.ignore_unknown_ekus == -1) { 142*3089Swyllys (void) fprintf(stderr, 143*3089Swyllys gettext("Error boolean input.\n")); 144*3089Swyllys rv = KC_ERR_USAGE; 145*3089Swyllys } else { 146*3089Swyllys flags |= KC_IGNORE_UNKNOWN_EKUS; 147*3089Swyllys } 148*3089Swyllys break; 149*3089Swyllys case 'a': 150*3089Swyllys plc.ignore_trust_anchor = 151*3089Swyllys get_boolean(optarg_av); 152*3089Swyllys if (plc.ignore_trust_anchor == -1) { 153*3089Swyllys (void) fprintf(stderr, 154*3089Swyllys gettext("Error boolean input.\n")); 155*3089Swyllys rv = KC_ERR_USAGE; 156*3089Swyllys } else { 157*3089Swyllys flags |= KC_IGNORE_TRUST_ANCHOR; 158*3089Swyllys } 159*3089Swyllys break; 160*3089Swyllys case 'v': 161*3089Swyllys plc.validity_adjusttime = 162*3089Swyllys get_string(optarg_av, &rv); 163*3089Swyllys if (plc.validity_adjusttime == NULL) { 164*3089Swyllys (void) fprintf(stderr, 165*3089Swyllys gettext("Error time input.\n")); 166*3089Swyllys } else { 167*3089Swyllys uint32_t adj; 168*3089Swyllys /* for syntax checking */ 169*3089Swyllys if (str2lifetime( 170*3089Swyllys plc.validity_adjusttime, 171*3089Swyllys &adj) < 0) { 172*3089Swyllys (void) fprintf(stderr, 173*3089Swyllys gettext("Error time " 174*3089Swyllys "input.\n")); 175*3089Swyllys rv = KC_ERR_USAGE; 176*3089Swyllys } else { 177*3089Swyllys flags |= KC_VALIDITY_ADJUSTTIME; 178*3089Swyllys } 179*3089Swyllys } 180*3089Swyllys break; 181*3089Swyllys case 't': 182*3089Swyllys plc.ta_name = get_string(optarg_av, &rv); 183*3089Swyllys if (plc.ta_name == NULL) { 184*3089Swyllys (void) fprintf(stderr, 185*3089Swyllys gettext("Error name input.\n")); 186*3089Swyllys } else { 187*3089Swyllys KMF_X509_NAME taDN; 188*3089Swyllys /* for syntax checking */ 189*3089Swyllys if (KMF_DNParser(plc.ta_name, 190*3089Swyllys &taDN) != KMF_OK) { 191*3089Swyllys (void) fprintf(stderr, 192*3089Swyllys gettext("Error name " 193*3089Swyllys "input.\n")); 194*3089Swyllys rv = KC_ERR_USAGE; 195*3089Swyllys } else { 196*3089Swyllys KMF_FreeDN(&taDN); 197*3089Swyllys flags |= KC_TA_NAME; 198*3089Swyllys } 199*3089Swyllys } 200*3089Swyllys break; 201*3089Swyllys case 's': 202*3089Swyllys plc.ta_serial = get_string(optarg_av, &rv); 203*3089Swyllys if (plc.ta_serial == NULL) { 204*3089Swyllys (void) fprintf(stderr, 205*3089Swyllys gettext("Error serial input.\n")); 206*3089Swyllys } else { 207*3089Swyllys uchar_t *bytes = NULL; 208*3089Swyllys size_t bytelen; 209*3089Swyllys 210*3089Swyllys ret = KMF_HexString2Bytes( 211*3089Swyllys (uchar_t *)plc.ta_serial, 212*3089Swyllys &bytes, &bytelen); 213*3089Swyllys if (ret != KMF_OK || bytes == NULL) { 214*3089Swyllys (void) fprintf(stderr, 215*3089Swyllys gettext("serial number " 216*3089Swyllys "must be specified as a " 217*3089Swyllys "hex number " 218*3089Swyllys "(ex: 0x0102030405" 219*3089Swyllys "ffeeddee)\n")); 220*3089Swyllys rv = KC_ERR_USAGE; 221*3089Swyllys break; 222*3089Swyllys } 223*3089Swyllys if (bytes != NULL) 224*3089Swyllys free(bytes); 225*3089Swyllys flags |= KC_TA_SERIAL; 226*3089Swyllys } 227*3089Swyllys break; 228*3089Swyllys case 'o': 229*3089Swyllys plc.VAL_OCSP_RESPONDER_URI = 230*3089Swyllys get_string(optarg_av, &rv); 231*3089Swyllys if (plc.VAL_OCSP_RESPONDER_URI == NULL) { 232*3089Swyllys (void) fprintf(stderr, 233*3089Swyllys gettext("Error responder " 234*3089Swyllys "input.\n")); 235*3089Swyllys } else { 236*3089Swyllys flags |= KC_OCSP_RESPONDER_URI; 237*3089Swyllys ocsp_set_attr++; 238*3089Swyllys } 239*3089Swyllys break; 240*3089Swyllys case 'P': 241*3089Swyllys plc.VAL_OCSP_PROXY = get_string(optarg_av, &rv); 242*3089Swyllys if (plc.VAL_OCSP_PROXY == NULL) { 243*3089Swyllys (void) fprintf(stderr, 244*3089Swyllys gettext("Error proxy input.\n")); 245*3089Swyllys } else { 246*3089Swyllys flags |= KC_OCSP_PROXY; 247*3089Swyllys ocsp_set_attr++; 248*3089Swyllys } 249*3089Swyllys break; 250*3089Swyllys case 'r': 251*3089Swyllys plc.VAL_OCSP_URI_FROM_CERT = 252*3089Swyllys get_boolean(optarg_av); 253*3089Swyllys if (plc.VAL_OCSP_URI_FROM_CERT == -1) { 254*3089Swyllys (void) fprintf(stderr, 255*3089Swyllys gettext("Error boolean input.\n")); 256*3089Swyllys rv = KC_ERR_USAGE; 257*3089Swyllys } else { 258*3089Swyllys flags |= KC_OCSP_URI_FROM_CERT; 259*3089Swyllys ocsp_set_attr++; 260*3089Swyllys } 261*3089Swyllys break; 262*3089Swyllys case 'T': 263*3089Swyllys plc.VAL_OCSP_RESP_LIFETIME = 264*3089Swyllys get_string(optarg_av, &rv); 265*3089Swyllys if (plc.VAL_OCSP_RESP_LIFETIME == NULL) { 266*3089Swyllys (void) fprintf(stderr, 267*3089Swyllys gettext("Error time input.\n")); 268*3089Swyllys } else { 269*3089Swyllys uint32_t adj; 270*3089Swyllys /* for syntax checking */ 271*3089Swyllys if (str2lifetime( 272*3089Swyllys plc.VAL_OCSP_RESP_LIFETIME, 273*3089Swyllys &adj) < 0) { 274*3089Swyllys (void) fprintf(stderr, 275*3089Swyllys gettext("Error time " 276*3089Swyllys "input.\n")); 277*3089Swyllys rv = KC_ERR_USAGE; 278*3089Swyllys } else { 279*3089Swyllys flags |= KC_OCSP_RESP_LIFETIME; 280*3089Swyllys ocsp_set_attr++; 281*3089Swyllys } 282*3089Swyllys } 283*3089Swyllys break; 284*3089Swyllys case 'R': 285*3089Swyllys plc.VAL_OCSP_IGNORE_RESP_SIGN = 286*3089Swyllys get_boolean(optarg_av); 287*3089Swyllys if (plc.VAL_OCSP_IGNORE_RESP_SIGN == -1) { 288*3089Swyllys (void) fprintf(stderr, 289*3089Swyllys gettext("Error boolean input.\n")); 290*3089Swyllys rv = KC_ERR_USAGE; 291*3089Swyllys } else { 292*3089Swyllys flags |= KC_OCSP_IGNORE_RESP_SIGN; 293*3089Swyllys ocsp_set_attr++; 294*3089Swyllys } 295*3089Swyllys break; 296*3089Swyllys case 'n': 297*3089Swyllys plc.VAL_OCSP_RESP_CERT_NAME = 298*3089Swyllys get_string(optarg_av, &rv); 299*3089Swyllys if (plc.VAL_OCSP_RESP_CERT_NAME == NULL) { 300*3089Swyllys (void) fprintf(stderr, 301*3089Swyllys gettext("Error name input.\n")); 302*3089Swyllys } else { 303*3089Swyllys KMF_X509_NAME respDN; 304*3089Swyllys /* for syntax checking */ 305*3089Swyllys if (KMF_DNParser( 306*3089Swyllys plc.VAL_OCSP_RESP_CERT_NAME, 307*3089Swyllys &respDN) != KMF_OK) { 308*3089Swyllys (void) fprintf(stderr, 309*3089Swyllys gettext("Error name " 310*3089Swyllys "input.\n")); 311*3089Swyllys rv = KC_ERR_USAGE; 312*3089Swyllys } else { 313*3089Swyllys KMF_FreeDN(&respDN); 314*3089Swyllys flags |= KC_OCSP_RESP_CERT_NAME; 315*3089Swyllys ocsp_set_attr++; 316*3089Swyllys } 317*3089Swyllys } 318*3089Swyllys break; 319*3089Swyllys case 'A': 320*3089Swyllys plc.VAL_OCSP_RESP_CERT_SERIAL = 321*3089Swyllys get_string(optarg_av, &rv); 322*3089Swyllys if (plc.VAL_OCSP_RESP_CERT_SERIAL == NULL) { 323*3089Swyllys (void) fprintf(stderr, 324*3089Swyllys gettext("Error serial input.\n")); 325*3089Swyllys } else { 326*3089Swyllys uchar_t *bytes = NULL; 327*3089Swyllys size_t bytelen; 328*3089Swyllys 329*3089Swyllys ret = KMF_HexString2Bytes((uchar_t *) 330*3089Swyllys plc.VAL_OCSP_RESP_CERT_SERIAL, 331*3089Swyllys &bytes, &bytelen); 332*3089Swyllys if (ret != KMF_OK || bytes == NULL) { 333*3089Swyllys (void) fprintf(stderr, 334*3089Swyllys gettext("serial number " 335*3089Swyllys "must be specified as a " 336*3089Swyllys "hex number " 337*3089Swyllys "(ex: 0x0102030405" 338*3089Swyllys "ffeeddee)\n")); 339*3089Swyllys rv = KC_ERR_USAGE; 340*3089Swyllys break; 341*3089Swyllys } 342*3089Swyllys if (bytes != NULL) 343*3089Swyllys free(bytes); 344*3089Swyllys flags |= KC_OCSP_RESP_CERT_SERIAL; 345*3089Swyllys ocsp_set_attr++; 346*3089Swyllys } 347*3089Swyllys break; 348*3089Swyllys case 'y': 349*3089Swyllys ocsp_none_opt = get_boolean(optarg_av); 350*3089Swyllys if (ocsp_none_opt == -1) { 351*3089Swyllys (void) fprintf(stderr, 352*3089Swyllys gettext("Error boolean input.\n")); 353*3089Swyllys rv = KC_ERR_USAGE; 354*3089Swyllys } else { 355*3089Swyllys flags |= KC_OCSP_NONE; 356*3089Swyllys } 357*3089Swyllys break; 358*3089Swyllys case 'c': 359*3089Swyllys plc.VAL_CRL_BASEFILENAME = 360*3089Swyllys get_string(optarg_av, &rv); 361*3089Swyllys if (plc.VAL_CRL_BASEFILENAME == NULL) { 362*3089Swyllys (void) fprintf(stderr, gettext( 363*3089Swyllys "Error basefilename input.\n")); 364*3089Swyllys } else { 365*3089Swyllys flags |= KC_CRL_BASEFILENAME; 366*3089Swyllys crl_set_attr++; 367*3089Swyllys } 368*3089Swyllys break; 369*3089Swyllys case 'I': 370*3089Swyllys plc.VAL_CRL_DIRECTORY = 371*3089Swyllys get_string(optarg_av, &rv); 372*3089Swyllys if (plc.VAL_CRL_DIRECTORY == NULL) { 373*3089Swyllys (void) fprintf(stderr, 374*3089Swyllys gettext("Error boolean input.\n")); 375*3089Swyllys } else { 376*3089Swyllys flags |= KC_CRL_DIRECTORY; 377*3089Swyllys crl_set_attr++; 378*3089Swyllys } 379*3089Swyllys break; 380*3089Swyllys case 'g': 381*3089Swyllys plc.VAL_CRL_GET_URI = get_boolean(optarg_av); 382*3089Swyllys if (plc.VAL_CRL_GET_URI == -1) { 383*3089Swyllys (void) fprintf(stderr, 384*3089Swyllys gettext("Error boolean input.\n")); 385*3089Swyllys rv = KC_ERR_USAGE; 386*3089Swyllys } else { 387*3089Swyllys flags |= KC_CRL_GET_URI; 388*3089Swyllys crl_set_attr++; 389*3089Swyllys } 390*3089Swyllys break; 391*3089Swyllys case 'X': 392*3089Swyllys plc.VAL_CRL_PROXY = get_string(optarg_av, &rv); 393*3089Swyllys if (plc.VAL_CRL_PROXY == NULL) { 394*3089Swyllys (void) fprintf(stderr, 395*3089Swyllys gettext("Error proxy input.\n")); 396*3089Swyllys } else { 397*3089Swyllys flags |= KC_CRL_PROXY; 398*3089Swyllys crl_set_attr++; 399*3089Swyllys } 400*3089Swyllys break; 401*3089Swyllys case 'S': 402*3089Swyllys plc.VAL_CRL_IGNORE_SIGN = 403*3089Swyllys get_boolean(optarg_av); 404*3089Swyllys if (plc.VAL_CRL_IGNORE_SIGN == -1) { 405*3089Swyllys (void) fprintf(stderr, 406*3089Swyllys gettext("Error boolean input.\n")); 407*3089Swyllys rv = KC_ERR_USAGE; 408*3089Swyllys } else { 409*3089Swyllys flags |= KC_CRL_IGNORE_SIGN; 410*3089Swyllys crl_set_attr++; 411*3089Swyllys } 412*3089Swyllys break; 413*3089Swyllys case 'D': 414*3089Swyllys plc.VAL_CRL_IGNORE_DATE = 415*3089Swyllys get_boolean(optarg_av); 416*3089Swyllys if (plc.VAL_CRL_IGNORE_DATE == -1) { 417*3089Swyllys (void) fprintf(stderr, 418*3089Swyllys gettext("Error boolean input.\n")); 419*3089Swyllys rv = KC_ERR_USAGE; 420*3089Swyllys } else { 421*3089Swyllys flags |= KC_CRL_IGNORE_DATE; 422*3089Swyllys crl_set_attr++; 423*3089Swyllys } 424*3089Swyllys break; 425*3089Swyllys case 'z': 426*3089Swyllys crl_none_opt = get_boolean(optarg_av); 427*3089Swyllys if (crl_none_opt == -1) { 428*3089Swyllys (void) fprintf(stderr, 429*3089Swyllys gettext("Error boolean input.\n")); 430*3089Swyllys rv = KC_ERR_USAGE; 431*3089Swyllys } else { 432*3089Swyllys flags |= KC_CRL_NONE; 433*3089Swyllys } 434*3089Swyllys break; 435*3089Swyllys case 'u': 436*3089Swyllys plc.ku_bits = parseKUlist(optarg_av); 437*3089Swyllys if (plc.ku_bits == 0) { 438*3089Swyllys (void) fprintf(stderr, gettext( 439*3089Swyllys "Error keyusage input.\n")); 440*3089Swyllys rv = KC_ERR_USAGE; 441*3089Swyllys } else { 442*3089Swyllys flags |= KC_KEYUSAGE; 443*3089Swyllys } 444*3089Swyllys break; 445*3089Swyllys case 'Y': 446*3089Swyllys ku_none_opt = get_boolean(optarg_av); 447*3089Swyllys if (ku_none_opt == -1) { 448*3089Swyllys (void) fprintf(stderr, 449*3089Swyllys gettext("Error boolean input.\n")); 450*3089Swyllys rv = KC_ERR_USAGE; 451*3089Swyllys } else { 452*3089Swyllys flags |= KC_KEYUSAGE_NONE; 453*3089Swyllys } 454*3089Swyllys break; 455*3089Swyllys case 'E': 456*3089Swyllys if (parseEKUNames(optarg_av, &plc) != 0) { 457*3089Swyllys (void) fprintf(stderr, 458*3089Swyllys gettext("Error EKU input.\n")); 459*3089Swyllys rv = KC_ERR_USAGE; 460*3089Swyllys } else { 461*3089Swyllys flags |= KC_EKUS; 462*3089Swyllys } 463*3089Swyllys break; 464*3089Swyllys case 'O': 465*3089Swyllys if (parseEKUOIDs(optarg_av, &plc) != 0) { 466*3089Swyllys (void) fprintf(stderr, 467*3089Swyllys gettext("Error EKU OID input.\n")); 468*3089Swyllys rv = KC_ERR_USAGE; 469*3089Swyllys } else { 470*3089Swyllys flags |= KC_EKUS; 471*3089Swyllys } 472*3089Swyllys break; 473*3089Swyllys case 'Z': 474*3089Swyllys eku_none_opt = get_boolean(optarg_av); 475*3089Swyllys if (eku_none_opt == -1) { 476*3089Swyllys (void) fprintf(stderr, 477*3089Swyllys gettext("Error boolean input.\n")); 478*3089Swyllys rv = KC_ERR_USAGE; 479*3089Swyllys } else { 480*3089Swyllys flags |= KC_EKUS_NONE; 481*3089Swyllys } 482*3089Swyllys break; 483*3089Swyllys default: 484*3089Swyllys (void) fprintf(stderr, 485*3089Swyllys gettext("Error input option.\n")); 486*3089Swyllys rv = KC_ERR_USAGE; 487*3089Swyllys break; 488*3089Swyllys } 489*3089Swyllys if (rv != KC_OK) 490*3089Swyllys goto out; 491*3089Swyllys } 492*3089Swyllys 493*3089Swyllys /* No additional args allowed. */ 494*3089Swyllys argc -= optind_av; 495*3089Swyllys if (argc) { 496*3089Swyllys (void) fprintf(stderr, 497*3089Swyllys gettext("Error input option\n")); 498*3089Swyllys rv = KC_ERR_USAGE; 499*3089Swyllys goto out; 500*3089Swyllys } 501*3089Swyllys 502*3089Swyllys if (filename == NULL) { 503*3089Swyllys filename = strdup(KMF_DEFAULT_POLICY_FILE); 504*3089Swyllys if (filename == NULL) { 505*3089Swyllys rv = KC_ERR_MEMORY; 506*3089Swyllys goto out; 507*3089Swyllys } 508*3089Swyllys } 509*3089Swyllys 510*3089Swyllys /* 511*3089Swyllys * Must have a policy name. The policy name can not be default 512*3089Swyllys * if using the default policy file. 513*3089Swyllys */ 514*3089Swyllys if (plc.name == NULL) { 515*3089Swyllys (void) fprintf(stderr, 516*3089Swyllys gettext("You must specify a policy name.\n")); 517*3089Swyllys rv = KC_ERR_USAGE; 518*3089Swyllys goto out; 519*3089Swyllys } else if (strcmp(filename, KMF_DEFAULT_POLICY_FILE) == 0 && 520*3089Swyllys strcmp(plc.name, KMF_DEFAULT_POLICY_NAME) == 0) { 521*3089Swyllys (void) fprintf(stderr, 522*3089Swyllys gettext("Can not modify the default policy in the default " 523*3089Swyllys "policy file.\n")); 524*3089Swyllys rv = KC_ERR_USAGE; 525*3089Swyllys goto out; 526*3089Swyllys } 527*3089Swyllys 528*3089Swyllys /* Check the access permission of the policy DB */ 529*3089Swyllys if (access(filename, W_OK) < 0) { 530*3089Swyllys int err = errno; 531*3089Swyllys (void) fprintf(stderr, 532*3089Swyllys gettext("Cannot access \"%s\" for modify - %s\n"), 533*3089Swyllys filename, strerror(err)); 534*3089Swyllys rv = KC_ERR_ACCESS; 535*3089Swyllys goto out; 536*3089Swyllys } 537*3089Swyllys 538*3089Swyllys /* Try to load the named policy from the DB */ 539*3089Swyllys ret = KMF_GetPolicy(filename, plc.name, &oplc); 540*3089Swyllys if (ret != KMF_OK) { 541*3089Swyllys (void) fprintf(stderr, 542*3089Swyllys gettext("Error loading policy \"%s\" from %s\n"), filename, 543*3089Swyllys plc.name); 544*3089Swyllys return (KC_ERR_FIND_POLICY); 545*3089Swyllys } 546*3089Swyllys 547*3089Swyllys /* Update the general policy attributes. */ 548*3089Swyllys if (flags & KC_IGNORE_DATE) 549*3089Swyllys oplc.ignore_date = plc.ignore_date; 550*3089Swyllys 551*3089Swyllys if (flags & KC_IGNORE_UNKNOWN_EKUS) 552*3089Swyllys oplc.ignore_unknown_ekus = plc.ignore_unknown_ekus; 553*3089Swyllys 554*3089Swyllys if (flags & KC_IGNORE_TRUST_ANCHOR) 555*3089Swyllys oplc.ignore_trust_anchor = plc.ignore_trust_anchor; 556*3089Swyllys 557*3089Swyllys if (flags & KC_VALIDITY_ADJUSTTIME) { 558*3089Swyllys if (oplc.validity_adjusttime) 559*3089Swyllys free(oplc.validity_adjusttime); 560*3089Swyllys oplc.validity_adjusttime = 561*3089Swyllys plc.validity_adjusttime; 562*3089Swyllys } 563*3089Swyllys 564*3089Swyllys if (flags & KC_TA_NAME) { 565*3089Swyllys if (oplc.ta_name) 566*3089Swyllys free(oplc.ta_name); 567*3089Swyllys oplc.ta_name = plc.ta_name; 568*3089Swyllys } 569*3089Swyllys if (flags & KC_TA_SERIAL) { 570*3089Swyllys if (oplc.ta_serial) 571*3089Swyllys free(oplc.ta_serial); 572*3089Swyllys oplc.ta_serial = plc.ta_serial; 573*3089Swyllys } 574*3089Swyllys 575*3089Swyllys /* Update the OCSP policy */ 576*3089Swyllys if (ocsp_none_opt == B_TRUE) { 577*3089Swyllys if (ocsp_set_attr > 0) { 578*3089Swyllys (void) fprintf(stderr, 579*3089Swyllys gettext("Can not set ocsp-none=true and other " 580*3089Swyllys "OCSP attributes at the same time.\n")); 581*3089Swyllys rv = KC_ERR_USAGE; 582*3089Swyllys goto out; 583*3089Swyllys } 584*3089Swyllys 585*3089Swyllys /* 586*3089Swyllys * If the original policy does not have OCSP checking, 587*3089Swyllys * then we do not need to do anything. If the original 588*3089Swyllys * policy has the OCSP checking, then we need to release the 589*3089Swyllys * space of OCSP attributes and turn the OCSP checking off. 590*3089Swyllys */ 591*3089Swyllys if (oplc.revocation & KMF_REVOCATION_METHOD_OCSP) { 592*3089Swyllys if (oplc.VAL_OCSP_BASIC.responderURI) { 593*3089Swyllys free(oplc.VAL_OCSP_BASIC.responderURI); 594*3089Swyllys oplc.VAL_OCSP_BASIC.responderURI = NULL; 595*3089Swyllys } 596*3089Swyllys 597*3089Swyllys if (oplc.VAL_OCSP_BASIC.proxy) { 598*3089Swyllys free(oplc.VAL_OCSP_BASIC.proxy); 599*3089Swyllys oplc.VAL_OCSP_BASIC.proxy = NULL; 600*3089Swyllys } 601*3089Swyllys 602*3089Swyllys if (oplc.VAL_OCSP_BASIC.response_lifetime) { 603*3089Swyllys free(oplc.VAL_OCSP_BASIC.response_lifetime); 604*3089Swyllys oplc.VAL_OCSP_BASIC.response_lifetime = NULL; 605*3089Swyllys } 606*3089Swyllys 607*3089Swyllys if (flags & KC_OCSP_RESP_CERT_NAME) { 608*3089Swyllys free(oplc.VAL_OCSP_RESP_CERT.name); 609*3089Swyllys oplc.VAL_OCSP_RESP_CERT.name = NULL; 610*3089Swyllys } 611*3089Swyllys 612*3089Swyllys if (flags & KC_OCSP_RESP_CERT_SERIAL) { 613*3089Swyllys free(oplc.VAL_OCSP_RESP_CERT.serial); 614*3089Swyllys oplc.VAL_OCSP_RESP_CERT.serial = NULL; 615*3089Swyllys } 616*3089Swyllys 617*3089Swyllys /* Turn off the OCSP checking */ 618*3089Swyllys oplc.revocation &= ~KMF_REVOCATION_METHOD_OCSP; 619*3089Swyllys } 620*3089Swyllys 621*3089Swyllys } else { 622*3089Swyllys /* 623*3089Swyllys * If the "ocsp-none" option is not set or is set to false, 624*3089Swyllys * then we only need to do the modification if there is at 625*3089Swyllys * least one OCSP attribute is specified. 626*3089Swyllys */ 627*3089Swyllys if (ocsp_set_attr > 0) { 628*3089Swyllys if (flags & KC_OCSP_RESPONDER_URI) { 629*3089Swyllys if (oplc.VAL_OCSP_RESPONDER_URI) 630*3089Swyllys free(oplc.VAL_OCSP_RESPONDER_URI); 631*3089Swyllys oplc.VAL_OCSP_RESPONDER_URI = 632*3089Swyllys plc.VAL_OCSP_RESPONDER_URI; 633*3089Swyllys } 634*3089Swyllys 635*3089Swyllys if (flags & KC_OCSP_PROXY) { 636*3089Swyllys if (oplc.VAL_OCSP_PROXY) 637*3089Swyllys free(oplc.VAL_OCSP_PROXY); 638*3089Swyllys oplc.VAL_OCSP_PROXY = plc.VAL_OCSP_PROXY; 639*3089Swyllys } 640*3089Swyllys 641*3089Swyllys if (flags & KC_OCSP_URI_FROM_CERT) 642*3089Swyllys oplc.VAL_OCSP_URI_FROM_CERT = 643*3089Swyllys plc.VAL_OCSP_URI_FROM_CERT; 644*3089Swyllys 645*3089Swyllys if (flags & KC_OCSP_RESP_LIFETIME) { 646*3089Swyllys if (oplc.VAL_OCSP_RESP_LIFETIME) 647*3089Swyllys free(oplc.VAL_OCSP_RESP_LIFETIME); 648*3089Swyllys oplc.VAL_OCSP_RESP_LIFETIME = 649*3089Swyllys plc.VAL_OCSP_RESP_LIFETIME; 650*3089Swyllys } 651*3089Swyllys 652*3089Swyllys if (flags & KC_OCSP_IGNORE_RESP_SIGN) 653*3089Swyllys oplc.VAL_OCSP_IGNORE_RESP_SIGN = 654*3089Swyllys plc.VAL_OCSP_IGNORE_RESP_SIGN; 655*3089Swyllys 656*3089Swyllys if (flags & KC_OCSP_RESP_CERT_NAME) { 657*3089Swyllys if (oplc.VAL_OCSP_RESP_CERT_NAME) 658*3089Swyllys free(oplc.VAL_OCSP_RESP_CERT_NAME); 659*3089Swyllys oplc.VAL_OCSP_RESP_CERT_NAME = 660*3089Swyllys plc.VAL_OCSP_RESP_CERT_NAME; 661*3089Swyllys } 662*3089Swyllys 663*3089Swyllys if (flags & KC_OCSP_RESP_CERT_SERIAL) { 664*3089Swyllys if (oplc.VAL_OCSP_RESP_CERT_SERIAL) 665*3089Swyllys free(oplc.VAL_OCSP_RESP_CERT_SERIAL); 666*3089Swyllys oplc.VAL_OCSP_RESP_CERT_SERIAL = 667*3089Swyllys plc.VAL_OCSP_RESP_CERT_SERIAL; 668*3089Swyllys } 669*3089Swyllys 670*3089Swyllys if (oplc.VAL_OCSP_RESP_CERT_NAME != NULL && 671*3089Swyllys oplc.VAL_OCSP_RESP_CERT_SERIAL != NULL) 672*3089Swyllys oplc.VAL_OCSP.has_resp_cert = B_TRUE; 673*3089Swyllys else 674*3089Swyllys oplc.VAL_OCSP.has_resp_cert = B_FALSE; 675*3089Swyllys 676*3089Swyllys /* Turn on the OCSP checking */ 677*3089Swyllys oplc.revocation |= KMF_REVOCATION_METHOD_OCSP; 678*3089Swyllys } 679*3089Swyllys } 680*3089Swyllys 681*3089Swyllys /* Update the CRL policy */ 682*3089Swyllys if (crl_none_opt == B_TRUE) { 683*3089Swyllys if (crl_set_attr > 0) { 684*3089Swyllys (void) fprintf(stderr, 685*3089Swyllys gettext("Can not set crl-none=true and other CRL " 686*3089Swyllys "attributes at the same time.\n")); 687*3089Swyllys rv = KC_ERR_USAGE; 688*3089Swyllys goto out; 689*3089Swyllys } 690*3089Swyllys 691*3089Swyllys /* 692*3089Swyllys * If the original policy does not have CRL checking, 693*3089Swyllys * then we do not need to do anything. If the original 694*3089Swyllys * policy has the CRL checking, then we need to release the 695*3089Swyllys * space of CRL attributes and turn the CRL checking off. 696*3089Swyllys */ 697*3089Swyllys if (oplc.revocation & KMF_REVOCATION_METHOD_CRL) { 698*3089Swyllys if (oplc.VAL_CRL_BASEFILENAME) { 699*3089Swyllys free(oplc.VAL_CRL_BASEFILENAME); 700*3089Swyllys oplc.VAL_CRL_BASEFILENAME = NULL; 701*3089Swyllys } 702*3089Swyllys 703*3089Swyllys if (oplc.VAL_CRL_DIRECTORY) { 704*3089Swyllys free(oplc.VAL_CRL_DIRECTORY); 705*3089Swyllys oplc.VAL_CRL_DIRECTORY = NULL; 706*3089Swyllys } 707*3089Swyllys 708*3089Swyllys if (oplc.VAL_CRL_PROXY) { 709*3089Swyllys free(oplc.VAL_CRL_PROXY); 710*3089Swyllys oplc.VAL_CRL_PROXY = NULL; 711*3089Swyllys } 712*3089Swyllys 713*3089Swyllys /* Turn off the CRL checking */ 714*3089Swyllys oplc.revocation &= ~KMF_REVOCATION_METHOD_CRL; 715*3089Swyllys } 716*3089Swyllys } else { 717*3089Swyllys /* 718*3089Swyllys * If the "ocsp-none" option is not set or is set to false, 719*3089Swyllys * then we only need to do the modification if there is at 720*3089Swyllys * least one CRL attribute is specified. 721*3089Swyllys */ 722*3089Swyllys if (crl_set_attr > 0) { 723*3089Swyllys if (flags & KC_CRL_BASEFILENAME) { 724*3089Swyllys if (oplc.VAL_CRL_BASEFILENAME) 725*3089Swyllys free(oplc.VAL_CRL_BASEFILENAME); 726*3089Swyllys oplc.VAL_CRL_BASEFILENAME = 727*3089Swyllys plc.VAL_CRL_BASEFILENAME; 728*3089Swyllys } 729*3089Swyllys 730*3089Swyllys if (flags & KC_CRL_DIRECTORY) { 731*3089Swyllys if (oplc.VAL_CRL_DIRECTORY) 732*3089Swyllys free(oplc.VAL_CRL_DIRECTORY); 733*3089Swyllys oplc.VAL_CRL_DIRECTORY = plc.VAL_CRL_DIRECTORY; 734*3089Swyllys } 735*3089Swyllys 736*3089Swyllys if (flags & KC_CRL_GET_URI) { 737*3089Swyllys oplc.VAL_CRL_GET_URI = plc.VAL_CRL_GET_URI; 738*3089Swyllys } 739*3089Swyllys 740*3089Swyllys if (flags & KC_CRL_PROXY) { 741*3089Swyllys if (oplc.VAL_CRL_PROXY) 742*3089Swyllys free(oplc.VAL_CRL_PROXY); 743*3089Swyllys oplc.VAL_CRL_PROXY = plc.VAL_CRL_PROXY; 744*3089Swyllys } 745*3089Swyllys 746*3089Swyllys if (flags & KC_CRL_IGNORE_SIGN) { 747*3089Swyllys oplc.VAL_CRL_IGNORE_SIGN = 748*3089Swyllys plc.VAL_CRL_IGNORE_SIGN; 749*3089Swyllys } 750*3089Swyllys 751*3089Swyllys if (flags & KC_CRL_IGNORE_DATE) { 752*3089Swyllys oplc.VAL_CRL_IGNORE_DATE = 753*3089Swyllys plc.VAL_CRL_IGNORE_DATE; 754*3089Swyllys } 755*3089Swyllys 756*3089Swyllys /* Turn on the CRL checking */ 757*3089Swyllys oplc.revocation |= KMF_REVOCATION_METHOD_CRL; 758*3089Swyllys } 759*3089Swyllys } 760*3089Swyllys 761*3089Swyllys /* Update the Key Usage */ 762*3089Swyllys if (ku_none_opt == B_TRUE) { 763*3089Swyllys if (flags & KC_KEYUSAGE) { 764*3089Swyllys (void) fprintf(stderr, 765*3089Swyllys gettext("Can not set keyusage-none=true and " 766*3089Swyllys "modify the keyusage value at the same time.\n")); 767*3089Swyllys rv = KC_ERR_USAGE; 768*3089Swyllys goto out; 769*3089Swyllys } 770*3089Swyllys 771*3089Swyllys oplc.ku_bits = 0; 772*3089Swyllys } else { 773*3089Swyllys /* 774*3089Swyllys * If the "keyusage-none" option is not set or is set to 775*3089Swyllys * false, then we only need to do the modification if 776*3089Swyllys * the keyusage value is specified. 777*3089Swyllys */ 778*3089Swyllys if (flags & KC_KEYUSAGE) 779*3089Swyllys oplc.ku_bits = plc.ku_bits; 780*3089Swyllys } 781*3089Swyllys 782*3089Swyllys 783*3089Swyllys /* Update the Extended Key Usage */ 784*3089Swyllys if (eku_none_opt == B_TRUE) { 785*3089Swyllys if (flags & KC_EKUS) { 786*3089Swyllys (void) fprintf(stderr, 787*3089Swyllys gettext("Can not set eku-none=true and modify " 788*3089Swyllys "EKU values at the same time.\n")); 789*3089Swyllys rv = KC_ERR_USAGE; 790*3089Swyllys goto out; 791*3089Swyllys } 792*3089Swyllys 793*3089Swyllys /* Release current EKU list (if any) */ 794*3089Swyllys if (oplc.eku_set.eku_count > 0) { 795*3089Swyllys KMF_FreeEKUPolicy(&oplc.eku_set); 796*3089Swyllys oplc.eku_set.eku_count = 0; 797*3089Swyllys oplc.eku_set.ekulist = NULL; 798*3089Swyllys } 799*3089Swyllys } else { 800*3089Swyllys /* 801*3089Swyllys * If the "eku-none" option is not set or is set to false, 802*3089Swyllys * then we only need to do the modification if either 803*3089Swyllys * "ekuname" or "ekuoids" is specified. 804*3089Swyllys */ 805*3089Swyllys if (flags & KC_EKUS) { 806*3089Swyllys /* Release current EKU list (if any) */ 807*3089Swyllys KMF_FreeEKUPolicy(&oplc.eku_set); 808*3089Swyllys oplc.eku_set = plc.eku_set; 809*3089Swyllys } 810*3089Swyllys } 811*3089Swyllys 812*3089Swyllys /* Do a sanity check on the modified policy */ 813*3089Swyllys ret = KMF_VerifyPolicy(&oplc); 814*3089Swyllys if (ret != KMF_OK) { 815*3089Swyllys print_sanity_error(ret); 816*3089Swyllys rv = KC_ERR_VERIFY_POLICY; 817*3089Swyllys goto out; 818*3089Swyllys } 819*3089Swyllys 820*3089Swyllys /* The modify operation is a delete followed by an add */ 821*3089Swyllys ret = KMF_DeletePolicyFromDB(oplc.name, filename); 822*3089Swyllys if (ret != KMF_OK) { 823*3089Swyllys rv = KC_ERR_DELETE_POLICY; 824*3089Swyllys goto out; 825*3089Swyllys } 826*3089Swyllys 827*3089Swyllys /* 828*3089Swyllys * Now add the modified policy back to the DB. 829*3089Swyllys */ 830*3089Swyllys ret = KMF_AddPolicyToDB(&oplc, filename, B_FALSE); 831*3089Swyllys if (ret != KMF_OK) { 832*3089Swyllys (void) fprintf(stderr, 833*3089Swyllys gettext("Error adding policy to database: 0x%04x\n"), ret); 834*3089Swyllys rv = KC_ERR_ADD_POLICY; 835*3089Swyllys goto out; 836*3089Swyllys } 837*3089Swyllys 838*3089Swyllys out: 839*3089Swyllys if (filename != NULL) 840*3089Swyllys free(filename); 841*3089Swyllys 842*3089Swyllys KMF_FreePolicyRecord(&oplc); 843*3089Swyllys 844*3089Swyllys return (rv); 845*3089Swyllys } 846