1*99ebb4caSwyllys /* 2*99ebb4caSwyllys * CDDL HEADER START 3*99ebb4caSwyllys * 4*99ebb4caSwyllys * The contents of this file are subject to the terms of the 5*99ebb4caSwyllys * Common Development and Distribution License (the "License"). 6*99ebb4caSwyllys * You may not use this file except in compliance with the License. 7*99ebb4caSwyllys * 8*99ebb4caSwyllys * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*99ebb4caSwyllys * or http://www.opensolaris.org/os/licensing. 10*99ebb4caSwyllys * See the License for the specific language governing permissions 11*99ebb4caSwyllys * and limitations under the License. 12*99ebb4caSwyllys * 13*99ebb4caSwyllys * When distributing Covered Code, include this CDDL HEADER in each 14*99ebb4caSwyllys * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*99ebb4caSwyllys * If applicable, add the following below this CDDL HEADER, with the 16*99ebb4caSwyllys * fields enclosed by brackets "[]" replaced with your own identifying 17*99ebb4caSwyllys * information: Portions Copyright [yyyy] [name of copyright owner] 18*99ebb4caSwyllys * 19*99ebb4caSwyllys * CDDL HEADER END 20*99ebb4caSwyllys * 21*99ebb4caSwyllys * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 22*99ebb4caSwyllys * Use is subject to license terms. 23*99ebb4caSwyllys */ 24*99ebb4caSwyllys 25*99ebb4caSwyllys #pragma ident "%Z%%M% %I% %E% SMI" 26*99ebb4caSwyllys 27*99ebb4caSwyllys #include <stdlib.h> 28*99ebb4caSwyllys #include <ctype.h> 29*99ebb4caSwyllys #include <strings.h> 30*99ebb4caSwyllys #include <unistd.h> 31*99ebb4caSwyllys #include <errno.h> 32*99ebb4caSwyllys #include <sys/param.h> 33*99ebb4caSwyllys #include <sys/stat.h> 34*99ebb4caSwyllys 35*99ebb4caSwyllys #include <kmfapiP.h> 36*99ebb4caSwyllys #include <libxml/tree.h> 37*99ebb4caSwyllys #include <libxml/parser.h> 38*99ebb4caSwyllys 39*99ebb4caSwyllys typedef struct { 40*99ebb4caSwyllys char *ekuname; 41*99ebb4caSwyllys KMF_OID *oid; 42*99ebb4caSwyllys } EKUName2OID; 43*99ebb4caSwyllys 44*99ebb4caSwyllys static EKUName2OID EKUList[] = { 45*99ebb4caSwyllys {"serverAuth", (KMF_OID *)&KMFOID_PKIX_KP_ServerAuth}, 46*99ebb4caSwyllys {"clientAuth", (KMF_OID *)&KMFOID_PKIX_KP_ClientAuth}, 47*99ebb4caSwyllys {"codeSigning", (KMF_OID *)&KMFOID_PKIX_KP_CodeSigning}, 48*99ebb4caSwyllys {"emailProtection", (KMF_OID *)&KMFOID_PKIX_KP_EmailProtection}, 49*99ebb4caSwyllys {"ipsecEndSystem", (KMF_OID *)&KMFOID_PKIX_KP_IPSecEndSystem}, 50*99ebb4caSwyllys {"ipsecTunnel", (KMF_OID *)&KMFOID_PKIX_KP_IPSecTunnel}, 51*99ebb4caSwyllys {"ipsecUser", (KMF_OID *)&KMFOID_PKIX_KP_IPSecUser}, 52*99ebb4caSwyllys {"timeStamping", (KMF_OID *)&KMFOID_PKIX_KP_TimeStamping}, 53*99ebb4caSwyllys {"OCSPSigning", (KMF_OID *)&KMFOID_PKIX_KP_OCSPSigning} 54*99ebb4caSwyllys }; 55*99ebb4caSwyllys 56*99ebb4caSwyllys static int num_ekus = sizeof (EKUList) / sizeof (EKUName2OID); 57*99ebb4caSwyllys 58*99ebb4caSwyllys static void 59*99ebb4caSwyllys addFormatting(xmlNodePtr parent, char *text) 60*99ebb4caSwyllys { 61*99ebb4caSwyllys xmlNodePtr snode; 62*99ebb4caSwyllys 63*99ebb4caSwyllys if (parent == NULL || text == NULL) 64*99ebb4caSwyllys return; 65*99ebb4caSwyllys 66*99ebb4caSwyllys snode = xmlNewText((const xmlChar *)text); 67*99ebb4caSwyllys if (snode != NULL) { 68*99ebb4caSwyllys xmlAddChild(parent, snode); 69*99ebb4caSwyllys } 70*99ebb4caSwyllys } 71*99ebb4caSwyllys 72*99ebb4caSwyllys static void 73*99ebb4caSwyllys parseOCSPValidation(xmlNodePtr node, KMF_VALIDATION_POLICY *vinfo) 74*99ebb4caSwyllys { 75*99ebb4caSwyllys xmlNodePtr n; 76*99ebb4caSwyllys char *c; 77*99ebb4caSwyllys n = node->children; 78*99ebb4caSwyllys while (n != NULL) { 79*99ebb4caSwyllys if (!xmlStrcmp((const xmlChar *)n->name, 80*99ebb4caSwyllys (const xmlChar *)KMF_OCSP_BASIC_ELEMENT)) { 81*99ebb4caSwyllys 82*99ebb4caSwyllys vinfo->ocsp_info.basic.responderURI = 83*99ebb4caSwyllys (char *)xmlGetProp(n, 84*99ebb4caSwyllys (const xmlChar *)KMF_OCSP_RESPONDER_ATTR); 85*99ebb4caSwyllys 86*99ebb4caSwyllys vinfo->ocsp_info.basic.proxy = (char *)xmlGetProp(n, 87*99ebb4caSwyllys (const xmlChar *)KMF_OCSP_PROXY_ATTR); 88*99ebb4caSwyllys 89*99ebb4caSwyllys c = (char *)xmlGetProp(n, 90*99ebb4caSwyllys (const xmlChar *)KMF_OCSP_URI_ATTR); 91*99ebb4caSwyllys if (c != NULL && !strcasecmp(c, "true")) { 92*99ebb4caSwyllys vinfo->ocsp_info.basic.uri_from_cert = 1; 93*99ebb4caSwyllys xmlFree(c); 94*99ebb4caSwyllys } 95*99ebb4caSwyllys 96*99ebb4caSwyllys vinfo->ocsp_info.basic.response_lifetime = 97*99ebb4caSwyllys (char *)xmlGetProp(n, 98*99ebb4caSwyllys (const xmlChar *)KMF_OCSP_RESPONSE_LIFETIME_ATTR); 99*99ebb4caSwyllys 100*99ebb4caSwyllys c = (char *)xmlGetProp(n, 101*99ebb4caSwyllys (const xmlChar *)KMF_OCSP_IGNORE_SIGN_ATTR); 102*99ebb4caSwyllys if (c != NULL && !strcasecmp(c, "true")) { 103*99ebb4caSwyllys vinfo->ocsp_info.basic.ignore_response_sign = 1; 104*99ebb4caSwyllys xmlFree(c); 105*99ebb4caSwyllys } 106*99ebb4caSwyllys 107*99ebb4caSwyllys } else if (!xmlStrcmp((const xmlChar *)n->name, 108*99ebb4caSwyllys (const xmlChar *)KMF_OCSP_RESPONDER_CERT_ELEMENT)) { 109*99ebb4caSwyllys 110*99ebb4caSwyllys vinfo->ocsp_info.resp_cert.name = 111*99ebb4caSwyllys (char *)xmlGetProp(n, 112*99ebb4caSwyllys (const xmlChar *)KMF_CERT_NAME_ATTR); 113*99ebb4caSwyllys vinfo->ocsp_info.resp_cert.serial = 114*99ebb4caSwyllys (char *)xmlGetProp(n, 115*99ebb4caSwyllys (const xmlChar *)KMF_CERT_SERIAL_ATTR); 116*99ebb4caSwyllys vinfo->ocsp_info.has_resp_cert = 1; 117*99ebb4caSwyllys } 118*99ebb4caSwyllys 119*99ebb4caSwyllys n = n->next; 120*99ebb4caSwyllys } 121*99ebb4caSwyllys 122*99ebb4caSwyllys } 123*99ebb4caSwyllys 124*99ebb4caSwyllys /* 125*99ebb4caSwyllys * Parse the "validation-methods" section of the policy. 126*99ebb4caSwyllys */ 127*99ebb4caSwyllys static void 128*99ebb4caSwyllys parseValidation(xmlNodePtr node, KMF_VALIDATION_POLICY *vinfo, 129*99ebb4caSwyllys KMF_POLICY_RECORD *policy) 130*99ebb4caSwyllys { 131*99ebb4caSwyllys xmlNodePtr n; 132*99ebb4caSwyllys char *c; 133*99ebb4caSwyllys n = node->children; 134*99ebb4caSwyllys while (n != NULL) { 135*99ebb4caSwyllys if (!xmlStrcmp((const xmlChar *)n->name, 136*99ebb4caSwyllys (const xmlChar *)KMF_OCSP_ELEMENT)) { 137*99ebb4caSwyllys 138*99ebb4caSwyllys parseOCSPValidation(n, &policy->validation_info); 139*99ebb4caSwyllys policy->revocation |= KMF_REVOCATION_METHOD_OCSP; 140*99ebb4caSwyllys 141*99ebb4caSwyllys 142*99ebb4caSwyllys } else if (!xmlStrcmp((const xmlChar *)n->name, 143*99ebb4caSwyllys (const xmlChar *)KMF_CRL_ELEMENT)) { 144*99ebb4caSwyllys 145*99ebb4caSwyllys vinfo->crl_info.basefilename = (char *)xmlGetProp(n, 146*99ebb4caSwyllys (const xmlChar *)KMF_CRL_BASENAME_ATTR); 147*99ebb4caSwyllys 148*99ebb4caSwyllys vinfo->crl_info.directory = (char *)xmlGetProp(n, 149*99ebb4caSwyllys (const xmlChar *)KMF_CRL_DIRECTORY_ATTR); 150*99ebb4caSwyllys 151*99ebb4caSwyllys c = (char *)xmlGetProp(n, 152*99ebb4caSwyllys (const xmlChar *)KMF_CRL_GET_URI_ATTR); 153*99ebb4caSwyllys if (c != NULL && !strcasecmp(c, "true")) { 154*99ebb4caSwyllys vinfo->crl_info.get_crl_uri = 1; 155*99ebb4caSwyllys } else { 156*99ebb4caSwyllys vinfo->crl_info.get_crl_uri = 0; 157*99ebb4caSwyllys } 158*99ebb4caSwyllys xmlFree(c); 159*99ebb4caSwyllys 160*99ebb4caSwyllys vinfo->crl_info.proxy = (char *)xmlGetProp(n, 161*99ebb4caSwyllys (const xmlChar *)KMF_CRL_PROXY_ATTR); 162*99ebb4caSwyllys 163*99ebb4caSwyllys c = (char *)xmlGetProp(n, 164*99ebb4caSwyllys (const xmlChar *)KMF_CRL_IGNORE_SIGN_ATTR); 165*99ebb4caSwyllys if (c != NULL && !strcasecmp(c, "true")) { 166*99ebb4caSwyllys vinfo->crl_info.ignore_crl_sign = 1; 167*99ebb4caSwyllys } else { 168*99ebb4caSwyllys vinfo->crl_info.ignore_crl_sign = 0; 169*99ebb4caSwyllys } 170*99ebb4caSwyllys xmlFree(c); 171*99ebb4caSwyllys 172*99ebb4caSwyllys c = (char *)xmlGetProp(n, 173*99ebb4caSwyllys (const xmlChar *)KMF_CRL_IGNORE_DATE_ATTR); 174*99ebb4caSwyllys if (c != NULL && !strcasecmp(c, "true")) { 175*99ebb4caSwyllys vinfo->crl_info.ignore_crl_date = 1; 176*99ebb4caSwyllys } else { 177*99ebb4caSwyllys vinfo->crl_info.ignore_crl_date = 0; 178*99ebb4caSwyllys } 179*99ebb4caSwyllys xmlFree(c); 180*99ebb4caSwyllys 181*99ebb4caSwyllys policy->revocation |= KMF_REVOCATION_METHOD_CRL; 182*99ebb4caSwyllys } 183*99ebb4caSwyllys 184*99ebb4caSwyllys n = n->next; 185*99ebb4caSwyllys } 186*99ebb4caSwyllys } 187*99ebb4caSwyllys 188*99ebb4caSwyllys char * 189*99ebb4caSwyllys ku2str(uint32_t bitfield) 190*99ebb4caSwyllys { 191*99ebb4caSwyllys if (bitfield & KMF_digitalSignature) 192*99ebb4caSwyllys return ("digitalSignature"); 193*99ebb4caSwyllys 194*99ebb4caSwyllys if (bitfield & KMF_nonRepudiation) 195*99ebb4caSwyllys return ("nonRepudiation"); 196*99ebb4caSwyllys 197*99ebb4caSwyllys if (bitfield & KMF_keyEncipherment) 198*99ebb4caSwyllys return ("keyEncipherment"); 199*99ebb4caSwyllys 200*99ebb4caSwyllys if (bitfield & KMF_dataEncipherment) 201*99ebb4caSwyllys return ("dataEncipherment"); 202*99ebb4caSwyllys 203*99ebb4caSwyllys if (bitfield & KMF_keyAgreement) 204*99ebb4caSwyllys return ("keyAgreement"); 205*99ebb4caSwyllys 206*99ebb4caSwyllys if (bitfield & KMF_keyCertSign) 207*99ebb4caSwyllys return ("keyCertSign"); 208*99ebb4caSwyllys 209*99ebb4caSwyllys if (bitfield & KMF_cRLSign) 210*99ebb4caSwyllys return ("cRLSign"); 211*99ebb4caSwyllys 212*99ebb4caSwyllys if (bitfield & KMF_encipherOnly) 213*99ebb4caSwyllys return ("encipherOnly"); 214*99ebb4caSwyllys 215*99ebb4caSwyllys if (bitfield & KMF_decipherOnly) 216*99ebb4caSwyllys return ("decipherOnly"); 217*99ebb4caSwyllys 218*99ebb4caSwyllys return (NULL); 219*99ebb4caSwyllys } 220*99ebb4caSwyllys 221*99ebb4caSwyllys uint16_t 222*99ebb4caSwyllys KMF_StringToKeyUsage(char *kustring) 223*99ebb4caSwyllys { 224*99ebb4caSwyllys if (kustring == NULL || !strlen(kustring)) 225*99ebb4caSwyllys return (0); 226*99ebb4caSwyllys if (strcasecmp(kustring, "digitalSignature") == 0) 227*99ebb4caSwyllys return (KMF_digitalSignature); 228*99ebb4caSwyllys if (strcasecmp(kustring, "nonRepudiation") == 0) 229*99ebb4caSwyllys return (KMF_nonRepudiation); 230*99ebb4caSwyllys if (strcasecmp(kustring, "keyEncipherment") == 0) 231*99ebb4caSwyllys return (KMF_keyEncipherment); 232*99ebb4caSwyllys if (strcasecmp(kustring, "dataEncipherment") == 0) 233*99ebb4caSwyllys return (KMF_dataEncipherment); 234*99ebb4caSwyllys if (strcasecmp(kustring, "keyAgreement") == 0) 235*99ebb4caSwyllys return (KMF_keyAgreement); 236*99ebb4caSwyllys if (strcasecmp(kustring, "keyCertSign") == 0) 237*99ebb4caSwyllys return (KMF_keyCertSign); 238*99ebb4caSwyllys if (strcasecmp(kustring, "cRLSign") == 0) 239*99ebb4caSwyllys return (KMF_cRLSign); 240*99ebb4caSwyllys if (strcasecmp(kustring, "encipherOnly") == 0) 241*99ebb4caSwyllys return (KMF_encipherOnly); 242*99ebb4caSwyllys if (strcasecmp(kustring, "decipherOnly") == 0) 243*99ebb4caSwyllys return (KMF_decipherOnly); 244*99ebb4caSwyllys 245*99ebb4caSwyllys return (0); 246*99ebb4caSwyllys } 247*99ebb4caSwyllys 248*99ebb4caSwyllys static void 249*99ebb4caSwyllys parseKeyUsageSet(xmlNodePtr node, uint32_t *kubits) 250*99ebb4caSwyllys { 251*99ebb4caSwyllys xmlNodePtr n; 252*99ebb4caSwyllys char *c; 253*99ebb4caSwyllys 254*99ebb4caSwyllys n = node->children; 255*99ebb4caSwyllys while (n != NULL) { 256*99ebb4caSwyllys if (!xmlStrcmp((const xmlChar *)n->name, 257*99ebb4caSwyllys (const xmlChar *)KMF_KEY_USAGE_ELEMENT)) { 258*99ebb4caSwyllys c = (char *)xmlGetProp(n, 259*99ebb4caSwyllys (const xmlChar *)KMF_KEY_USAGE_USE_ATTR); 260*99ebb4caSwyllys if (c) { 261*99ebb4caSwyllys *kubits |= KMF_StringToKeyUsage(c); 262*99ebb4caSwyllys xmlFree(c); 263*99ebb4caSwyllys } 264*99ebb4caSwyllys } 265*99ebb4caSwyllys 266*99ebb4caSwyllys n = n->next; 267*99ebb4caSwyllys } 268*99ebb4caSwyllys } 269*99ebb4caSwyllys 270*99ebb4caSwyllys static KMF_OID * 271*99ebb4caSwyllys dup_oid(KMF_OID *oldoid) 272*99ebb4caSwyllys { 273*99ebb4caSwyllys KMF_OID *oid; 274*99ebb4caSwyllys 275*99ebb4caSwyllys oid = malloc(sizeof (KMF_OID)); 276*99ebb4caSwyllys if (oid == NULL) 277*99ebb4caSwyllys return (NULL); 278*99ebb4caSwyllys 279*99ebb4caSwyllys oid->Length = oldoid->Length; 280*99ebb4caSwyllys oid->Data = malloc(oid->Length); 281*99ebb4caSwyllys if (oid->Data == NULL) { 282*99ebb4caSwyllys free(oid); 283*99ebb4caSwyllys return (NULL); 284*99ebb4caSwyllys } 285*99ebb4caSwyllys (void) memcpy(oid->Data, oldoid->Data, oid->Length); 286*99ebb4caSwyllys 287*99ebb4caSwyllys return (oid); 288*99ebb4caSwyllys } 289*99ebb4caSwyllys 290*99ebb4caSwyllys KMF_OID * 291*99ebb4caSwyllys kmf_ekuname2oid(char *ekuname) 292*99ebb4caSwyllys { 293*99ebb4caSwyllys KMF_OID *oid; 294*99ebb4caSwyllys int i; 295*99ebb4caSwyllys 296*99ebb4caSwyllys if (ekuname == NULL) 297*99ebb4caSwyllys return (NULL); 298*99ebb4caSwyllys 299*99ebb4caSwyllys for (i = 0; i < num_ekus; i++) { 300*99ebb4caSwyllys if (strcasecmp(EKUList[i].ekuname, ekuname) == 0) { 301*99ebb4caSwyllys oid = dup_oid(EKUList[i].oid); 302*99ebb4caSwyllys return (oid); 303*99ebb4caSwyllys } 304*99ebb4caSwyllys } 305*99ebb4caSwyllys 306*99ebb4caSwyllys return (NULL); 307*99ebb4caSwyllys } 308*99ebb4caSwyllys 309*99ebb4caSwyllys char * 310*99ebb4caSwyllys KMF_OID2EKUString(KMF_OID *oid) 311*99ebb4caSwyllys { 312*99ebb4caSwyllys int i; 313*99ebb4caSwyllys for (i = 0; i < num_ekus; i++) { 314*99ebb4caSwyllys if (oid->Length == EKUList[i].oid->Length && 315*99ebb4caSwyllys !memcmp(oid->Data, EKUList[i].oid->Data, oid->Length)) { 316*99ebb4caSwyllys return (EKUList[i].ekuname); 317*99ebb4caSwyllys } 318*99ebb4caSwyllys } 319*99ebb4caSwyllys return (NULL); 320*99ebb4caSwyllys } 321*99ebb4caSwyllys 322*99ebb4caSwyllys /* 323*99ebb4caSwyllys * Convert a human-readable OID string of the form "1.2.3.4" or 324*99ebb4caSwyllys * "1 2 3 4" into a KMF_OID value. 325*99ebb4caSwyllys */ 326*99ebb4caSwyllys KMF_OID * 327*99ebb4caSwyllys kmf_string2oid(char *oidstring) 328*99ebb4caSwyllys { 329*99ebb4caSwyllys KMF_OID *oid = NULL; 330*99ebb4caSwyllys char *cp, *bp, *startp; 331*99ebb4caSwyllys int numbuf; 332*99ebb4caSwyllys int onumbuf; 333*99ebb4caSwyllys int nbytes, index; 334*99ebb4caSwyllys int len; 335*99ebb4caSwyllys unsigned char *op; 336*99ebb4caSwyllys 337*99ebb4caSwyllys if (oidstring == NULL) 338*99ebb4caSwyllys return (NULL); 339*99ebb4caSwyllys 340*99ebb4caSwyllys len = strlen(oidstring); 341*99ebb4caSwyllys 342*99ebb4caSwyllys bp = oidstring; 343*99ebb4caSwyllys cp = bp; 344*99ebb4caSwyllys /* Skip over leading space */ 345*99ebb4caSwyllys while ((bp < &cp[len]) && isspace(*bp)) 346*99ebb4caSwyllys bp++; 347*99ebb4caSwyllys 348*99ebb4caSwyllys startp = bp; 349*99ebb4caSwyllys nbytes = 0; 350*99ebb4caSwyllys 351*99ebb4caSwyllys /* 352*99ebb4caSwyllys * The first two numbers are chewed up by the first octet. 353*99ebb4caSwyllys */ 354*99ebb4caSwyllys if (sscanf(bp, "%d", &numbuf) != 1) 355*99ebb4caSwyllys return (NULL); 356*99ebb4caSwyllys while ((bp < &cp[len]) && isdigit(*bp)) 357*99ebb4caSwyllys bp++; 358*99ebb4caSwyllys while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.')) 359*99ebb4caSwyllys bp++; 360*99ebb4caSwyllys if (sscanf(bp, "%d", &numbuf) != 1) 361*99ebb4caSwyllys return (NULL); 362*99ebb4caSwyllys while ((bp < &cp[len]) && isdigit(*bp)) 363*99ebb4caSwyllys bp++; 364*99ebb4caSwyllys while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.')) 365*99ebb4caSwyllys bp++; 366*99ebb4caSwyllys nbytes++; 367*99ebb4caSwyllys 368*99ebb4caSwyllys while (isdigit(*bp)) { 369*99ebb4caSwyllys if (sscanf(bp, "%d", &numbuf) != 1) 370*99ebb4caSwyllys return (NULL); 371*99ebb4caSwyllys while (numbuf) { 372*99ebb4caSwyllys nbytes++; 373*99ebb4caSwyllys numbuf >>= 7; 374*99ebb4caSwyllys } 375*99ebb4caSwyllys while ((bp < &cp[len]) && isdigit(*bp)) 376*99ebb4caSwyllys bp++; 377*99ebb4caSwyllys while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.')) 378*99ebb4caSwyllys bp++; 379*99ebb4caSwyllys } 380*99ebb4caSwyllys 381*99ebb4caSwyllys oid = malloc(sizeof (KMF_OID)); 382*99ebb4caSwyllys if (oid == NULL) 383*99ebb4caSwyllys return (NULL); 384*99ebb4caSwyllys 385*99ebb4caSwyllys oid->Length = nbytes; 386*99ebb4caSwyllys oid->Data = malloc(oid->Length); 387*99ebb4caSwyllys if (oid->Data == NULL) { 388*99ebb4caSwyllys free(oid); 389*99ebb4caSwyllys return (NULL); 390*99ebb4caSwyllys } 391*99ebb4caSwyllys (void) memset(oid->Data, 0, oid->Length); 392*99ebb4caSwyllys 393*99ebb4caSwyllys op = oid->Data; 394*99ebb4caSwyllys 395*99ebb4caSwyllys bp = startp; 396*99ebb4caSwyllys (void) sscanf(bp, "%d", &numbuf); 397*99ebb4caSwyllys 398*99ebb4caSwyllys while (isdigit(*bp)) bp++; 399*99ebb4caSwyllys while (isspace(*bp) || *bp == '.') bp++; 400*99ebb4caSwyllys 401*99ebb4caSwyllys onumbuf = 40 * numbuf; 402*99ebb4caSwyllys (void) sscanf(bp, "%d", &numbuf); 403*99ebb4caSwyllys onumbuf += numbuf; 404*99ebb4caSwyllys *op = (unsigned char) onumbuf; 405*99ebb4caSwyllys op++; 406*99ebb4caSwyllys 407*99ebb4caSwyllys while (isdigit(*bp)) bp++; 408*99ebb4caSwyllys while (isspace(*bp) || *bp == '.') bp++; 409*99ebb4caSwyllys while (isdigit(*bp)) { 410*99ebb4caSwyllys (void) sscanf(bp, "%d", &numbuf); 411*99ebb4caSwyllys nbytes = 0; 412*99ebb4caSwyllys /* Have to fill in the bytes msb-first */ 413*99ebb4caSwyllys onumbuf = numbuf; 414*99ebb4caSwyllys while (numbuf) { 415*99ebb4caSwyllys nbytes++; 416*99ebb4caSwyllys numbuf >>= 7; 417*99ebb4caSwyllys } 418*99ebb4caSwyllys numbuf = onumbuf; 419*99ebb4caSwyllys op += nbytes; 420*99ebb4caSwyllys index = -1; 421*99ebb4caSwyllys while (numbuf) { 422*99ebb4caSwyllys op[index] = (unsigned char)numbuf & 0x7f; 423*99ebb4caSwyllys if (index != -1) 424*99ebb4caSwyllys op[index] |= 0x80; 425*99ebb4caSwyllys index--; 426*99ebb4caSwyllys numbuf >>= 7; 427*99ebb4caSwyllys } 428*99ebb4caSwyllys while (isdigit(*bp)) bp++; 429*99ebb4caSwyllys while (isspace(*bp) || *bp == '.') bp++; 430*99ebb4caSwyllys } 431*99ebb4caSwyllys 432*99ebb4caSwyllys return (oid); 433*99ebb4caSwyllys } 434*99ebb4caSwyllys 435*99ebb4caSwyllys static KMF_RETURN 436*99ebb4caSwyllys parseExtKeyUsage(xmlNodePtr node, KMF_EKU_POLICY *ekus) 437*99ebb4caSwyllys { 438*99ebb4caSwyllys xmlNodePtr n; 439*99ebb4caSwyllys char *c; 440*99ebb4caSwyllys KMF_RETURN ret = KMF_OK; 441*99ebb4caSwyllys boolean_t found = FALSE; 442*99ebb4caSwyllys 443*99ebb4caSwyllys n = node->children; 444*99ebb4caSwyllys while (n != NULL && ret == KMF_OK) { 445*99ebb4caSwyllys KMF_OID *newoid = NULL; 446*99ebb4caSwyllys 447*99ebb4caSwyllys if (!xmlStrcmp((const xmlChar *)n->name, 448*99ebb4caSwyllys (const xmlChar *)KMF_EKU_NAME_ELEMENT)) { 449*99ebb4caSwyllys c = (char *)xmlGetProp(n, 450*99ebb4caSwyllys (const xmlChar *)KMF_EKU_NAME_ATTR); 451*99ebb4caSwyllys if (c != NULL) { 452*99ebb4caSwyllys newoid = kmf_ekuname2oid(c); 453*99ebb4caSwyllys xmlFree(c); 454*99ebb4caSwyllys found = TRUE; 455*99ebb4caSwyllys } 456*99ebb4caSwyllys } else if (!xmlStrcmp((const xmlChar *)n->name, 457*99ebb4caSwyllys (const xmlChar *)KMF_EKU_OID_ELEMENT)) { 458*99ebb4caSwyllys c = (char *)xmlGetProp(n, 459*99ebb4caSwyllys (const xmlChar *)KMF_EKU_OID_ATTR); 460*99ebb4caSwyllys if (c != NULL) { 461*99ebb4caSwyllys newoid = kmf_string2oid(c); 462*99ebb4caSwyllys xmlFree(c); 463*99ebb4caSwyllys found = TRUE; 464*99ebb4caSwyllys } 465*99ebb4caSwyllys } else { 466*99ebb4caSwyllys n = n->next; 467*99ebb4caSwyllys if ((n == NULL) && (!found)) 468*99ebb4caSwyllys ret = KMF_ERR_POLICY_DB_FORMAT; 469*99ebb4caSwyllys continue; 470*99ebb4caSwyllys } 471*99ebb4caSwyllys 472*99ebb4caSwyllys if (newoid != NULL) { 473*99ebb4caSwyllys ekus->eku_count++; 474*99ebb4caSwyllys ekus->ekulist = realloc(ekus->ekulist, 475*99ebb4caSwyllys ekus->eku_count * sizeof (KMF_OID)); 476*99ebb4caSwyllys if (ekus->ekulist != NULL) { 477*99ebb4caSwyllys ekus->ekulist[ekus->eku_count-1].Length = 478*99ebb4caSwyllys newoid->Length; 479*99ebb4caSwyllys ekus->ekulist[ekus->eku_count-1].Data = 480*99ebb4caSwyllys malloc(newoid->Length); 481*99ebb4caSwyllys if (ekus->ekulist[ekus->eku_count-1].Data == 482*99ebb4caSwyllys NULL) { 483*99ebb4caSwyllys ret = KMF_ERR_MEMORY; 484*99ebb4caSwyllys } else { 485*99ebb4caSwyllys (void) memcpy( 486*99ebb4caSwyllys ekus->ekulist[ekus->eku_count-1]. 487*99ebb4caSwyllys Data, 488*99ebb4caSwyllys newoid->Data, newoid->Length); 489*99ebb4caSwyllys } 490*99ebb4caSwyllys } else { 491*99ebb4caSwyllys ret = KMF_ERR_MEMORY; 492*99ebb4caSwyllys } 493*99ebb4caSwyllys KMF_FreeData(newoid); 494*99ebb4caSwyllys free(newoid); 495*99ebb4caSwyllys } else { 496*99ebb4caSwyllys ret = KMF_ERR_POLICY_DB_FORMAT; 497*99ebb4caSwyllys } 498*99ebb4caSwyllys 499*99ebb4caSwyllys n = n->next; 500*99ebb4caSwyllys } 501*99ebb4caSwyllys 502*99ebb4caSwyllys return (ret); 503*99ebb4caSwyllys } 504*99ebb4caSwyllys 505*99ebb4caSwyllys int 506*99ebb4caSwyllys parsePolicyElement(xmlNodePtr node, KMF_POLICY_RECORD *policy) 507*99ebb4caSwyllys { 508*99ebb4caSwyllys int ret = 0; 509*99ebb4caSwyllys xmlNodePtr n = node->xmlChildrenNode; 510*99ebb4caSwyllys char *c; 511*99ebb4caSwyllys 512*99ebb4caSwyllys if (node->type == XML_ELEMENT_NODE) { 513*99ebb4caSwyllys if (node->properties != NULL) { 514*99ebb4caSwyllys policy->name = (char *)xmlGetProp(node, 515*99ebb4caSwyllys (const xmlChar *)KMF_POLICY_NAME_ATTR); 516*99ebb4caSwyllys 517*99ebb4caSwyllys c = (char *)xmlGetProp(node, 518*99ebb4caSwyllys (const xmlChar *)KMF_OPTIONS_IGNORE_DATE_ATTR); 519*99ebb4caSwyllys if (c && !strcasecmp(c, "true")) { 520*99ebb4caSwyllys policy->ignore_date = 1; 521*99ebb4caSwyllys xmlFree((xmlChar *)c); 522*99ebb4caSwyllys } 523*99ebb4caSwyllys 524*99ebb4caSwyllys c = (char *)xmlGetProp(node, 525*99ebb4caSwyllys (const xmlChar *)KMF_OPTIONS_IGNORE_UNKNOWN_EKUS); 526*99ebb4caSwyllys if (c && !strcasecmp(c, "true")) { 527*99ebb4caSwyllys policy->ignore_unknown_ekus = 1; 528*99ebb4caSwyllys xmlFree(c); 529*99ebb4caSwyllys } 530*99ebb4caSwyllys 531*99ebb4caSwyllys c = (char *)xmlGetProp(node, 532*99ebb4caSwyllys (const xmlChar *)KMF_OPTIONS_IGNORE_TRUST_ANCHOR); 533*99ebb4caSwyllys if (c && !strcasecmp(c, "true")) { 534*99ebb4caSwyllys policy->ignore_trust_anchor = 1; 535*99ebb4caSwyllys xmlFree(c); 536*99ebb4caSwyllys } 537*99ebb4caSwyllys 538*99ebb4caSwyllys c = (char *)xmlGetProp(node, 539*99ebb4caSwyllys (const xmlChar *)KMF_OPTIONS_VALIDITY_ADJUSTTIME); 540*99ebb4caSwyllys if (c) { 541*99ebb4caSwyllys policy->validity_adjusttime = c; 542*99ebb4caSwyllys } else { 543*99ebb4caSwyllys policy->validity_adjusttime = NULL; 544*99ebb4caSwyllys } 545*99ebb4caSwyllys 546*99ebb4caSwyllys policy->ta_name = (char *)xmlGetProp(node, 547*99ebb4caSwyllys (const xmlChar *)KMF_POLICY_TA_NAME_ATTR); 548*99ebb4caSwyllys 549*99ebb4caSwyllys policy->ta_serial = (char *)xmlGetProp(node, 550*99ebb4caSwyllys (const xmlChar *)KMF_POLICY_TA_SERIAL_ATTR); 551*99ebb4caSwyllys } 552*99ebb4caSwyllys 553*99ebb4caSwyllys n = node->children; 554*99ebb4caSwyllys while (n != NULL) { 555*99ebb4caSwyllys if (!xmlStrcmp((const xmlChar *)n->name, 556*99ebb4caSwyllys (const xmlChar *)KMF_VALIDATION_METHODS_ELEMENT)) 557*99ebb4caSwyllys parseValidation(n, &policy->validation_info, 558*99ebb4caSwyllys policy); 559*99ebb4caSwyllys else if (!xmlStrcmp((const xmlChar *)n->name, 560*99ebb4caSwyllys (const xmlChar *)KMF_KEY_USAGE_SET_ELEMENT)) 561*99ebb4caSwyllys parseKeyUsageSet(n, &policy->ku_bits); 562*99ebb4caSwyllys else if (!xmlStrcmp((const xmlChar *)n->name, 563*99ebb4caSwyllys (const xmlChar *)KMF_EKU_ELEMENT)) { 564*99ebb4caSwyllys ret = parseExtKeyUsage(n, &policy->eku_set); 565*99ebb4caSwyllys if (ret != KMF_OK) 566*99ebb4caSwyllys return (ret); 567*99ebb4caSwyllys } 568*99ebb4caSwyllys 569*99ebb4caSwyllys n = n->next; 570*99ebb4caSwyllys } 571*99ebb4caSwyllys } 572*99ebb4caSwyllys 573*99ebb4caSwyllys return (ret); 574*99ebb4caSwyllys } 575*99ebb4caSwyllys 576*99ebb4caSwyllys static int 577*99ebb4caSwyllys newprop(xmlNodePtr node, char *attrname, char *src) 578*99ebb4caSwyllys { 579*99ebb4caSwyllys xmlAttrPtr newattr; 580*99ebb4caSwyllys 581*99ebb4caSwyllys if (src != NULL && strlen(src)) { 582*99ebb4caSwyllys newattr = xmlNewProp(node, (const xmlChar *)attrname, 583*99ebb4caSwyllys (xmlChar *)src); 584*99ebb4caSwyllys if (newattr == NULL) { 585*99ebb4caSwyllys xmlUnlinkNode(node); 586*99ebb4caSwyllys xmlFreeNode(node); 587*99ebb4caSwyllys return (-1); 588*99ebb4caSwyllys } 589*99ebb4caSwyllys } 590*99ebb4caSwyllys return (0); 591*99ebb4caSwyllys } 592*99ebb4caSwyllys 593*99ebb4caSwyllys /* 594*99ebb4caSwyllys * Add CRL policy information to the XML tree. 595*99ebb4caSwyllys * Return non-zero on any failure, else 0 for success. 596*99ebb4caSwyllys * 597*99ebb4caSwyllys * This function is called only when the KMF_REVOCATION_METHOD_CRL flag is on. 598*99ebb4caSwyllys */ 599*99ebb4caSwyllys static int 600*99ebb4caSwyllys AddCRLNodes(xmlNodePtr node, KMF_CRL_POLICY *crlinfo) 601*99ebb4caSwyllys { 602*99ebb4caSwyllys xmlNodePtr n; 603*99ebb4caSwyllys 604*99ebb4caSwyllys addFormatting(node, "\t\t"); 605*99ebb4caSwyllys n = xmlNewChild(node, NULL, (const xmlChar *)"crl", NULL); 606*99ebb4caSwyllys if (n == NULL) 607*99ebb4caSwyllys return (-1); 608*99ebb4caSwyllys 609*99ebb4caSwyllys if (crlinfo->basefilename && 610*99ebb4caSwyllys newprop(n, KMF_CRL_BASENAME_ATTR, crlinfo->basefilename)) 611*99ebb4caSwyllys return (-1); 612*99ebb4caSwyllys 613*99ebb4caSwyllys if (crlinfo->directory && 614*99ebb4caSwyllys newprop(n, KMF_CRL_DIRECTORY_ATTR, crlinfo->directory)) 615*99ebb4caSwyllys return (-1); 616*99ebb4caSwyllys 617*99ebb4caSwyllys if (crlinfo->get_crl_uri && 618*99ebb4caSwyllys newprop(n, KMF_CRL_GET_URI_ATTR, "TRUE")) { 619*99ebb4caSwyllys return (-1); 620*99ebb4caSwyllys } 621*99ebb4caSwyllys 622*99ebb4caSwyllys if (crlinfo->proxy && 623*99ebb4caSwyllys newprop(n, KMF_CRL_PROXY_ATTR, crlinfo->proxy)) 624*99ebb4caSwyllys return (-1); 625*99ebb4caSwyllys 626*99ebb4caSwyllys if (crlinfo->ignore_crl_sign && 627*99ebb4caSwyllys newprop(n, KMF_CRL_IGNORE_SIGN_ATTR, "TRUE")) { 628*99ebb4caSwyllys return (-1); 629*99ebb4caSwyllys } 630*99ebb4caSwyllys 631*99ebb4caSwyllys if (crlinfo->ignore_crl_date && 632*99ebb4caSwyllys newprop(n, KMF_CRL_IGNORE_DATE_ATTR, "TRUE")) { 633*99ebb4caSwyllys return (-1); 634*99ebb4caSwyllys } 635*99ebb4caSwyllys 636*99ebb4caSwyllys addFormatting(node, "\n"); 637*99ebb4caSwyllys return (0); 638*99ebb4caSwyllys } 639*99ebb4caSwyllys 640*99ebb4caSwyllys /* 641*99ebb4caSwyllys * Add OCSP information to the policy tree. 642*99ebb4caSwyllys * Return non-zero on any failure, else 0 for success. 643*99ebb4caSwyllys * 644*99ebb4caSwyllys * This function is called only when the KMF_REVOCATION_METHOD_OCSP flag is on. 645*99ebb4caSwyllys */ 646*99ebb4caSwyllys static int 647*99ebb4caSwyllys AddOCSPNodes(xmlNodePtr parent, KMF_OCSP_POLICY *ocsp) 648*99ebb4caSwyllys { 649*99ebb4caSwyllys int ret = 0; 650*99ebb4caSwyllys xmlNodePtr n_ocsp, n_basic, n_resp; 651*99ebb4caSwyllys KMF_OCSP_BASIC_POLICY *basic; 652*99ebb4caSwyllys KMF_RESP_CERT_POLICY *resp_cert; 653*99ebb4caSwyllys 654*99ebb4caSwyllys basic = &(ocsp->basic); 655*99ebb4caSwyllys resp_cert = &(ocsp->resp_cert); 656*99ebb4caSwyllys 657*99ebb4caSwyllys if (basic->responderURI != NULL || basic->uri_from_cert == B_TRUE) { 658*99ebb4caSwyllys 659*99ebb4caSwyllys addFormatting(parent, "\t\t"); 660*99ebb4caSwyllys 661*99ebb4caSwyllys /* basic node */ 662*99ebb4caSwyllys n_ocsp = xmlNewChild(parent, NULL, 663*99ebb4caSwyllys (const xmlChar *)KMF_OCSP_ELEMENT, NULL); 664*99ebb4caSwyllys if (n_ocsp == NULL) 665*99ebb4caSwyllys return (-1); 666*99ebb4caSwyllys addFormatting(n_ocsp, "\n\t\t\t"); 667*99ebb4caSwyllys 668*99ebb4caSwyllys n_basic = xmlNewChild(n_ocsp, NULL, 669*99ebb4caSwyllys (const xmlChar *)KMF_OCSP_BASIC_ELEMENT, NULL); 670*99ebb4caSwyllys if (n_basic == NULL) 671*99ebb4caSwyllys return (-1); 672*99ebb4caSwyllys if (basic->responderURI && newprop(n_basic, 673*99ebb4caSwyllys KMF_OCSP_RESPONDER_ATTR, basic->responderURI)) 674*99ebb4caSwyllys return (-1); 675*99ebb4caSwyllys if (basic->proxy && 676*99ebb4caSwyllys newprop(n_basic, KMF_OCSP_PROXY_ATTR, basic->proxy)) 677*99ebb4caSwyllys return (-1); 678*99ebb4caSwyllys if (basic->uri_from_cert && 679*99ebb4caSwyllys newprop(n_basic, KMF_OCSP_URI_ATTR, "TRUE")) 680*99ebb4caSwyllys return (-1); 681*99ebb4caSwyllys if (basic->response_lifetime && 682*99ebb4caSwyllys newprop(n_basic, KMF_OCSP_RESPONSE_LIFETIME_ATTR, 683*99ebb4caSwyllys basic->response_lifetime)) 684*99ebb4caSwyllys return (-1); 685*99ebb4caSwyllys if (basic->ignore_response_sign && 686*99ebb4caSwyllys newprop(n_basic, KMF_OCSP_IGNORE_SIGN_ATTR, "TRUE")) 687*99ebb4caSwyllys return (-1); 688*99ebb4caSwyllys 689*99ebb4caSwyllys addFormatting(n_ocsp, "\n\t\t\t"); 690*99ebb4caSwyllys 691*99ebb4caSwyllys /* responder cert node */ 692*99ebb4caSwyllys if (ocsp->has_resp_cert) { 693*99ebb4caSwyllys n_resp = xmlNewChild(n_ocsp, NULL, 694*99ebb4caSwyllys (const xmlChar *)KMF_OCSP_RESPONDER_CERT_ELEMENT, 695*99ebb4caSwyllys NULL); 696*99ebb4caSwyllys if (n_resp == NULL) 697*99ebb4caSwyllys return (-1); 698*99ebb4caSwyllys if (newprop(n_resp, KMF_CERT_NAME_ATTR, 699*99ebb4caSwyllys resp_cert->name)) 700*99ebb4caSwyllys return (-1); 701*99ebb4caSwyllys if (newprop(n_resp, KMF_CERT_SERIAL_ATTR, 702*99ebb4caSwyllys resp_cert->serial)) 703*99ebb4caSwyllys return (-1); 704*99ebb4caSwyllys } 705*99ebb4caSwyllys addFormatting(n_ocsp, "\n\t\t"); 706*99ebb4caSwyllys } 707*99ebb4caSwyllys 708*99ebb4caSwyllys addFormatting(parent, "\n"); 709*99ebb4caSwyllys return (ret); 710*99ebb4caSwyllys } 711*99ebb4caSwyllys 712*99ebb4caSwyllys /* 713*99ebb4caSwyllys * Add validation method information to the policy tree. 714*99ebb4caSwyllys * Return non-zero on any failure, else 0 for success. 715*99ebb4caSwyllys */ 716*99ebb4caSwyllys static int 717*99ebb4caSwyllys AddValidationNodes(xmlNodePtr parent, KMF_POLICY_RECORD *policy) 718*99ebb4caSwyllys { 719*99ebb4caSwyllys xmlNodePtr mnode; 720*99ebb4caSwyllys int ret = 0; 721*99ebb4caSwyllys 722*99ebb4caSwyllys addFormatting(parent, "\t"); 723*99ebb4caSwyllys mnode = xmlNewChild(parent, NULL, 724*99ebb4caSwyllys (const xmlChar *)KMF_VALIDATION_METHODS_ELEMENT, NULL); 725*99ebb4caSwyllys if (mnode == NULL) 726*99ebb4caSwyllys return (-1); 727*99ebb4caSwyllys 728*99ebb4caSwyllys addFormatting(mnode, "\n"); 729*99ebb4caSwyllys 730*99ebb4caSwyllys if (policy->revocation & KMF_REVOCATION_METHOD_OCSP) { 731*99ebb4caSwyllys ret = AddOCSPNodes(mnode, &(policy->validation_info.ocsp_info)); 732*99ebb4caSwyllys if (ret != KMF_OK) 733*99ebb4caSwyllys goto end; 734*99ebb4caSwyllys } 735*99ebb4caSwyllys 736*99ebb4caSwyllys if (policy->revocation & KMF_REVOCATION_METHOD_CRL) { 737*99ebb4caSwyllys ret = AddCRLNodes(mnode, &(policy->validation_info.crl_info)); 738*99ebb4caSwyllys if (ret != KMF_OK) 739*99ebb4caSwyllys goto end; 740*99ebb4caSwyllys } 741*99ebb4caSwyllys 742*99ebb4caSwyllys addFormatting(mnode, "\t"); 743*99ebb4caSwyllys addFormatting(parent, "\n"); 744*99ebb4caSwyllys 745*99ebb4caSwyllys end: 746*99ebb4caSwyllys if (ret != 0) { 747*99ebb4caSwyllys xmlUnlinkNode(mnode); 748*99ebb4caSwyllys xmlFreeNode(mnode); 749*99ebb4caSwyllys } 750*99ebb4caSwyllys return (ret); 751*99ebb4caSwyllys 752*99ebb4caSwyllys } 753*99ebb4caSwyllys 754*99ebb4caSwyllys /* 755*99ebb4caSwyllys * Add Key Usage information to the policy tree. 756*99ebb4caSwyllys * Return non-zero on any failure, else 0 for success. 757*99ebb4caSwyllys */ 758*99ebb4caSwyllys static KMF_RETURN 759*99ebb4caSwyllys AddKeyUsageNodes(xmlNodePtr parent, uint32_t kubits) 760*99ebb4caSwyllys { 761*99ebb4caSwyllys int ret = KMF_OK; 762*99ebb4caSwyllys int i; 763*99ebb4caSwyllys 764*99ebb4caSwyllys xmlNodePtr kuset, kunode; 765*99ebb4caSwyllys 766*99ebb4caSwyllys if (kubits == 0) 767*99ebb4caSwyllys return (0); 768*99ebb4caSwyllys 769*99ebb4caSwyllys addFormatting(parent, "\n\t"); 770*99ebb4caSwyllys kuset = xmlNewChild(parent, NULL, 771*99ebb4caSwyllys (const xmlChar *)KMF_KEY_USAGE_SET_ELEMENT, NULL); 772*99ebb4caSwyllys if (kuset == NULL) 773*99ebb4caSwyllys return (KMF_ERR_POLICY_ENGINE); 774*99ebb4caSwyllys 775*99ebb4caSwyllys for (i = KULOWBIT; i <= KUHIGHBIT && ret == KMF_OK; i++) { 776*99ebb4caSwyllys char *s = ku2str((kubits & (1<<i))); 777*99ebb4caSwyllys if (s != NULL) { 778*99ebb4caSwyllys addFormatting(kuset, "\n\t\t"); 779*99ebb4caSwyllys 780*99ebb4caSwyllys kunode = xmlNewChild(kuset, NULL, 781*99ebb4caSwyllys (const xmlChar *)KMF_KEY_USAGE_ELEMENT, NULL); 782*99ebb4caSwyllys if (kunode == NULL) 783*99ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 784*99ebb4caSwyllys 785*99ebb4caSwyllys else if (newprop(kunode, KMF_KEY_USAGE_USE_ATTR, s)) 786*99ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 787*99ebb4caSwyllys } 788*99ebb4caSwyllys } 789*99ebb4caSwyllys addFormatting(kuset, "\n\t"); 790*99ebb4caSwyllys addFormatting(parent, "\n"); 791*99ebb4caSwyllys 792*99ebb4caSwyllys if (ret != KMF_OK) { 793*99ebb4caSwyllys xmlUnlinkNode(kuset); 794*99ebb4caSwyllys xmlFreeNode(kuset); 795*99ebb4caSwyllys } 796*99ebb4caSwyllys 797*99ebb4caSwyllys return (ret); 798*99ebb4caSwyllys } 799*99ebb4caSwyllys 800*99ebb4caSwyllys /* 801*99ebb4caSwyllys * Add Extended-Key-Usage information to the policy tree. 802*99ebb4caSwyllys * Return non-zero on any failure, else 0 for success. 803*99ebb4caSwyllys */ 804*99ebb4caSwyllys static KMF_RETURN 805*99ebb4caSwyllys AddExtKeyUsageNodes(xmlNodePtr parent, KMF_EKU_POLICY *ekus) 806*99ebb4caSwyllys { 807*99ebb4caSwyllys KMF_RETURN ret = KMF_OK; 808*99ebb4caSwyllys xmlNodePtr n, kunode; 809*99ebb4caSwyllys int i; 810*99ebb4caSwyllys 811*99ebb4caSwyllys if (ekus != NULL && ekus->eku_count > 0) { 812*99ebb4caSwyllys addFormatting(parent, "\n\t"); 813*99ebb4caSwyllys n = xmlNewChild(parent, NULL, 814*99ebb4caSwyllys (const xmlChar *)KMF_EKU_ELEMENT, NULL); 815*99ebb4caSwyllys if (n == NULL) 816*99ebb4caSwyllys return (KMF_ERR_POLICY_ENGINE); 817*99ebb4caSwyllys 818*99ebb4caSwyllys for (i = 0; i < ekus->eku_count; i++) { 819*99ebb4caSwyllys char *s = KMF_OID2String(&ekus->ekulist[i]); 820*99ebb4caSwyllys if (s != NULL) { 821*99ebb4caSwyllys addFormatting(n, "\n\t\t"); 822*99ebb4caSwyllys kunode = xmlNewChild(n, NULL, 823*99ebb4caSwyllys (const xmlChar *)KMF_EKU_OID_ELEMENT, 824*99ebb4caSwyllys NULL); 825*99ebb4caSwyllys if (kunode == NULL) 826*99ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 827*99ebb4caSwyllys 828*99ebb4caSwyllys else if (newprop(kunode, KMF_EKU_OID_ATTR, s)) 829*99ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 830*99ebb4caSwyllys free(s); 831*99ebb4caSwyllys } else { 832*99ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 833*99ebb4caSwyllys } 834*99ebb4caSwyllys } 835*99ebb4caSwyllys addFormatting(n, "\n\t"); 836*99ebb4caSwyllys addFormatting(parent, "\n"); 837*99ebb4caSwyllys } 838*99ebb4caSwyllys 839*99ebb4caSwyllys if (ret != KMF_OK) { 840*99ebb4caSwyllys xmlUnlinkNode(n); 841*99ebb4caSwyllys xmlFreeNode(n); 842*99ebb4caSwyllys } 843*99ebb4caSwyllys return (ret); 844*99ebb4caSwyllys } 845*99ebb4caSwyllys 846*99ebb4caSwyllys void 847*99ebb4caSwyllys KMF_FreeEKUPolicy(KMF_EKU_POLICY *ekus) 848*99ebb4caSwyllys { 849*99ebb4caSwyllys if (ekus->eku_count > 0) { 850*99ebb4caSwyllys int i; 851*99ebb4caSwyllys for (i = 0; i < ekus->eku_count; i++) { 852*99ebb4caSwyllys KMF_FreeData(&ekus->ekulist[i]); 853*99ebb4caSwyllys } 854*99ebb4caSwyllys free(ekus->ekulist); 855*99ebb4caSwyllys } 856*99ebb4caSwyllys } 857*99ebb4caSwyllys 858*99ebb4caSwyllys #define FREE_POLICY_STR(s) if (s != NULL) free(s); 859*99ebb4caSwyllys 860*99ebb4caSwyllys void 861*99ebb4caSwyllys KMF_FreePolicyRecord(KMF_POLICY_RECORD *policy) 862*99ebb4caSwyllys { 863*99ebb4caSwyllys if (policy == NULL) 864*99ebb4caSwyllys return; 865*99ebb4caSwyllys 866*99ebb4caSwyllys FREE_POLICY_STR(policy->name) 867*99ebb4caSwyllys FREE_POLICY_STR(policy->VAL_OCSP_BASIC.responderURI) 868*99ebb4caSwyllys FREE_POLICY_STR(policy->VAL_OCSP_BASIC.proxy) 869*99ebb4caSwyllys FREE_POLICY_STR(policy->VAL_OCSP_BASIC.response_lifetime) 870*99ebb4caSwyllys FREE_POLICY_STR(policy->VAL_OCSP_RESP_CERT.name) 871*99ebb4caSwyllys FREE_POLICY_STR(policy->VAL_OCSP_RESP_CERT.serial) 872*99ebb4caSwyllys FREE_POLICY_STR(policy->validation_info.crl_info.basefilename) 873*99ebb4caSwyllys FREE_POLICY_STR(policy->validation_info.crl_info.directory) 874*99ebb4caSwyllys FREE_POLICY_STR(policy->validation_info.crl_info.proxy) 875*99ebb4caSwyllys FREE_POLICY_STR(policy->validity_adjusttime) 876*99ebb4caSwyllys FREE_POLICY_STR(policy->ta_name) 877*99ebb4caSwyllys FREE_POLICY_STR(policy->ta_serial) 878*99ebb4caSwyllys 879*99ebb4caSwyllys KMF_FreeEKUPolicy(&policy->eku_set); 880*99ebb4caSwyllys 881*99ebb4caSwyllys (void) memset(policy, 0, sizeof (KMF_POLICY_RECORD)); 882*99ebb4caSwyllys } 883*99ebb4caSwyllys 884*99ebb4caSwyllys /* 885*99ebb4caSwyllys * KMF_GetPolicy 886*99ebb4caSwyllys * 887*99ebb4caSwyllys * Find a policy record in the database. 888*99ebb4caSwyllys */ 889*99ebb4caSwyllys KMF_RETURN 890*99ebb4caSwyllys KMF_GetPolicy(char *filename, char *policy_name, KMF_POLICY_RECORD *plc) 891*99ebb4caSwyllys { 892*99ebb4caSwyllys KMF_RETURN ret = KMF_OK; 893*99ebb4caSwyllys xmlParserCtxtPtr ctxt; 894*99ebb4caSwyllys xmlDocPtr doc = NULL; 895*99ebb4caSwyllys xmlNodePtr cur, node; 896*99ebb4caSwyllys int found = 0; 897*99ebb4caSwyllys 898*99ebb4caSwyllys if (filename == NULL || policy_name == NULL || plc == NULL) 899*99ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 900*99ebb4caSwyllys 901*99ebb4caSwyllys (void) memset(plc, 0, sizeof (KMF_POLICY_RECORD)); 902*99ebb4caSwyllys 903*99ebb4caSwyllys /* Create a parser context */ 904*99ebb4caSwyllys ctxt = xmlNewParserCtxt(); 905*99ebb4caSwyllys if (ctxt == NULL) 906*99ebb4caSwyllys return (KMF_ERR_POLICY_DB_FORMAT); 907*99ebb4caSwyllys 908*99ebb4caSwyllys /* Read the policy DB and verify it against the schema. */ 909*99ebb4caSwyllys doc = xmlCtxtReadFile(ctxt, filename, NULL, 910*99ebb4caSwyllys XML_PARSE_DTDVALID | XML_PARSE_NOERROR | XML_PARSE_NOWARNING); 911*99ebb4caSwyllys if (doc == NULL || ctxt->valid == 0) { 912*99ebb4caSwyllys ret = KMF_ERR_POLICY_DB_FORMAT; 913*99ebb4caSwyllys goto out; 914*99ebb4caSwyllys } 915*99ebb4caSwyllys 916*99ebb4caSwyllys cur = xmlDocGetRootElement(doc); 917*99ebb4caSwyllys if (cur == NULL) { 918*99ebb4caSwyllys ret = KMF_ERR_POLICY_DB_FORMAT; 919*99ebb4caSwyllys goto out; 920*99ebb4caSwyllys } 921*99ebb4caSwyllys 922*99ebb4caSwyllys node = cur->xmlChildrenNode; 923*99ebb4caSwyllys while (node != NULL && !found) { 924*99ebb4caSwyllys char *c; 925*99ebb4caSwyllys /* 926*99ebb4caSwyllys * Search for the policy that matches the given name. 927*99ebb4caSwyllys */ 928*99ebb4caSwyllys if (!xmlStrcmp((const xmlChar *)node->name, 929*99ebb4caSwyllys (const xmlChar *)KMF_POLICY_ELEMENT)) { 930*99ebb4caSwyllys /* Check the name attribute */ 931*99ebb4caSwyllys c = (char *)xmlGetProp(node, 932*99ebb4caSwyllys (const xmlChar *)KMF_POLICY_NAME_ATTR); 933*99ebb4caSwyllys 934*99ebb4caSwyllys /* If a match, parse the rest of the data */ 935*99ebb4caSwyllys if (c != NULL) { 936*99ebb4caSwyllys if (strcmp(c, policy_name) == 0) { 937*99ebb4caSwyllys ret = parsePolicyElement(node, plc); 938*99ebb4caSwyllys found = (ret == KMF_OK); 939*99ebb4caSwyllys } 940*99ebb4caSwyllys xmlFree(c); 941*99ebb4caSwyllys } 942*99ebb4caSwyllys } 943*99ebb4caSwyllys node = node->next; 944*99ebb4caSwyllys } 945*99ebb4caSwyllys 946*99ebb4caSwyllys if (!found) { 947*99ebb4caSwyllys ret = KMF_ERR_POLICY_NOT_FOUND; 948*99ebb4caSwyllys goto out; 949*99ebb4caSwyllys } 950*99ebb4caSwyllys 951*99ebb4caSwyllys out: 952*99ebb4caSwyllys if (ctxt != NULL) 953*99ebb4caSwyllys xmlFreeParserCtxt(ctxt); 954*99ebb4caSwyllys 955*99ebb4caSwyllys if (doc != NULL) 956*99ebb4caSwyllys xmlFreeDoc(doc); 957*99ebb4caSwyllys 958*99ebb4caSwyllys return (ret); 959*99ebb4caSwyllys } 960*99ebb4caSwyllys 961*99ebb4caSwyllys /* 962*99ebb4caSwyllys * KMF_SetPolicy 963*99ebb4caSwyllys * 964*99ebb4caSwyllys * Set the policy record in the handle. This searches 965*99ebb4caSwyllys * the policy DB for the named policy. If it is not found 966*99ebb4caSwyllys * or an error occurred in processing, the existing policy 967*99ebb4caSwyllys * is kept and an error code is returned. 968*99ebb4caSwyllys */ 969*99ebb4caSwyllys KMF_RETURN 970*99ebb4caSwyllys KMF_SetPolicy(KMF_HANDLE_T handle, char *policyfile, char *policyname) 971*99ebb4caSwyllys { 972*99ebb4caSwyllys KMF_RETURN ret = KMF_OK; 973*99ebb4caSwyllys KMF_POLICY_RECORD *newpolicy = NULL; 974*99ebb4caSwyllys 975*99ebb4caSwyllys CLEAR_ERROR(handle, ret); 976*99ebb4caSwyllys if (ret != KMF_OK) 977*99ebb4caSwyllys return (ret); 978*99ebb4caSwyllys 979*99ebb4caSwyllys newpolicy = malloc(sizeof (KMF_POLICY_RECORD)); 980*99ebb4caSwyllys if (newpolicy == NULL) 981*99ebb4caSwyllys return (KMF_ERR_MEMORY); 982*99ebb4caSwyllys (void) memset(newpolicy, 0, sizeof (KMF_POLICY_RECORD)); 983*99ebb4caSwyllys 984*99ebb4caSwyllys ret = KMF_GetPolicy( 985*99ebb4caSwyllys policyfile == NULL ? KMF_DEFAULT_POLICY_FILE : policyfile, 986*99ebb4caSwyllys policyname == NULL ? KMF_DEFAULT_POLICY_NAME : policyname, 987*99ebb4caSwyllys newpolicy); 988*99ebb4caSwyllys if (ret != KMF_OK) 989*99ebb4caSwyllys goto out; 990*99ebb4caSwyllys 991*99ebb4caSwyllys ret = KMF_VerifyPolicy(newpolicy); 992*99ebb4caSwyllys if (ret != KMF_OK) 993*99ebb4caSwyllys goto out; 994*99ebb4caSwyllys 995*99ebb4caSwyllys /* release the existing policy data (if any). */ 996*99ebb4caSwyllys if (handle->policy != NULL) { 997*99ebb4caSwyllys KMF_FreePolicyRecord(handle->policy); 998*99ebb4caSwyllys free(handle->policy); 999*99ebb4caSwyllys } 1000*99ebb4caSwyllys 1001*99ebb4caSwyllys handle->policy = newpolicy; 1002*99ebb4caSwyllys 1003*99ebb4caSwyllys out: 1004*99ebb4caSwyllys /* Cleanup any data allocated before the error occurred */ 1005*99ebb4caSwyllys if (ret != KMF_OK) { 1006*99ebb4caSwyllys KMF_FreePolicyRecord(newpolicy); 1007*99ebb4caSwyllys free(newpolicy); 1008*99ebb4caSwyllys } 1009*99ebb4caSwyllys 1010*99ebb4caSwyllys return (ret); 1011*99ebb4caSwyllys } 1012*99ebb4caSwyllys 1013*99ebb4caSwyllys 1014*99ebb4caSwyllys static KMF_RETURN 1015*99ebb4caSwyllys deletePolicyNode(xmlNodePtr node, char *policy_name) 1016*99ebb4caSwyllys { 1017*99ebb4caSwyllys KMF_RETURN ret = KMF_OK; 1018*99ebb4caSwyllys int found = 0; 1019*99ebb4caSwyllys xmlNodePtr dnode = NULL; 1020*99ebb4caSwyllys 1021*99ebb4caSwyllys while (node != NULL && !found) { 1022*99ebb4caSwyllys char *c; 1023*99ebb4caSwyllys /* 1024*99ebb4caSwyllys * Search for the policy that matches the given name. 1025*99ebb4caSwyllys */ 1026*99ebb4caSwyllys if (!xmlStrcmp((const xmlChar *)node->name, 1027*99ebb4caSwyllys (const xmlChar *)KMF_POLICY_ELEMENT)) { 1028*99ebb4caSwyllys /* Check the name attribute */ 1029*99ebb4caSwyllys c = (char *)xmlGetProp(node, 1030*99ebb4caSwyllys (const xmlChar *)KMF_POLICY_NAME_ATTR); 1031*99ebb4caSwyllys 1032*99ebb4caSwyllys /* If a match, parse the rest of the data */ 1033*99ebb4caSwyllys if (c != NULL) { 1034*99ebb4caSwyllys if (strcmp(c, policy_name) == 0) { 1035*99ebb4caSwyllys found = 1; 1036*99ebb4caSwyllys dnode = node; 1037*99ebb4caSwyllys } 1038*99ebb4caSwyllys xmlFree(c); 1039*99ebb4caSwyllys } 1040*99ebb4caSwyllys } 1041*99ebb4caSwyllys if (!found) 1042*99ebb4caSwyllys node = node->next; 1043*99ebb4caSwyllys } 1044*99ebb4caSwyllys 1045*99ebb4caSwyllys if (found && dnode != NULL) { 1046*99ebb4caSwyllys /* Unlink the node */ 1047*99ebb4caSwyllys xmlUnlinkNode(dnode); 1048*99ebb4caSwyllys 1049*99ebb4caSwyllys /* Delete it from the document tree */ 1050*99ebb4caSwyllys xmlFreeNode(dnode); 1051*99ebb4caSwyllys } else { 1052*99ebb4caSwyllys ret = KMF_ERR_POLICY_NOT_FOUND; 1053*99ebb4caSwyllys } 1054*99ebb4caSwyllys 1055*99ebb4caSwyllys return (ret); 1056*99ebb4caSwyllys } 1057*99ebb4caSwyllys 1058*99ebb4caSwyllys /* 1059*99ebb4caSwyllys * update_policyfile 1060*99ebb4caSwyllys * 1061*99ebb4caSwyllys * Attempt to do a "safe" file update as follows: 1062*99ebb4caSwyllys * 1. Lock the original file. 1063*99ebb4caSwyllys * 2. Create and write to a temporary file 1064*99ebb4caSwyllys * 3. Replace the original file with the temporary file. 1065*99ebb4caSwyllys */ 1066*99ebb4caSwyllys static KMF_RETURN 1067*99ebb4caSwyllys update_policyfile(xmlDocPtr doc, char *filename) 1068*99ebb4caSwyllys { 1069*99ebb4caSwyllys KMF_RETURN ret = KMF_OK; 1070*99ebb4caSwyllys FILE *pfile, *tmpfile; 1071*99ebb4caSwyllys char tmpfilename[MAXPATHLEN]; 1072*99ebb4caSwyllys char *p; 1073*99ebb4caSwyllys int prefix_len, tmpfd; 1074*99ebb4caSwyllys mode_t old_mode; 1075*99ebb4caSwyllys 1076*99ebb4caSwyllys /* 1077*99ebb4caSwyllys * Open and lock the DB file. First try to open an existing file, 1078*99ebb4caSwyllys * if that fails, open it as if it were new. 1079*99ebb4caSwyllys */ 1080*99ebb4caSwyllys if ((pfile = fopen(filename, "r+")) == NULL && errno == ENOENT) 1081*99ebb4caSwyllys pfile = fopen(filename, "w+"); 1082*99ebb4caSwyllys 1083*99ebb4caSwyllys if (pfile == NULL) 1084*99ebb4caSwyllys return (KMF_ERR_POLICY_DB_FILE); 1085*99ebb4caSwyllys 1086*99ebb4caSwyllys if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { 1087*99ebb4caSwyllys (void) fclose(pfile); 1088*99ebb4caSwyllys return (KMF_ERR_POLICY_DB_FILE); 1089*99ebb4caSwyllys } 1090*99ebb4caSwyllys 1091*99ebb4caSwyllys /* 1092*99ebb4caSwyllys * Create a temporary file to hold the new data. 1093*99ebb4caSwyllys */ 1094*99ebb4caSwyllys (void) memset(tmpfilename, 0, sizeof (tmpfilename)); 1095*99ebb4caSwyllys p = (char *)strrchr(filename, '/'); 1096*99ebb4caSwyllys if (p == NULL) { 1097*99ebb4caSwyllys /* 1098*99ebb4caSwyllys * filename contains basename only so we 1099*99ebb4caSwyllys * create a temp file in current directory. 1100*99ebb4caSwyllys */ 1101*99ebb4caSwyllys if (strlcpy(tmpfilename, TMPFILE_TEMPLATE, 1102*99ebb4caSwyllys sizeof (tmpfilename)) >= sizeof (tmpfilename)) 1103*99ebb4caSwyllys return (KMF_ERR_INTERNAL); 1104*99ebb4caSwyllys } else { 1105*99ebb4caSwyllys /* 1106*99ebb4caSwyllys * create a temp file in the same directory 1107*99ebb4caSwyllys * as the policy file. 1108*99ebb4caSwyllys */ 1109*99ebb4caSwyllys prefix_len = p - filename; 1110*99ebb4caSwyllys (void) strncpy(tmpfilename, filename, prefix_len); 1111*99ebb4caSwyllys (void) strncat(tmpfilename, "/", 1); 1112*99ebb4caSwyllys (void) strncat(tmpfilename, TMPFILE_TEMPLATE, 1113*99ebb4caSwyllys sizeof (TMPFILE_TEMPLATE)); 1114*99ebb4caSwyllys } 1115*99ebb4caSwyllys 1116*99ebb4caSwyllys old_mode = umask(077); 1117*99ebb4caSwyllys tmpfd = mkstemp(tmpfilename); 1118*99ebb4caSwyllys (void) umask(old_mode); 1119*99ebb4caSwyllys if (tmpfd == -1) { 1120*99ebb4caSwyllys return (KMF_ERR_POLICY_DB_FILE); 1121*99ebb4caSwyllys } 1122*99ebb4caSwyllys 1123*99ebb4caSwyllys if ((tmpfile = fdopen(tmpfd, "w")) == NULL) { 1124*99ebb4caSwyllys (void) close(tmpfd); 1125*99ebb4caSwyllys (void) unlink(tmpfilename); 1126*99ebb4caSwyllys (void) fclose(pfile); 1127*99ebb4caSwyllys return (KMF_ERR_POLICY_DB_FILE); 1128*99ebb4caSwyllys } 1129*99ebb4caSwyllys 1130*99ebb4caSwyllys /* 1131*99ebb4caSwyllys * Write the new info to the temporary file. 1132*99ebb4caSwyllys */ 1133*99ebb4caSwyllys if (xmlDocFormatDump(tmpfile, doc, 1) == -1) { 1134*99ebb4caSwyllys (void) fclose(pfile); 1135*99ebb4caSwyllys (void) fclose(tmpfile); 1136*99ebb4caSwyllys (void) unlink(tmpfilename); 1137*99ebb4caSwyllys return (KMF_ERR_POLICY_ENGINE); 1138*99ebb4caSwyllys } 1139*99ebb4caSwyllys 1140*99ebb4caSwyllys (void) fclose(pfile); 1141*99ebb4caSwyllys 1142*99ebb4caSwyllys if (fchmod(tmpfd, 1143*99ebb4caSwyllys S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 1144*99ebb4caSwyllys (void) close(tmpfd); 1145*99ebb4caSwyllys (void) unlink(tmpfilename); 1146*99ebb4caSwyllys return (KMF_ERR_POLICY_DB_FILE); 1147*99ebb4caSwyllys } 1148*99ebb4caSwyllys if (fclose(tmpfile) != 0) 1149*99ebb4caSwyllys return (KMF_ERR_POLICY_DB_FILE); 1150*99ebb4caSwyllys 1151*99ebb4caSwyllys /* 1152*99ebb4caSwyllys * Replace the original file with the updated tempfile. 1153*99ebb4caSwyllys */ 1154*99ebb4caSwyllys if (rename(tmpfilename, filename) == -1) { 1155*99ebb4caSwyllys ret = KMF_ERR_POLICY_DB_FILE; 1156*99ebb4caSwyllys } 1157*99ebb4caSwyllys 1158*99ebb4caSwyllys if (ret != KMF_OK) { 1159*99ebb4caSwyllys /* try to remove the tmp file */ 1160*99ebb4caSwyllys (void) unlink(tmpfilename); 1161*99ebb4caSwyllys } 1162*99ebb4caSwyllys 1163*99ebb4caSwyllys return (ret); 1164*99ebb4caSwyllys } 1165*99ebb4caSwyllys 1166*99ebb4caSwyllys /* 1167*99ebb4caSwyllys * DeletePolicyFromDB 1168*99ebb4caSwyllys * 1169*99ebb4caSwyllys * Find a policy by name and remove it from the policy DB file. 1170*99ebb4caSwyllys * If the policy is not found, return an error. 1171*99ebb4caSwyllys */ 1172*99ebb4caSwyllys KMF_RETURN 1173*99ebb4caSwyllys KMF_DeletePolicyFromDB(char *policy_name, char *dbfilename) 1174*99ebb4caSwyllys { 1175*99ebb4caSwyllys KMF_RETURN ret; 1176*99ebb4caSwyllys xmlParserCtxtPtr ctxt = NULL; 1177*99ebb4caSwyllys xmlDocPtr doc = NULL; 1178*99ebb4caSwyllys xmlNodePtr cur, node; 1179*99ebb4caSwyllys 1180*99ebb4caSwyllys if (policy_name == NULL || dbfilename == NULL) 1181*99ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 1182*99ebb4caSwyllys 1183*99ebb4caSwyllys /* 1184*99ebb4caSwyllys * Cannot delete the default policy record from the system 1185*99ebb4caSwyllys * default policy database (/etc/security/kmfpolicy.xml). 1186*99ebb4caSwyllys */ 1187*99ebb4caSwyllys if (strcmp(dbfilename, KMF_DEFAULT_POLICY_FILE) == 0 && 1188*99ebb4caSwyllys strcmp(policy_name, KMF_DEFAULT_POLICY_NAME) == 0) 1189*99ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 1190*99ebb4caSwyllys 1191*99ebb4caSwyllys /* Make sure the policy file exists */ 1192*99ebb4caSwyllys if (access(dbfilename, R_OK | W_OK)) 1193*99ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 1194*99ebb4caSwyllys 1195*99ebb4caSwyllys /* Read the policy DB and verify it against the schema. */ 1196*99ebb4caSwyllys ctxt = xmlNewParserCtxt(); 1197*99ebb4caSwyllys if (ctxt == NULL) 1198*99ebb4caSwyllys return (KMF_ERR_POLICY_DB_FORMAT); 1199*99ebb4caSwyllys 1200*99ebb4caSwyllys doc = xmlCtxtReadFile(ctxt, dbfilename, NULL, 1201*99ebb4caSwyllys XML_PARSE_DTDVALID | XML_PARSE_NOERROR | XML_PARSE_NOWARNING); 1202*99ebb4caSwyllys if (doc == NULL || ctxt->valid == 0) { 1203*99ebb4caSwyllys ret = KMF_ERR_POLICY_DB_FORMAT; 1204*99ebb4caSwyllys goto end; 1205*99ebb4caSwyllys } 1206*99ebb4caSwyllys 1207*99ebb4caSwyllys cur = xmlDocGetRootElement(doc); 1208*99ebb4caSwyllys if (cur == NULL) { 1209*99ebb4caSwyllys xmlFreeDoc(doc); 1210*99ebb4caSwyllys return (KMF_ERR_POLICY_DB_FORMAT); 1211*99ebb4caSwyllys } 1212*99ebb4caSwyllys node = cur->xmlChildrenNode; 1213*99ebb4caSwyllys 1214*99ebb4caSwyllys ret = deletePolicyNode(node, policy_name); 1215*99ebb4caSwyllys 1216*99ebb4caSwyllys if (ret == KMF_OK) 1217*99ebb4caSwyllys ret = update_policyfile(doc, dbfilename); 1218*99ebb4caSwyllys 1219*99ebb4caSwyllys end: 1220*99ebb4caSwyllys if (ctxt != NULL) 1221*99ebb4caSwyllys xmlFreeParserCtxt(ctxt); 1222*99ebb4caSwyllys 1223*99ebb4caSwyllys if (doc != NULL) 1224*99ebb4caSwyllys xmlFreeDoc(doc); 1225*99ebb4caSwyllys 1226*99ebb4caSwyllys return (ret); 1227*99ebb4caSwyllys } 1228*99ebb4caSwyllys 1229*99ebb4caSwyllys /* 1230*99ebb4caSwyllys * Add a new policy node to the Policy DB XML tree. 1231*99ebb4caSwyllys */ 1232*99ebb4caSwyllys static KMF_RETURN 1233*99ebb4caSwyllys addPolicyNode(xmlNodePtr pnode, KMF_POLICY_RECORD *policy) 1234*99ebb4caSwyllys { 1235*99ebb4caSwyllys KMF_RETURN ret = KMF_OK; 1236*99ebb4caSwyllys 1237*99ebb4caSwyllys if (pnode != NULL && policy != NULL) { 1238*99ebb4caSwyllys if (newprop(pnode, KMF_POLICY_NAME_ATTR, policy->name) != 0) { 1239*99ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 1240*99ebb4caSwyllys goto out; 1241*99ebb4caSwyllys } 1242*99ebb4caSwyllys if (policy->ignore_date) { 1243*99ebb4caSwyllys if (newprop(pnode, KMF_OPTIONS_IGNORE_DATE_ATTR, 1244*99ebb4caSwyllys "TRUE")) { 1245*99ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 1246*99ebb4caSwyllys goto out; 1247*99ebb4caSwyllys } 1248*99ebb4caSwyllys } 1249*99ebb4caSwyllys 1250*99ebb4caSwyllys if (policy->ignore_unknown_ekus) { 1251*99ebb4caSwyllys if (newprop(pnode, KMF_OPTIONS_IGNORE_UNKNOWN_EKUS, 1252*99ebb4caSwyllys "TRUE")) { 1253*99ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 1254*99ebb4caSwyllys goto out; 1255*99ebb4caSwyllys } 1256*99ebb4caSwyllys } 1257*99ebb4caSwyllys 1258*99ebb4caSwyllys if (policy->ignore_trust_anchor) { 1259*99ebb4caSwyllys if (newprop(pnode, KMF_OPTIONS_IGNORE_TRUST_ANCHOR, 1260*99ebb4caSwyllys "TRUE")) { 1261*99ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 1262*99ebb4caSwyllys goto out; 1263*99ebb4caSwyllys } 1264*99ebb4caSwyllys } 1265*99ebb4caSwyllys 1266*99ebb4caSwyllys if (policy->validity_adjusttime) { 1267*99ebb4caSwyllys if (newprop(pnode, KMF_OPTIONS_VALIDITY_ADJUSTTIME, 1268*99ebb4caSwyllys policy->validity_adjusttime)) { 1269*99ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 1270*99ebb4caSwyllys goto out; 1271*99ebb4caSwyllys } 1272*99ebb4caSwyllys } 1273*99ebb4caSwyllys 1274*99ebb4caSwyllys if (newprop(pnode, KMF_POLICY_TA_NAME_ATTR, 1275*99ebb4caSwyllys policy->ta_name) != 0) { 1276*99ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 1277*99ebb4caSwyllys goto out; 1278*99ebb4caSwyllys } 1279*99ebb4caSwyllys 1280*99ebb4caSwyllys if (newprop(pnode, KMF_POLICY_TA_SERIAL_ATTR, 1281*99ebb4caSwyllys policy->ta_serial) != 0) { 1282*99ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 1283*99ebb4caSwyllys goto out; 1284*99ebb4caSwyllys } 1285*99ebb4caSwyllys 1286*99ebb4caSwyllys /* Add a text node for readability */ 1287*99ebb4caSwyllys addFormatting(pnode, "\n"); 1288*99ebb4caSwyllys 1289*99ebb4caSwyllys if (ret = AddValidationNodes(pnode, policy)) { 1290*99ebb4caSwyllys goto out; 1291*99ebb4caSwyllys } 1292*99ebb4caSwyllys 1293*99ebb4caSwyllys if ((ret = AddKeyUsageNodes(pnode, policy->ku_bits))) { 1294*99ebb4caSwyllys goto out; 1295*99ebb4caSwyllys } 1296*99ebb4caSwyllys 1297*99ebb4caSwyllys if ((ret = AddExtKeyUsageNodes(pnode, &policy->eku_set))) { 1298*99ebb4caSwyllys goto out; 1299*99ebb4caSwyllys } 1300*99ebb4caSwyllys } else { 1301*99ebb4caSwyllys ret = KMF_ERR_BAD_PARAMETER; 1302*99ebb4caSwyllys } 1303*99ebb4caSwyllys out: 1304*99ebb4caSwyllys if (ret != KMF_OK && pnode != NULL) { 1305*99ebb4caSwyllys xmlUnlinkNode(pnode); 1306*99ebb4caSwyllys xmlFreeNode(pnode); 1307*99ebb4caSwyllys } 1308*99ebb4caSwyllys 1309*99ebb4caSwyllys return (ret); 1310*99ebb4caSwyllys } 1311*99ebb4caSwyllys 1312*99ebb4caSwyllys 1313*99ebb4caSwyllys KMF_RETURN 1314*99ebb4caSwyllys KMF_VerifyPolicy(KMF_POLICY_RECORD *policy) 1315*99ebb4caSwyllys { 1316*99ebb4caSwyllys KMF_RETURN ret = KMF_OK; 1317*99ebb4caSwyllys boolean_t has_ta; 1318*99ebb4caSwyllys 1319*99ebb4caSwyllys if (policy->name == NULL || !strlen(policy->name)) 1320*99ebb4caSwyllys return (KMF_ERR_POLICY_NAME); 1321*99ebb4caSwyllys 1322*99ebb4caSwyllys /* Check the TA related policy */ 1323*99ebb4caSwyllys if (policy->ta_name != NULL && policy->ta_serial != NULL) { 1324*99ebb4caSwyllys has_ta = B_TRUE; 1325*99ebb4caSwyllys } else if (policy->ta_name == NULL && policy->ta_serial == NULL) { 1326*99ebb4caSwyllys has_ta = B_FALSE; 1327*99ebb4caSwyllys } else { 1328*99ebb4caSwyllys /* 1329*99ebb4caSwyllys * If the TA cert is set, then both name and serial number 1330*99ebb4caSwyllys * need to be specified. 1331*99ebb4caSwyllys */ 1332*99ebb4caSwyllys return (KMF_ERR_TA_POLICY); 1333*99ebb4caSwyllys } 1334*99ebb4caSwyllys 1335*99ebb4caSwyllys if (has_ta == B_FALSE && policy->ignore_trust_anchor == B_FALSE) 1336*99ebb4caSwyllys return (KMF_ERR_TA_POLICY); 1337*99ebb4caSwyllys 1338*99ebb4caSwyllys if (policy->revocation & KMF_REVOCATION_METHOD_OCSP) { 1339*99ebb4caSwyllys /* 1340*99ebb4caSwyllys * For OCSP, either use a fixed responder or use the 1341*99ebb4caSwyllys * value from the cert, but not both. 1342*99ebb4caSwyllys */ 1343*99ebb4caSwyllys if ((policy->VAL_OCSP_BASIC.responderURI == NULL && 1344*99ebb4caSwyllys policy->VAL_OCSP_BASIC.uri_from_cert == B_FALSE) || 1345*99ebb4caSwyllys (policy->VAL_OCSP_BASIC.responderURI != NULL && 1346*99ebb4caSwyllys policy->VAL_OCSP_BASIC.uri_from_cert == B_TRUE)) 1347*99ebb4caSwyllys return (KMF_ERR_OCSP_POLICY); 1348*99ebb4caSwyllys 1349*99ebb4caSwyllys /* 1350*99ebb4caSwyllys * If the OCSP responder cert is set, then both name and serial 1351*99ebb4caSwyllys * number need to be specified. 1352*99ebb4caSwyllys */ 1353*99ebb4caSwyllys if ((policy->VAL_OCSP_RESP_CERT.name != NULL && 1354*99ebb4caSwyllys policy->VAL_OCSP_RESP_CERT.serial == NULL) || 1355*99ebb4caSwyllys (policy->VAL_OCSP_RESP_CERT.name == NULL && 1356*99ebb4caSwyllys policy->VAL_OCSP_RESP_CERT.serial != NULL)) 1357*99ebb4caSwyllys return (KMF_ERR_OCSP_POLICY); 1358*99ebb4caSwyllys } 1359*99ebb4caSwyllys 1360*99ebb4caSwyllys return (ret); 1361*99ebb4caSwyllys } 1362*99ebb4caSwyllys 1363*99ebb4caSwyllys /* 1364*99ebb4caSwyllys * Update the KMF policy file by creating a new XML Policy doc tree 1365*99ebb4caSwyllys * from the data in the KMF_POLICY_RECORD structure. If "check_policy" 1366*99ebb4caSwyllys * is true, then we check the policy sanity also. 1367*99ebb4caSwyllys */ 1368*99ebb4caSwyllys KMF_RETURN 1369*99ebb4caSwyllys KMF_AddPolicyToDB(KMF_POLICY_RECORD *policy, char *dbfilename, 1370*99ebb4caSwyllys boolean_t check_policy) 1371*99ebb4caSwyllys { 1372*99ebb4caSwyllys KMF_RETURN ret = KMF_OK; 1373*99ebb4caSwyllys xmlDocPtr doc = NULL; 1374*99ebb4caSwyllys xmlNodePtr root, node; 1375*99ebb4caSwyllys xmlParserCtxtPtr ctxt = NULL; 1376*99ebb4caSwyllys 1377*99ebb4caSwyllys if (policy == NULL || dbfilename == NULL) 1378*99ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 1379*99ebb4caSwyllys 1380*99ebb4caSwyllys if (check_policy == B_TRUE) { 1381*99ebb4caSwyllys if (ret = KMF_VerifyPolicy(policy)) 1382*99ebb4caSwyllys return (ret); 1383*99ebb4caSwyllys } 1384*99ebb4caSwyllys 1385*99ebb4caSwyllys /* If the policyDB exists, load it into memory */ 1386*99ebb4caSwyllys if (!access(dbfilename, R_OK)) { 1387*99ebb4caSwyllys 1388*99ebb4caSwyllys /* Create a parser context */ 1389*99ebb4caSwyllys ctxt = xmlNewParserCtxt(); 1390*99ebb4caSwyllys if (ctxt == NULL) 1391*99ebb4caSwyllys return (KMF_ERR_POLICY_DB_FORMAT); 1392*99ebb4caSwyllys 1393*99ebb4caSwyllys doc = xmlCtxtReadFile(ctxt, dbfilename, NULL, 1394*99ebb4caSwyllys XML_PARSE_DTDVALID | XML_PARSE_NOERROR | 1395*99ebb4caSwyllys XML_PARSE_NOWARNING); 1396*99ebb4caSwyllys if (doc == NULL || ctxt->valid == 0) { 1397*99ebb4caSwyllys ret = KMF_ERR_POLICY_DB_FORMAT; 1398*99ebb4caSwyllys goto out; 1399*99ebb4caSwyllys } 1400*99ebb4caSwyllys 1401*99ebb4caSwyllys root = xmlDocGetRootElement(doc); 1402*99ebb4caSwyllys if (root == NULL) { 1403*99ebb4caSwyllys ret = KMF_ERR_POLICY_DB_FORMAT; 1404*99ebb4caSwyllys goto out; 1405*99ebb4caSwyllys } 1406*99ebb4caSwyllys 1407*99ebb4caSwyllys node = root->xmlChildrenNode; 1408*99ebb4caSwyllys /* 1409*99ebb4caSwyllys * If the DB has an existing policy of the 1410*99ebb4caSwyllys * same name, delete it from the tree. 1411*99ebb4caSwyllys */ 1412*99ebb4caSwyllys ret = deletePolicyNode(node, policy->name); 1413*99ebb4caSwyllys if (ret == KMF_ERR_POLICY_NOT_FOUND) 1414*99ebb4caSwyllys ret = KMF_OK; 1415*99ebb4caSwyllys } else { 1416*99ebb4caSwyllys /* Initialize a new DB tree */ 1417*99ebb4caSwyllys doc = xmlNewDoc((const xmlChar *)"1.0"); 1418*99ebb4caSwyllys if (doc == NULL) 1419*99ebb4caSwyllys return (KMF_ERR_POLICY_ENGINE); 1420*99ebb4caSwyllys 1421*99ebb4caSwyllys /* 1422*99ebb4caSwyllys * Add the DOCTYPE header to the tree so the 1423*99ebb4caSwyllys * DTD link is embedded 1424*99ebb4caSwyllys */ 1425*99ebb4caSwyllys doc->intSubset = xmlCreateIntSubset(doc, 1426*99ebb4caSwyllys (const xmlChar *)KMF_POLICY_ROOT, 1427*99ebb4caSwyllys NULL, (const xmlChar *)KMF_POLICY_DTD); 1428*99ebb4caSwyllys 1429*99ebb4caSwyllys root = xmlNewDocNode(doc, NULL, 1430*99ebb4caSwyllys (const xmlChar *)KMF_POLICY_ROOT, NULL); 1431*99ebb4caSwyllys if (root != NULL) { 1432*99ebb4caSwyllys xmlDocSetRootElement(doc, root); 1433*99ebb4caSwyllys } 1434*99ebb4caSwyllys } 1435*99ebb4caSwyllys 1436*99ebb4caSwyllys /* Append the new policy info to the root node. */ 1437*99ebb4caSwyllys if (root != NULL) { 1438*99ebb4caSwyllys xmlNodePtr pnode; 1439*99ebb4caSwyllys 1440*99ebb4caSwyllys pnode = xmlNewChild(root, NULL, 1441*99ebb4caSwyllys (const xmlChar *)KMF_POLICY_ELEMENT, NULL); 1442*99ebb4caSwyllys 1443*99ebb4caSwyllys ret = addPolicyNode(pnode, policy); 1444*99ebb4caSwyllys /* If that worked, update the DB file. */ 1445*99ebb4caSwyllys if (ret == KMF_OK) 1446*99ebb4caSwyllys ret = update_policyfile(doc, dbfilename); 1447*99ebb4caSwyllys } else { 1448*99ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 1449*99ebb4caSwyllys } 1450*99ebb4caSwyllys 1451*99ebb4caSwyllys 1452*99ebb4caSwyllys out: 1453*99ebb4caSwyllys if (ctxt != NULL) 1454*99ebb4caSwyllys xmlFreeParserCtxt(ctxt); 1455*99ebb4caSwyllys 1456*99ebb4caSwyllys if (doc != NULL) 1457*99ebb4caSwyllys xmlFreeDoc(doc); 1458*99ebb4caSwyllys 1459*99ebb4caSwyllys return (ret); 1460*99ebb4caSwyllys } 1461