199ebb4caSwyllys /* 299ebb4caSwyllys * CDDL HEADER START 399ebb4caSwyllys * 499ebb4caSwyllys * The contents of this file are subject to the terms of the 599ebb4caSwyllys * Common Development and Distribution License (the "License"). 699ebb4caSwyllys * You may not use this file except in compliance with the License. 799ebb4caSwyllys * 899ebb4caSwyllys * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 999ebb4caSwyllys * or http://www.opensolaris.org/os/licensing. 1099ebb4caSwyllys * See the License for the specific language governing permissions 1199ebb4caSwyllys * and limitations under the License. 1299ebb4caSwyllys * 1399ebb4caSwyllys * When distributing Covered Code, include this CDDL HEADER in each 1499ebb4caSwyllys * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1599ebb4caSwyllys * If applicable, add the following below this CDDL HEADER, with the 1699ebb4caSwyllys * fields enclosed by brackets "[]" replaced with your own identifying 1799ebb4caSwyllys * information: Portions Copyright [yyyy] [name of copyright owner] 1899ebb4caSwyllys * 1999ebb4caSwyllys * CDDL HEADER END 20*269e59f9SJan Pechanec * 21*269e59f9SJan Pechanec * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 2299ebb4caSwyllys */ 2399ebb4caSwyllys 2499ebb4caSwyllys #include <stdlib.h> 2599ebb4caSwyllys #include <ctype.h> 2699ebb4caSwyllys #include <strings.h> 2799ebb4caSwyllys #include <unistd.h> 2899ebb4caSwyllys #include <errno.h> 29*269e59f9SJan Pechanec #include <libgen.h> 3099ebb4caSwyllys #include <sys/param.h> 3199ebb4caSwyllys #include <sys/stat.h> 3299ebb4caSwyllys 3399ebb4caSwyllys #include <kmfapiP.h> 3499ebb4caSwyllys #include <libxml/tree.h> 3599ebb4caSwyllys #include <libxml/parser.h> 3699ebb4caSwyllys 3799ebb4caSwyllys typedef struct { 3899ebb4caSwyllys char *ekuname; 3999ebb4caSwyllys KMF_OID *oid; 4099ebb4caSwyllys } EKUName2OID; 4199ebb4caSwyllys 4299ebb4caSwyllys static EKUName2OID EKUList[] = { 4399ebb4caSwyllys {"serverAuth", (KMF_OID *)&KMFOID_PKIX_KP_ServerAuth}, 4499ebb4caSwyllys {"clientAuth", (KMF_OID *)&KMFOID_PKIX_KP_ClientAuth}, 4599ebb4caSwyllys {"codeSigning", (KMF_OID *)&KMFOID_PKIX_KP_CodeSigning}, 4699ebb4caSwyllys {"emailProtection", (KMF_OID *)&KMFOID_PKIX_KP_EmailProtection}, 4799ebb4caSwyllys {"ipsecEndSystem", (KMF_OID *)&KMFOID_PKIX_KP_IPSecEndSystem}, 4899ebb4caSwyllys {"ipsecTunnel", (KMF_OID *)&KMFOID_PKIX_KP_IPSecTunnel}, 4999ebb4caSwyllys {"ipsecUser", (KMF_OID *)&KMFOID_PKIX_KP_IPSecUser}, 5099ebb4caSwyllys {"timeStamping", (KMF_OID *)&KMFOID_PKIX_KP_TimeStamping}, 5172ca8cc9SWyllys Ingersoll {"OCSPSigning", (KMF_OID *)&KMFOID_PKIX_KP_OCSPSigning}, 5272ca8cc9SWyllys Ingersoll {"KPClientAuth", (KMF_OID *)&KMFOID_PKINIT_ClientAuth}, 5372ca8cc9SWyllys Ingersoll {"KPKdc", (KMF_OID *)&KMFOID_PKINIT_Kdc}, 5472ca8cc9SWyllys Ingersoll {"scLogon", (KMF_OID *)&KMFOID_MS_KP_SCLogon} 5599ebb4caSwyllys }; 5699ebb4caSwyllys 5799ebb4caSwyllys static int num_ekus = sizeof (EKUList) / sizeof (EKUName2OID); 5899ebb4caSwyllys 5999ebb4caSwyllys static void 6099ebb4caSwyllys addFormatting(xmlNodePtr parent, char *text) 6199ebb4caSwyllys { 6299ebb4caSwyllys xmlNodePtr snode; 6399ebb4caSwyllys 6499ebb4caSwyllys if (parent == NULL || text == NULL) 6599ebb4caSwyllys return; 6699ebb4caSwyllys 6799ebb4caSwyllys snode = xmlNewText((const xmlChar *)text); 6899ebb4caSwyllys if (snode != NULL) { 695ad42b1bSSurya Prakki (void) xmlAddChild(parent, snode); 7099ebb4caSwyllys } 7199ebb4caSwyllys } 7299ebb4caSwyllys 7399ebb4caSwyllys static void 7499ebb4caSwyllys parseOCSPValidation(xmlNodePtr node, KMF_VALIDATION_POLICY *vinfo) 7599ebb4caSwyllys { 7699ebb4caSwyllys xmlNodePtr n; 7799ebb4caSwyllys char *c; 7899ebb4caSwyllys n = node->children; 7999ebb4caSwyllys while (n != NULL) { 8099ebb4caSwyllys if (!xmlStrcmp((const xmlChar *)n->name, 8130a5e8faSwyllys (const xmlChar *)KMF_OCSP_BASIC_ELEMENT)) { 8299ebb4caSwyllys 8399ebb4caSwyllys vinfo->ocsp_info.basic.responderURI = 8499ebb4caSwyllys (char *)xmlGetProp(n, 8599ebb4caSwyllys (const xmlChar *)KMF_OCSP_RESPONDER_ATTR); 8699ebb4caSwyllys 8799ebb4caSwyllys vinfo->ocsp_info.basic.proxy = (char *)xmlGetProp(n, 8899ebb4caSwyllys (const xmlChar *)KMF_OCSP_PROXY_ATTR); 8999ebb4caSwyllys 9099ebb4caSwyllys c = (char *)xmlGetProp(n, 9199ebb4caSwyllys (const xmlChar *)KMF_OCSP_URI_ATTR); 9299ebb4caSwyllys if (c != NULL && !strcasecmp(c, "true")) { 9399ebb4caSwyllys vinfo->ocsp_info.basic.uri_from_cert = 1; 9499ebb4caSwyllys xmlFree(c); 9599ebb4caSwyllys } 9699ebb4caSwyllys 9799ebb4caSwyllys vinfo->ocsp_info.basic.response_lifetime = 9899ebb4caSwyllys (char *)xmlGetProp(n, 9999ebb4caSwyllys (const xmlChar *)KMF_OCSP_RESPONSE_LIFETIME_ATTR); 10099ebb4caSwyllys 10199ebb4caSwyllys c = (char *)xmlGetProp(n, 10299ebb4caSwyllys (const xmlChar *)KMF_OCSP_IGNORE_SIGN_ATTR); 10399ebb4caSwyllys if (c != NULL && !strcasecmp(c, "true")) { 10499ebb4caSwyllys vinfo->ocsp_info.basic.ignore_response_sign = 1; 10599ebb4caSwyllys xmlFree(c); 10699ebb4caSwyllys } 10799ebb4caSwyllys 10899ebb4caSwyllys } else if (!xmlStrcmp((const xmlChar *)n->name, 10999ebb4caSwyllys (const xmlChar *)KMF_OCSP_RESPONDER_CERT_ELEMENT)) { 11099ebb4caSwyllys 11199ebb4caSwyllys vinfo->ocsp_info.resp_cert.name = 11299ebb4caSwyllys (char *)xmlGetProp(n, 11399ebb4caSwyllys (const xmlChar *)KMF_CERT_NAME_ATTR); 11499ebb4caSwyllys vinfo->ocsp_info.resp_cert.serial = 11530a5e8faSwyllys (char *)xmlGetProp(n, 11630a5e8faSwyllys (const xmlChar *)KMF_CERT_SERIAL_ATTR); 11799ebb4caSwyllys vinfo->ocsp_info.has_resp_cert = 1; 11899ebb4caSwyllys } 11999ebb4caSwyllys 12099ebb4caSwyllys n = n->next; 12199ebb4caSwyllys } 12299ebb4caSwyllys 12399ebb4caSwyllys } 12499ebb4caSwyllys 12599ebb4caSwyllys /* 12699ebb4caSwyllys * Parse the "validation-methods" section of the policy. 12799ebb4caSwyllys */ 12899ebb4caSwyllys static void 12999ebb4caSwyllys parseValidation(xmlNodePtr node, KMF_VALIDATION_POLICY *vinfo, 13099ebb4caSwyllys KMF_POLICY_RECORD *policy) 13199ebb4caSwyllys { 13299ebb4caSwyllys xmlNodePtr n; 13399ebb4caSwyllys char *c; 13499ebb4caSwyllys n = node->children; 13599ebb4caSwyllys while (n != NULL) { 13699ebb4caSwyllys if (!xmlStrcmp((const xmlChar *)n->name, 13730a5e8faSwyllys (const xmlChar *)KMF_OCSP_ELEMENT)) { 13899ebb4caSwyllys 13999ebb4caSwyllys parseOCSPValidation(n, &policy->validation_info); 14099ebb4caSwyllys policy->revocation |= KMF_REVOCATION_METHOD_OCSP; 14199ebb4caSwyllys 14299ebb4caSwyllys 14399ebb4caSwyllys } else if (!xmlStrcmp((const xmlChar *)n->name, 14430a5e8faSwyllys (const xmlChar *)KMF_CRL_ELEMENT)) { 14599ebb4caSwyllys 14699ebb4caSwyllys vinfo->crl_info.basefilename = (char *)xmlGetProp(n, 14730a5e8faSwyllys (const xmlChar *)KMF_CRL_BASENAME_ATTR); 14899ebb4caSwyllys 14999ebb4caSwyllys vinfo->crl_info.directory = (char *)xmlGetProp(n, 15030a5e8faSwyllys (const xmlChar *)KMF_CRL_DIRECTORY_ATTR); 15199ebb4caSwyllys 15299ebb4caSwyllys c = (char *)xmlGetProp(n, 15330a5e8faSwyllys (const xmlChar *)KMF_CRL_GET_URI_ATTR); 15499ebb4caSwyllys if (c != NULL && !strcasecmp(c, "true")) { 15599ebb4caSwyllys vinfo->crl_info.get_crl_uri = 1; 15699ebb4caSwyllys } else { 15799ebb4caSwyllys vinfo->crl_info.get_crl_uri = 0; 15899ebb4caSwyllys } 15999ebb4caSwyllys xmlFree(c); 16099ebb4caSwyllys 16199ebb4caSwyllys vinfo->crl_info.proxy = (char *)xmlGetProp(n, 16299ebb4caSwyllys (const xmlChar *)KMF_CRL_PROXY_ATTR); 16399ebb4caSwyllys 16499ebb4caSwyllys c = (char *)xmlGetProp(n, 16530a5e8faSwyllys (const xmlChar *)KMF_CRL_IGNORE_SIGN_ATTR); 16699ebb4caSwyllys if (c != NULL && !strcasecmp(c, "true")) { 16799ebb4caSwyllys vinfo->crl_info.ignore_crl_sign = 1; 16899ebb4caSwyllys } else { 16999ebb4caSwyllys vinfo->crl_info.ignore_crl_sign = 0; 17099ebb4caSwyllys } 17199ebb4caSwyllys xmlFree(c); 17299ebb4caSwyllys 17399ebb4caSwyllys c = (char *)xmlGetProp(n, 17430a5e8faSwyllys (const xmlChar *)KMF_CRL_IGNORE_DATE_ATTR); 17599ebb4caSwyllys if (c != NULL && !strcasecmp(c, "true")) { 17699ebb4caSwyllys vinfo->crl_info.ignore_crl_date = 1; 17799ebb4caSwyllys } else { 17899ebb4caSwyllys vinfo->crl_info.ignore_crl_date = 0; 17999ebb4caSwyllys } 18099ebb4caSwyllys xmlFree(c); 18199ebb4caSwyllys 18299ebb4caSwyllys policy->revocation |= KMF_REVOCATION_METHOD_CRL; 18399ebb4caSwyllys } 18499ebb4caSwyllys 18599ebb4caSwyllys n = n->next; 18699ebb4caSwyllys } 18799ebb4caSwyllys } 18899ebb4caSwyllys 18999ebb4caSwyllys char * 19030a5e8faSwyllys kmf_ku_to_string(uint32_t bitfield) 19199ebb4caSwyllys { 19299ebb4caSwyllys if (bitfield & KMF_digitalSignature) 19399ebb4caSwyllys return ("digitalSignature"); 19499ebb4caSwyllys 19599ebb4caSwyllys if (bitfield & KMF_nonRepudiation) 19699ebb4caSwyllys return ("nonRepudiation"); 19799ebb4caSwyllys 19899ebb4caSwyllys if (bitfield & KMF_keyEncipherment) 19999ebb4caSwyllys return ("keyEncipherment"); 20099ebb4caSwyllys 20199ebb4caSwyllys if (bitfield & KMF_dataEncipherment) 20299ebb4caSwyllys return ("dataEncipherment"); 20399ebb4caSwyllys 20499ebb4caSwyllys if (bitfield & KMF_keyAgreement) 20599ebb4caSwyllys return ("keyAgreement"); 20699ebb4caSwyllys 20799ebb4caSwyllys if (bitfield & KMF_keyCertSign) 20899ebb4caSwyllys return ("keyCertSign"); 20999ebb4caSwyllys 21099ebb4caSwyllys if (bitfield & KMF_cRLSign) 21199ebb4caSwyllys return ("cRLSign"); 21299ebb4caSwyllys 21399ebb4caSwyllys if (bitfield & KMF_encipherOnly) 21499ebb4caSwyllys return ("encipherOnly"); 21599ebb4caSwyllys 21699ebb4caSwyllys if (bitfield & KMF_decipherOnly) 21799ebb4caSwyllys return ("decipherOnly"); 21899ebb4caSwyllys 21999ebb4caSwyllys return (NULL); 22099ebb4caSwyllys } 22199ebb4caSwyllys 22230a5e8faSwyllys uint32_t 22330a5e8faSwyllys kmf_string_to_ku(char *kustring) 22499ebb4caSwyllys { 22599ebb4caSwyllys if (kustring == NULL || !strlen(kustring)) 22699ebb4caSwyllys return (0); 22799ebb4caSwyllys if (strcasecmp(kustring, "digitalSignature") == 0) 22899ebb4caSwyllys return (KMF_digitalSignature); 22999ebb4caSwyllys if (strcasecmp(kustring, "nonRepudiation") == 0) 23099ebb4caSwyllys return (KMF_nonRepudiation); 23199ebb4caSwyllys if (strcasecmp(kustring, "keyEncipherment") == 0) 23299ebb4caSwyllys return (KMF_keyEncipherment); 23399ebb4caSwyllys if (strcasecmp(kustring, "dataEncipherment") == 0) 23499ebb4caSwyllys return (KMF_dataEncipherment); 23599ebb4caSwyllys if (strcasecmp(kustring, "keyAgreement") == 0) 23699ebb4caSwyllys return (KMF_keyAgreement); 23799ebb4caSwyllys if (strcasecmp(kustring, "keyCertSign") == 0) 23899ebb4caSwyllys return (KMF_keyCertSign); 23999ebb4caSwyllys if (strcasecmp(kustring, "cRLSign") == 0) 24099ebb4caSwyllys return (KMF_cRLSign); 24199ebb4caSwyllys if (strcasecmp(kustring, "encipherOnly") == 0) 24299ebb4caSwyllys return (KMF_encipherOnly); 24399ebb4caSwyllys if (strcasecmp(kustring, "decipherOnly") == 0) 24499ebb4caSwyllys return (KMF_decipherOnly); 24599ebb4caSwyllys 24699ebb4caSwyllys return (0); 24799ebb4caSwyllys } 24899ebb4caSwyllys 24999ebb4caSwyllys static void 25099ebb4caSwyllys parseKeyUsageSet(xmlNodePtr node, uint32_t *kubits) 25199ebb4caSwyllys { 25299ebb4caSwyllys xmlNodePtr n; 25399ebb4caSwyllys char *c; 25499ebb4caSwyllys 25599ebb4caSwyllys n = node->children; 25699ebb4caSwyllys while (n != NULL) { 25799ebb4caSwyllys if (!xmlStrcmp((const xmlChar *)n->name, 25830a5e8faSwyllys (const xmlChar *)KMF_KEY_USAGE_ELEMENT)) { 25999ebb4caSwyllys c = (char *)xmlGetProp(n, 26030a5e8faSwyllys (const xmlChar *)KMF_KEY_USAGE_USE_ATTR); 26199ebb4caSwyllys if (c) { 26230a5e8faSwyllys *kubits |= kmf_string_to_ku(c); 26399ebb4caSwyllys xmlFree(c); 26499ebb4caSwyllys } 26599ebb4caSwyllys } 26699ebb4caSwyllys 26799ebb4caSwyllys n = n->next; 26899ebb4caSwyllys } 26999ebb4caSwyllys } 27099ebb4caSwyllys 27199ebb4caSwyllys static KMF_OID * 27299ebb4caSwyllys dup_oid(KMF_OID *oldoid) 27399ebb4caSwyllys { 27499ebb4caSwyllys KMF_OID *oid; 27599ebb4caSwyllys 27699ebb4caSwyllys oid = malloc(sizeof (KMF_OID)); 27799ebb4caSwyllys if (oid == NULL) 27899ebb4caSwyllys return (NULL); 27999ebb4caSwyllys 28099ebb4caSwyllys oid->Length = oldoid->Length; 28199ebb4caSwyllys oid->Data = malloc(oid->Length); 28299ebb4caSwyllys if (oid->Data == NULL) { 28399ebb4caSwyllys free(oid); 28499ebb4caSwyllys return (NULL); 28599ebb4caSwyllys } 28699ebb4caSwyllys (void) memcpy(oid->Data, oldoid->Data, oid->Length); 28799ebb4caSwyllys 28899ebb4caSwyllys return (oid); 28999ebb4caSwyllys } 29099ebb4caSwyllys 29199ebb4caSwyllys KMF_OID * 29230a5e8faSwyllys kmf_ekuname_to_oid(char *ekuname) 29399ebb4caSwyllys { 29499ebb4caSwyllys KMF_OID *oid; 29599ebb4caSwyllys int i; 29699ebb4caSwyllys 29799ebb4caSwyllys if (ekuname == NULL) 29899ebb4caSwyllys return (NULL); 29999ebb4caSwyllys 30099ebb4caSwyllys for (i = 0; i < num_ekus; i++) { 30199ebb4caSwyllys if (strcasecmp(EKUList[i].ekuname, ekuname) == 0) { 30299ebb4caSwyllys oid = dup_oid(EKUList[i].oid); 30399ebb4caSwyllys return (oid); 30499ebb4caSwyllys } 30599ebb4caSwyllys } 30699ebb4caSwyllys 30799ebb4caSwyllys return (NULL); 30899ebb4caSwyllys } 30999ebb4caSwyllys 31099ebb4caSwyllys char * 311d00756ccSwyllys kmf_oid_to_ekuname(KMF_OID *oid) 31299ebb4caSwyllys { 31399ebb4caSwyllys int i; 31499ebb4caSwyllys for (i = 0; i < num_ekus; i++) { 31599ebb4caSwyllys if (oid->Length == EKUList[i].oid->Length && 31630a5e8faSwyllys !memcmp(oid->Data, EKUList[i].oid->Data, oid->Length)) { 31799ebb4caSwyllys return (EKUList[i].ekuname); 31899ebb4caSwyllys } 31999ebb4caSwyllys } 32099ebb4caSwyllys return (NULL); 32199ebb4caSwyllys } 32299ebb4caSwyllys 32399ebb4caSwyllys static KMF_RETURN 32499ebb4caSwyllys parseExtKeyUsage(xmlNodePtr node, KMF_EKU_POLICY *ekus) 32599ebb4caSwyllys { 32699ebb4caSwyllys xmlNodePtr n; 32799ebb4caSwyllys char *c; 32899ebb4caSwyllys KMF_RETURN ret = KMF_OK; 32999ebb4caSwyllys boolean_t found = FALSE; 33099ebb4caSwyllys 33199ebb4caSwyllys n = node->children; 33299ebb4caSwyllys while (n != NULL && ret == KMF_OK) { 33330a5e8faSwyllys KMF_OID newoid, *oidptr; 33430a5e8faSwyllys 33530a5e8faSwyllys oidptr = NULL; 33630a5e8faSwyllys newoid.Data = NULL; 33730a5e8faSwyllys newoid.Length = 0; 33899ebb4caSwyllys 33999ebb4caSwyllys if (!xmlStrcmp((const xmlChar *)n->name, 34030a5e8faSwyllys (const xmlChar *)KMF_EKU_NAME_ELEMENT)) { 34199ebb4caSwyllys c = (char *)xmlGetProp(n, 34230a5e8faSwyllys (const xmlChar *)KMF_EKU_NAME_ATTR); 34399ebb4caSwyllys if (c != NULL) { 34430a5e8faSwyllys oidptr = kmf_ekuname_to_oid(c); 34599ebb4caSwyllys xmlFree(c); 34699ebb4caSwyllys found = TRUE; 34730a5e8faSwyllys if (oidptr != NULL) 34830a5e8faSwyllys newoid = *oidptr; 34999ebb4caSwyllys } 35099ebb4caSwyllys } else if (!xmlStrcmp((const xmlChar *)n->name, 35130a5e8faSwyllys (const xmlChar *)KMF_EKU_OID_ELEMENT)) { 35299ebb4caSwyllys c = (char *)xmlGetProp(n, 35330a5e8faSwyllys (const xmlChar *)KMF_EKU_OID_ATTR); 35499ebb4caSwyllys if (c != NULL) { 35530a5e8faSwyllys (void) kmf_string_to_oid(c, &newoid); 35699ebb4caSwyllys xmlFree(c); 35799ebb4caSwyllys found = TRUE; 35899ebb4caSwyllys } 35999ebb4caSwyllys } else { 36099ebb4caSwyllys n = n->next; 36199ebb4caSwyllys if ((n == NULL) && (!found)) 36299ebb4caSwyllys ret = KMF_ERR_POLICY_DB_FORMAT; 36399ebb4caSwyllys continue; 36499ebb4caSwyllys } 36599ebb4caSwyllys 36630a5e8faSwyllys if (newoid.Data != NULL) { 36799ebb4caSwyllys ekus->eku_count++; 36899ebb4caSwyllys ekus->ekulist = realloc(ekus->ekulist, 36930a5e8faSwyllys ekus->eku_count * sizeof (KMF_OID)); 37099ebb4caSwyllys if (ekus->ekulist != NULL) { 37199ebb4caSwyllys ekus->ekulist[ekus->eku_count-1].Length = 37230a5e8faSwyllys newoid.Length; 37399ebb4caSwyllys ekus->ekulist[ekus->eku_count-1].Data = 37430a5e8faSwyllys newoid.Data; 37599ebb4caSwyllys } else { 37699ebb4caSwyllys ret = KMF_ERR_MEMORY; 37799ebb4caSwyllys } 37899ebb4caSwyllys } else { 37999ebb4caSwyllys ret = KMF_ERR_POLICY_DB_FORMAT; 38099ebb4caSwyllys } 38199ebb4caSwyllys 38299ebb4caSwyllys n = n->next; 38399ebb4caSwyllys } 38499ebb4caSwyllys 38599ebb4caSwyllys return (ret); 38699ebb4caSwyllys } 38799ebb4caSwyllys 388*269e59f9SJan Pechanec static KMF_RETURN 389*269e59f9SJan Pechanec parseMapper(xmlNodePtr node, KMF_MAPPER_RECORD *mapper) 390*269e59f9SJan Pechanec { 391*269e59f9SJan Pechanec xmlNodePtr n; 392*269e59f9SJan Pechanec 393*269e59f9SJan Pechanec n = node; 394*269e59f9SJan Pechanec mapper->mapname = (char *)xmlGetProp(n, 395*269e59f9SJan Pechanec (const xmlChar *)KMF_CERT_MAPPER_NAME_ATTR); 396*269e59f9SJan Pechanec mapper->dir = (char *)xmlGetProp(n, 397*269e59f9SJan Pechanec (const xmlChar *)KMF_CERT_MAPPER_DIR_ATTR); 398*269e59f9SJan Pechanec mapper->pathname = (char *)xmlGetProp(n, 399*269e59f9SJan Pechanec (const xmlChar *)KMF_CERT_MAPPER_PATH_ATTR); 400*269e59f9SJan Pechanec mapper->options = (char *)xmlGetProp(n, 401*269e59f9SJan Pechanec (const xmlChar *)KMF_CERT_MAPPER_OPTIONS_ATTR); 402*269e59f9SJan Pechanec 403*269e59f9SJan Pechanec /* 404*269e59f9SJan Pechanec * These are set according to whether mapper setting is taken from the 405*269e59f9SJan Pechanec * database or init function attributes. 406*269e59f9SJan Pechanec */ 407*269e59f9SJan Pechanec mapper->curpathname = NULL; 408*269e59f9SJan Pechanec mapper->curoptions = NULL; 409*269e59f9SJan Pechanec 410*269e59f9SJan Pechanec return (KMF_OK); 411*269e59f9SJan Pechanec } 412*269e59f9SJan Pechanec 41399ebb4caSwyllys int 41499ebb4caSwyllys parsePolicyElement(xmlNodePtr node, KMF_POLICY_RECORD *policy) 41599ebb4caSwyllys { 41699ebb4caSwyllys int ret = 0; 41799ebb4caSwyllys xmlNodePtr n = node->xmlChildrenNode; 41899ebb4caSwyllys char *c; 41999ebb4caSwyllys 42099ebb4caSwyllys if (node->type == XML_ELEMENT_NODE) { 42199ebb4caSwyllys if (node->properties != NULL) { 42299ebb4caSwyllys policy->name = (char *)xmlGetProp(node, 42330a5e8faSwyllys (const xmlChar *)KMF_POLICY_NAME_ATTR); 42499ebb4caSwyllys 42599ebb4caSwyllys c = (char *)xmlGetProp(node, 42630a5e8faSwyllys (const xmlChar *)KMF_OPTIONS_IGNORE_DATE_ATTR); 42799ebb4caSwyllys if (c && !strcasecmp(c, "true")) { 42899ebb4caSwyllys policy->ignore_date = 1; 42999ebb4caSwyllys xmlFree((xmlChar *)c); 43099ebb4caSwyllys } 43199ebb4caSwyllys 43299ebb4caSwyllys c = (char *)xmlGetProp(node, 43399ebb4caSwyllys (const xmlChar *)KMF_OPTIONS_IGNORE_UNKNOWN_EKUS); 43499ebb4caSwyllys if (c && !strcasecmp(c, "true")) { 43599ebb4caSwyllys policy->ignore_unknown_ekus = 1; 43699ebb4caSwyllys xmlFree(c); 43799ebb4caSwyllys } 43899ebb4caSwyllys 43999ebb4caSwyllys c = (char *)xmlGetProp(node, 44099ebb4caSwyllys (const xmlChar *)KMF_OPTIONS_IGNORE_TRUST_ANCHOR); 44199ebb4caSwyllys if (c && !strcasecmp(c, "true")) { 44299ebb4caSwyllys policy->ignore_trust_anchor = 1; 44399ebb4caSwyllys xmlFree(c); 44499ebb4caSwyllys } 44599ebb4caSwyllys 44699ebb4caSwyllys c = (char *)xmlGetProp(node, 44799ebb4caSwyllys (const xmlChar *)KMF_OPTIONS_VALIDITY_ADJUSTTIME); 44899ebb4caSwyllys if (c) { 44999ebb4caSwyllys policy->validity_adjusttime = c; 45099ebb4caSwyllys } else { 45199ebb4caSwyllys policy->validity_adjusttime = NULL; 45299ebb4caSwyllys } 45399ebb4caSwyllys 45499ebb4caSwyllys policy->ta_name = (char *)xmlGetProp(node, 45530a5e8faSwyllys (const xmlChar *)KMF_POLICY_TA_NAME_ATTR); 45699ebb4caSwyllys 45799ebb4caSwyllys policy->ta_serial = (char *)xmlGetProp(node, 45830a5e8faSwyllys (const xmlChar *)KMF_POLICY_TA_SERIAL_ATTR); 45999ebb4caSwyllys } 46099ebb4caSwyllys 46199ebb4caSwyllys n = node->children; 46299ebb4caSwyllys while (n != NULL) { 46399ebb4caSwyllys if (!xmlStrcmp((const xmlChar *)n->name, 46430a5e8faSwyllys (const xmlChar *)KMF_VALIDATION_METHODS_ELEMENT)) 46599ebb4caSwyllys parseValidation(n, &policy->validation_info, 46699ebb4caSwyllys policy); 46799ebb4caSwyllys else if (!xmlStrcmp((const xmlChar *)n->name, 46830a5e8faSwyllys (const xmlChar *)KMF_KEY_USAGE_SET_ELEMENT)) 46999ebb4caSwyllys parseKeyUsageSet(n, &policy->ku_bits); 47099ebb4caSwyllys else if (!xmlStrcmp((const xmlChar *)n->name, 47199ebb4caSwyllys (const xmlChar *)KMF_EKU_ELEMENT)) { 47299ebb4caSwyllys ret = parseExtKeyUsage(n, &policy->eku_set); 47399ebb4caSwyllys if (ret != KMF_OK) 47499ebb4caSwyllys return (ret); 475*269e59f9SJan Pechanec } else if (!xmlStrcmp((const xmlChar *)n->name, 476*269e59f9SJan Pechanec (const xmlChar *)KMF_CERT_MAPPER_ELEMENT)) { 477*269e59f9SJan Pechanec ret = parseMapper(n, &policy->mapper); 478*269e59f9SJan Pechanec if (ret != KMF_OK) 479*269e59f9SJan Pechanec return (ret); 48099ebb4caSwyllys } 48199ebb4caSwyllys 48299ebb4caSwyllys n = n->next; 48399ebb4caSwyllys } 48499ebb4caSwyllys } 48599ebb4caSwyllys 48699ebb4caSwyllys return (ret); 48799ebb4caSwyllys } 48899ebb4caSwyllys 48999ebb4caSwyllys static int 49099ebb4caSwyllys newprop(xmlNodePtr node, char *attrname, char *src) 49199ebb4caSwyllys { 49299ebb4caSwyllys xmlAttrPtr newattr; 49399ebb4caSwyllys 49499ebb4caSwyllys if (src != NULL && strlen(src)) { 49599ebb4caSwyllys newattr = xmlNewProp(node, (const xmlChar *)attrname, 49630a5e8faSwyllys (xmlChar *)src); 49799ebb4caSwyllys if (newattr == NULL) { 49899ebb4caSwyllys xmlUnlinkNode(node); 49999ebb4caSwyllys xmlFreeNode(node); 50099ebb4caSwyllys return (-1); 50199ebb4caSwyllys } 50299ebb4caSwyllys } 50399ebb4caSwyllys return (0); 50499ebb4caSwyllys } 50599ebb4caSwyllys 50699ebb4caSwyllys /* 50799ebb4caSwyllys * Add CRL policy information to the XML tree. 50899ebb4caSwyllys * Return non-zero on any failure, else 0 for success. 50999ebb4caSwyllys * 51099ebb4caSwyllys * This function is called only when the KMF_REVOCATION_METHOD_CRL flag is on. 51199ebb4caSwyllys */ 51299ebb4caSwyllys static int 51399ebb4caSwyllys AddCRLNodes(xmlNodePtr node, KMF_CRL_POLICY *crlinfo) 51499ebb4caSwyllys { 51599ebb4caSwyllys xmlNodePtr n; 51699ebb4caSwyllys 51799ebb4caSwyllys addFormatting(node, "\t\t"); 51899ebb4caSwyllys n = xmlNewChild(node, NULL, (const xmlChar *)"crl", NULL); 51999ebb4caSwyllys if (n == NULL) 52099ebb4caSwyllys return (-1); 52199ebb4caSwyllys 52299ebb4caSwyllys if (crlinfo->basefilename && 52399ebb4caSwyllys newprop(n, KMF_CRL_BASENAME_ATTR, crlinfo->basefilename)) 52499ebb4caSwyllys return (-1); 52599ebb4caSwyllys 52699ebb4caSwyllys if (crlinfo->directory && 52799ebb4caSwyllys newprop(n, KMF_CRL_DIRECTORY_ATTR, crlinfo->directory)) 52899ebb4caSwyllys return (-1); 52999ebb4caSwyllys 53099ebb4caSwyllys if (crlinfo->get_crl_uri && 53199ebb4caSwyllys newprop(n, KMF_CRL_GET_URI_ATTR, "TRUE")) { 53299ebb4caSwyllys return (-1); 53399ebb4caSwyllys } 53499ebb4caSwyllys 53599ebb4caSwyllys if (crlinfo->proxy && 53699ebb4caSwyllys newprop(n, KMF_CRL_PROXY_ATTR, crlinfo->proxy)) 53799ebb4caSwyllys return (-1); 53899ebb4caSwyllys 53999ebb4caSwyllys if (crlinfo->ignore_crl_sign && 54099ebb4caSwyllys newprop(n, KMF_CRL_IGNORE_SIGN_ATTR, "TRUE")) { 54199ebb4caSwyllys return (-1); 54299ebb4caSwyllys } 54399ebb4caSwyllys 54499ebb4caSwyllys if (crlinfo->ignore_crl_date && 54599ebb4caSwyllys newprop(n, KMF_CRL_IGNORE_DATE_ATTR, "TRUE")) { 54699ebb4caSwyllys return (-1); 54799ebb4caSwyllys } 54899ebb4caSwyllys 54999ebb4caSwyllys addFormatting(node, "\n"); 55099ebb4caSwyllys return (0); 55199ebb4caSwyllys } 55299ebb4caSwyllys 55399ebb4caSwyllys /* 55499ebb4caSwyllys * Add OCSP information to the policy tree. 55599ebb4caSwyllys * Return non-zero on any failure, else 0 for success. 55699ebb4caSwyllys * 55799ebb4caSwyllys * This function is called only when the KMF_REVOCATION_METHOD_OCSP flag is on. 55899ebb4caSwyllys */ 55999ebb4caSwyllys static int 56099ebb4caSwyllys AddOCSPNodes(xmlNodePtr parent, KMF_OCSP_POLICY *ocsp) 56199ebb4caSwyllys { 56299ebb4caSwyllys int ret = 0; 56399ebb4caSwyllys xmlNodePtr n_ocsp, n_basic, n_resp; 56499ebb4caSwyllys KMF_OCSP_BASIC_POLICY *basic; 56599ebb4caSwyllys KMF_RESP_CERT_POLICY *resp_cert; 56699ebb4caSwyllys 56799ebb4caSwyllys basic = &(ocsp->basic); 56899ebb4caSwyllys resp_cert = &(ocsp->resp_cert); 56999ebb4caSwyllys 57099ebb4caSwyllys if (basic->responderURI != NULL || basic->uri_from_cert == B_TRUE) { 57199ebb4caSwyllys 57299ebb4caSwyllys addFormatting(parent, "\t\t"); 57399ebb4caSwyllys 57499ebb4caSwyllys /* basic node */ 57599ebb4caSwyllys n_ocsp = xmlNewChild(parent, NULL, 57630a5e8faSwyllys (const xmlChar *)KMF_OCSP_ELEMENT, NULL); 57799ebb4caSwyllys if (n_ocsp == NULL) 57899ebb4caSwyllys return (-1); 57999ebb4caSwyllys addFormatting(n_ocsp, "\n\t\t\t"); 58099ebb4caSwyllys 58199ebb4caSwyllys n_basic = xmlNewChild(n_ocsp, NULL, 58299ebb4caSwyllys (const xmlChar *)KMF_OCSP_BASIC_ELEMENT, NULL); 58399ebb4caSwyllys if (n_basic == NULL) 58499ebb4caSwyllys return (-1); 58599ebb4caSwyllys if (basic->responderURI && newprop(n_basic, 58699ebb4caSwyllys KMF_OCSP_RESPONDER_ATTR, basic->responderURI)) 58799ebb4caSwyllys return (-1); 58899ebb4caSwyllys if (basic->proxy && 58999ebb4caSwyllys newprop(n_basic, KMF_OCSP_PROXY_ATTR, basic->proxy)) 59099ebb4caSwyllys return (-1); 59199ebb4caSwyllys if (basic->uri_from_cert && 59299ebb4caSwyllys newprop(n_basic, KMF_OCSP_URI_ATTR, "TRUE")) 59399ebb4caSwyllys return (-1); 59499ebb4caSwyllys if (basic->response_lifetime && 59599ebb4caSwyllys newprop(n_basic, KMF_OCSP_RESPONSE_LIFETIME_ATTR, 59630a5e8faSwyllys basic->response_lifetime)) 59799ebb4caSwyllys return (-1); 59899ebb4caSwyllys if (basic->ignore_response_sign && 59999ebb4caSwyllys newprop(n_basic, KMF_OCSP_IGNORE_SIGN_ATTR, "TRUE")) 60099ebb4caSwyllys return (-1); 60199ebb4caSwyllys 60299ebb4caSwyllys addFormatting(n_ocsp, "\n\t\t\t"); 60399ebb4caSwyllys 60499ebb4caSwyllys /* responder cert node */ 60599ebb4caSwyllys if (ocsp->has_resp_cert) { 60699ebb4caSwyllys n_resp = xmlNewChild(n_ocsp, NULL, 60799ebb4caSwyllys (const xmlChar *)KMF_OCSP_RESPONDER_CERT_ELEMENT, 60899ebb4caSwyllys NULL); 60999ebb4caSwyllys if (n_resp == NULL) 61099ebb4caSwyllys return (-1); 61199ebb4caSwyllys if (newprop(n_resp, KMF_CERT_NAME_ATTR, 61299ebb4caSwyllys resp_cert->name)) 61399ebb4caSwyllys return (-1); 61499ebb4caSwyllys if (newprop(n_resp, KMF_CERT_SERIAL_ATTR, 61599ebb4caSwyllys resp_cert->serial)) 61699ebb4caSwyllys return (-1); 61799ebb4caSwyllys } 61899ebb4caSwyllys addFormatting(n_ocsp, "\n\t\t"); 61999ebb4caSwyllys } 62099ebb4caSwyllys 62199ebb4caSwyllys addFormatting(parent, "\n"); 62299ebb4caSwyllys return (ret); 62399ebb4caSwyllys } 62499ebb4caSwyllys 62599ebb4caSwyllys /* 62699ebb4caSwyllys * Add validation method information to the policy tree. 62799ebb4caSwyllys * Return non-zero on any failure, else 0 for success. 62899ebb4caSwyllys */ 62999ebb4caSwyllys static int 63099ebb4caSwyllys AddValidationNodes(xmlNodePtr parent, KMF_POLICY_RECORD *policy) 63199ebb4caSwyllys { 63299ebb4caSwyllys xmlNodePtr mnode; 63399ebb4caSwyllys int ret = 0; 63499ebb4caSwyllys 63599ebb4caSwyllys addFormatting(parent, "\t"); 63699ebb4caSwyllys mnode = xmlNewChild(parent, NULL, 63730a5e8faSwyllys (const xmlChar *)KMF_VALIDATION_METHODS_ELEMENT, NULL); 63899ebb4caSwyllys if (mnode == NULL) 63999ebb4caSwyllys return (-1); 64099ebb4caSwyllys 64199ebb4caSwyllys addFormatting(mnode, "\n"); 64299ebb4caSwyllys 64399ebb4caSwyllys if (policy->revocation & KMF_REVOCATION_METHOD_OCSP) { 64499ebb4caSwyllys ret = AddOCSPNodes(mnode, &(policy->validation_info.ocsp_info)); 64599ebb4caSwyllys if (ret != KMF_OK) 64699ebb4caSwyllys goto end; 64799ebb4caSwyllys } 64899ebb4caSwyllys 64999ebb4caSwyllys if (policy->revocation & KMF_REVOCATION_METHOD_CRL) { 65099ebb4caSwyllys ret = AddCRLNodes(mnode, &(policy->validation_info.crl_info)); 65199ebb4caSwyllys if (ret != KMF_OK) 65299ebb4caSwyllys goto end; 65399ebb4caSwyllys } 65499ebb4caSwyllys 65599ebb4caSwyllys addFormatting(mnode, "\t"); 65699ebb4caSwyllys addFormatting(parent, "\n"); 65799ebb4caSwyllys 65899ebb4caSwyllys end: 65999ebb4caSwyllys if (ret != 0) { 66099ebb4caSwyllys xmlUnlinkNode(mnode); 66199ebb4caSwyllys xmlFreeNode(mnode); 66299ebb4caSwyllys } 66399ebb4caSwyllys return (ret); 66499ebb4caSwyllys 66599ebb4caSwyllys } 66699ebb4caSwyllys 667*269e59f9SJan Pechanec /* 668*269e59f9SJan Pechanec * Add mapper policy info to the policy tree. 669*269e59f9SJan Pechanec * Return non-zero on any failure, else 0 for success. 670*269e59f9SJan Pechanec */ 671*269e59f9SJan Pechanec static KMF_RETURN 672*269e59f9SJan Pechanec AddMapperPolicyNodes(xmlNodePtr parent, KMF_MAPPER_RECORD *mapper) 673*269e59f9SJan Pechanec { 674*269e59f9SJan Pechanec KMF_RETURN ret = KMF_OK; 675*269e59f9SJan Pechanec xmlNodePtr mapper_node; 676*269e59f9SJan Pechanec 677*269e59f9SJan Pechanec addFormatting(parent, "\n\t"); 678*269e59f9SJan Pechanec mapper_node = xmlNewChild(parent, NULL, 679*269e59f9SJan Pechanec (const xmlChar *)KMF_CERT_MAPPER_ELEMENT, NULL); 680*269e59f9SJan Pechanec if (mapper_node == NULL) 681*269e59f9SJan Pechanec return (KMF_ERR_POLICY_ENGINE); 682*269e59f9SJan Pechanec 683*269e59f9SJan Pechanec if (mapper->mapname != NULL && 684*269e59f9SJan Pechanec newprop(mapper_node, KMF_CERT_MAPPER_NAME_ATTR, mapper->mapname)) { 685*269e59f9SJan Pechanec ret = KMF_ERR_POLICY_ENGINE; 686*269e59f9SJan Pechanec goto end; 687*269e59f9SJan Pechanec } 688*269e59f9SJan Pechanec 689*269e59f9SJan Pechanec if (mapper->pathname != NULL && 690*269e59f9SJan Pechanec newprop(mapper_node, KMF_CERT_MAPPER_PATH_ATTR, mapper->pathname)) { 691*269e59f9SJan Pechanec ret = KMF_ERR_POLICY_ENGINE; 692*269e59f9SJan Pechanec goto end; 693*269e59f9SJan Pechanec } 694*269e59f9SJan Pechanec 695*269e59f9SJan Pechanec if (mapper->dir != NULL && 696*269e59f9SJan Pechanec newprop(mapper_node, KMF_CERT_MAPPER_DIR_ATTR, mapper->dir)) { 697*269e59f9SJan Pechanec ret = KMF_ERR_POLICY_ENGINE; 698*269e59f9SJan Pechanec goto end; 699*269e59f9SJan Pechanec } 700*269e59f9SJan Pechanec 701*269e59f9SJan Pechanec if (mapper->options != NULL && 702*269e59f9SJan Pechanec newprop(mapper_node, KMF_CERT_MAPPER_OPTIONS_ATTR, mapper->options)) 703*269e59f9SJan Pechanec ret = KMF_ERR_POLICY_ENGINE; 704*269e59f9SJan Pechanec 705*269e59f9SJan Pechanec if (ret == KMF_OK) { 706*269e59f9SJan Pechanec addFormatting(mapper_node, "\n\t"); 707*269e59f9SJan Pechanec addFormatting(parent, "\n"); 708*269e59f9SJan Pechanec } 709*269e59f9SJan Pechanec 710*269e59f9SJan Pechanec end: 711*269e59f9SJan Pechanec if (ret != KMF_OK) { 712*269e59f9SJan Pechanec xmlUnlinkNode(mapper_node); 713*269e59f9SJan Pechanec xmlFreeNode(mapper_node); 714*269e59f9SJan Pechanec } 715*269e59f9SJan Pechanec return (ret); 716*269e59f9SJan Pechanec } 717*269e59f9SJan Pechanec 71899ebb4caSwyllys /* 71999ebb4caSwyllys * Add Key Usage information to the policy tree. 72099ebb4caSwyllys * Return non-zero on any failure, else 0 for success. 72199ebb4caSwyllys */ 72299ebb4caSwyllys static KMF_RETURN 72399ebb4caSwyllys AddKeyUsageNodes(xmlNodePtr parent, uint32_t kubits) 72499ebb4caSwyllys { 72599ebb4caSwyllys int ret = KMF_OK; 72699ebb4caSwyllys int i; 72799ebb4caSwyllys 72899ebb4caSwyllys xmlNodePtr kuset, kunode; 72999ebb4caSwyllys 73099ebb4caSwyllys if (kubits == 0) 73199ebb4caSwyllys return (0); 73299ebb4caSwyllys 73399ebb4caSwyllys addFormatting(parent, "\n\t"); 73499ebb4caSwyllys kuset = xmlNewChild(parent, NULL, 73530a5e8faSwyllys (const xmlChar *)KMF_KEY_USAGE_SET_ELEMENT, NULL); 73699ebb4caSwyllys if (kuset == NULL) 73799ebb4caSwyllys return (KMF_ERR_POLICY_ENGINE); 73899ebb4caSwyllys 73999ebb4caSwyllys for (i = KULOWBIT; i <= KUHIGHBIT && ret == KMF_OK; i++) { 74030a5e8faSwyllys char *s = kmf_ku_to_string((kubits & (1<<i))); 74199ebb4caSwyllys if (s != NULL) { 74299ebb4caSwyllys addFormatting(kuset, "\n\t\t"); 74399ebb4caSwyllys 74499ebb4caSwyllys kunode = xmlNewChild(kuset, NULL, 74530a5e8faSwyllys (const xmlChar *)KMF_KEY_USAGE_ELEMENT, NULL); 74699ebb4caSwyllys if (kunode == NULL) 74799ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 74899ebb4caSwyllys 74999ebb4caSwyllys else if (newprop(kunode, KMF_KEY_USAGE_USE_ATTR, s)) 75099ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 75199ebb4caSwyllys } 75299ebb4caSwyllys } 75399ebb4caSwyllys addFormatting(kuset, "\n\t"); 75499ebb4caSwyllys addFormatting(parent, "\n"); 75599ebb4caSwyllys 75699ebb4caSwyllys if (ret != KMF_OK) { 75799ebb4caSwyllys xmlUnlinkNode(kuset); 75899ebb4caSwyllys xmlFreeNode(kuset); 75999ebb4caSwyllys } 76099ebb4caSwyllys 76199ebb4caSwyllys return (ret); 76299ebb4caSwyllys } 76399ebb4caSwyllys 76499ebb4caSwyllys /* 76599ebb4caSwyllys * Add Extended-Key-Usage information to the policy tree. 76699ebb4caSwyllys * Return non-zero on any failure, else 0 for success. 76799ebb4caSwyllys */ 76899ebb4caSwyllys static KMF_RETURN 76999ebb4caSwyllys AddExtKeyUsageNodes(xmlNodePtr parent, KMF_EKU_POLICY *ekus) 77099ebb4caSwyllys { 77199ebb4caSwyllys KMF_RETURN ret = KMF_OK; 77299ebb4caSwyllys xmlNodePtr n, kunode; 77399ebb4caSwyllys int i; 77499ebb4caSwyllys 77599ebb4caSwyllys if (ekus != NULL && ekus->eku_count > 0) { 77699ebb4caSwyllys addFormatting(parent, "\n\t"); 77799ebb4caSwyllys n = xmlNewChild(parent, NULL, 77830a5e8faSwyllys (const xmlChar *)KMF_EKU_ELEMENT, NULL); 77999ebb4caSwyllys if (n == NULL) 78099ebb4caSwyllys return (KMF_ERR_POLICY_ENGINE); 78199ebb4caSwyllys 78299ebb4caSwyllys for (i = 0; i < ekus->eku_count; i++) { 78330a5e8faSwyllys char *s = kmf_oid_to_string(&ekus->ekulist[i]); 78499ebb4caSwyllys if (s != NULL) { 78599ebb4caSwyllys addFormatting(n, "\n\t\t"); 78699ebb4caSwyllys kunode = xmlNewChild(n, NULL, 78730a5e8faSwyllys (const xmlChar *)KMF_EKU_OID_ELEMENT, 78830a5e8faSwyllys NULL); 78999ebb4caSwyllys if (kunode == NULL) 79099ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 79199ebb4caSwyllys 79299ebb4caSwyllys else if (newprop(kunode, KMF_EKU_OID_ATTR, s)) 79399ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 79499ebb4caSwyllys free(s); 79599ebb4caSwyllys } else { 79699ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 79799ebb4caSwyllys } 79899ebb4caSwyllys } 79999ebb4caSwyllys addFormatting(n, "\n\t"); 80099ebb4caSwyllys addFormatting(parent, "\n"); 80199ebb4caSwyllys } 80299ebb4caSwyllys 80399ebb4caSwyllys if (ret != KMF_OK) { 80499ebb4caSwyllys xmlUnlinkNode(n); 80599ebb4caSwyllys xmlFreeNode(n); 80699ebb4caSwyllys } 80799ebb4caSwyllys return (ret); 80899ebb4caSwyllys } 80999ebb4caSwyllys 81099ebb4caSwyllys void 81130a5e8faSwyllys kmf_free_eku_policy(KMF_EKU_POLICY *ekus) 81299ebb4caSwyllys { 81399ebb4caSwyllys if (ekus->eku_count > 0) { 81499ebb4caSwyllys int i; 81599ebb4caSwyllys for (i = 0; i < ekus->eku_count; i++) { 81630a5e8faSwyllys kmf_free_data(&ekus->ekulist[i]); 81799ebb4caSwyllys } 81899ebb4caSwyllys free(ekus->ekulist); 81999ebb4caSwyllys } 82099ebb4caSwyllys } 82199ebb4caSwyllys 82299ebb4caSwyllys #define FREE_POLICY_STR(s) if (s != NULL) free(s); 82399ebb4caSwyllys 82499ebb4caSwyllys void 82530a5e8faSwyllys kmf_free_policy_record(KMF_POLICY_RECORD *policy) 82699ebb4caSwyllys { 82799ebb4caSwyllys if (policy == NULL) 82899ebb4caSwyllys return; 82999ebb4caSwyllys 83099ebb4caSwyllys FREE_POLICY_STR(policy->name) 83199ebb4caSwyllys FREE_POLICY_STR(policy->VAL_OCSP_BASIC.responderURI) 83299ebb4caSwyllys FREE_POLICY_STR(policy->VAL_OCSP_BASIC.proxy) 83399ebb4caSwyllys FREE_POLICY_STR(policy->VAL_OCSP_BASIC.response_lifetime) 83499ebb4caSwyllys FREE_POLICY_STR(policy->VAL_OCSP_RESP_CERT.name) 83599ebb4caSwyllys FREE_POLICY_STR(policy->VAL_OCSP_RESP_CERT.serial) 83699ebb4caSwyllys FREE_POLICY_STR(policy->validation_info.crl_info.basefilename) 83799ebb4caSwyllys FREE_POLICY_STR(policy->validation_info.crl_info.directory) 83899ebb4caSwyllys FREE_POLICY_STR(policy->validation_info.crl_info.proxy) 83999ebb4caSwyllys FREE_POLICY_STR(policy->validity_adjusttime) 84099ebb4caSwyllys FREE_POLICY_STR(policy->ta_name) 84199ebb4caSwyllys FREE_POLICY_STR(policy->ta_serial) 842*269e59f9SJan Pechanec FREE_POLICY_STR(policy->mapper.mapname) 843*269e59f9SJan Pechanec FREE_POLICY_STR(policy->mapper.pathname) 844*269e59f9SJan Pechanec FREE_POLICY_STR(policy->mapper.options) 845*269e59f9SJan Pechanec FREE_POLICY_STR(policy->mapper.dir) 84699ebb4caSwyllys 84730a5e8faSwyllys kmf_free_eku_policy(&policy->eku_set); 84899ebb4caSwyllys 84999ebb4caSwyllys (void) memset(policy, 0, sizeof (KMF_POLICY_RECORD)); 85099ebb4caSwyllys } 85199ebb4caSwyllys 85299ebb4caSwyllys /* 85330a5e8faSwyllys * kmf_get_policy 85499ebb4caSwyllys * 85599ebb4caSwyllys * Find a policy record in the database. 85699ebb4caSwyllys */ 85799ebb4caSwyllys KMF_RETURN 85830a5e8faSwyllys kmf_get_policy(char *filename, char *policy_name, KMF_POLICY_RECORD *plc) 85999ebb4caSwyllys { 86099ebb4caSwyllys KMF_RETURN ret = KMF_OK; 86199ebb4caSwyllys xmlParserCtxtPtr ctxt; 86299ebb4caSwyllys xmlDocPtr doc = NULL; 86399ebb4caSwyllys xmlNodePtr cur, node; 86499ebb4caSwyllys int found = 0; 86599ebb4caSwyllys 86699ebb4caSwyllys if (filename == NULL || policy_name == NULL || plc == NULL) 86799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 86899ebb4caSwyllys 86999ebb4caSwyllys (void) memset(plc, 0, sizeof (KMF_POLICY_RECORD)); 87099ebb4caSwyllys 87199ebb4caSwyllys /* Create a parser context */ 87299ebb4caSwyllys ctxt = xmlNewParserCtxt(); 87399ebb4caSwyllys if (ctxt == NULL) 87499ebb4caSwyllys return (KMF_ERR_POLICY_DB_FORMAT); 87599ebb4caSwyllys 87699ebb4caSwyllys /* Read the policy DB and verify it against the schema. */ 87799ebb4caSwyllys doc = xmlCtxtReadFile(ctxt, filename, NULL, 87899ebb4caSwyllys XML_PARSE_DTDVALID | XML_PARSE_NOERROR | XML_PARSE_NOWARNING); 87999ebb4caSwyllys if (doc == NULL || ctxt->valid == 0) { 88099ebb4caSwyllys ret = KMF_ERR_POLICY_DB_FORMAT; 88199ebb4caSwyllys goto out; 88299ebb4caSwyllys } 88399ebb4caSwyllys 88499ebb4caSwyllys cur = xmlDocGetRootElement(doc); 88599ebb4caSwyllys if (cur == NULL) { 88699ebb4caSwyllys ret = KMF_ERR_POLICY_DB_FORMAT; 88799ebb4caSwyllys goto out; 88899ebb4caSwyllys } 88999ebb4caSwyllys 89099ebb4caSwyllys node = cur->xmlChildrenNode; 89199ebb4caSwyllys while (node != NULL && !found) { 89299ebb4caSwyllys char *c; 89399ebb4caSwyllys /* 89499ebb4caSwyllys * Search for the policy that matches the given name. 89599ebb4caSwyllys */ 89699ebb4caSwyllys if (!xmlStrcmp((const xmlChar *)node->name, 89730a5e8faSwyllys (const xmlChar *)KMF_POLICY_ELEMENT)) { 89899ebb4caSwyllys /* Check the name attribute */ 89999ebb4caSwyllys c = (char *)xmlGetProp(node, 90030a5e8faSwyllys (const xmlChar *)KMF_POLICY_NAME_ATTR); 90199ebb4caSwyllys 90299ebb4caSwyllys /* If a match, parse the rest of the data */ 90399ebb4caSwyllys if (c != NULL) { 90499ebb4caSwyllys if (strcmp(c, policy_name) == 0) { 90599ebb4caSwyllys ret = parsePolicyElement(node, plc); 90699ebb4caSwyllys found = (ret == KMF_OK); 90799ebb4caSwyllys } 90899ebb4caSwyllys xmlFree(c); 90999ebb4caSwyllys } 91099ebb4caSwyllys } 91199ebb4caSwyllys node = node->next; 91299ebb4caSwyllys } 91399ebb4caSwyllys 91499ebb4caSwyllys if (!found) { 91599ebb4caSwyllys ret = KMF_ERR_POLICY_NOT_FOUND; 91699ebb4caSwyllys goto out; 91799ebb4caSwyllys } 91899ebb4caSwyllys 91999ebb4caSwyllys out: 92099ebb4caSwyllys if (ctxt != NULL) 92199ebb4caSwyllys xmlFreeParserCtxt(ctxt); 92299ebb4caSwyllys 92399ebb4caSwyllys if (doc != NULL) 92499ebb4caSwyllys xmlFreeDoc(doc); 92599ebb4caSwyllys 92699ebb4caSwyllys return (ret); 92799ebb4caSwyllys } 92899ebb4caSwyllys 92999ebb4caSwyllys /* 93030a5e8faSwyllys * kmf_set_policy 93199ebb4caSwyllys * 93299ebb4caSwyllys * Set the policy record in the handle. This searches 93399ebb4caSwyllys * the policy DB for the named policy. If it is not found 93499ebb4caSwyllys * or an error occurred in processing, the existing policy 93599ebb4caSwyllys * is kept and an error code is returned. 93699ebb4caSwyllys */ 93799ebb4caSwyllys KMF_RETURN 93830a5e8faSwyllys kmf_set_policy(KMF_HANDLE_T handle, char *policyfile, char *policyname) 93999ebb4caSwyllys { 94099ebb4caSwyllys KMF_RETURN ret = KMF_OK; 94199ebb4caSwyllys KMF_POLICY_RECORD *newpolicy = NULL; 94299ebb4caSwyllys 94399ebb4caSwyllys CLEAR_ERROR(handle, ret); 94499ebb4caSwyllys if (ret != KMF_OK) 94599ebb4caSwyllys return (ret); 94699ebb4caSwyllys 94799ebb4caSwyllys newpolicy = malloc(sizeof (KMF_POLICY_RECORD)); 94899ebb4caSwyllys if (newpolicy == NULL) 94999ebb4caSwyllys return (KMF_ERR_MEMORY); 95099ebb4caSwyllys (void) memset(newpolicy, 0, sizeof (KMF_POLICY_RECORD)); 95199ebb4caSwyllys 95230a5e8faSwyllys ret = kmf_get_policy( 95399ebb4caSwyllys policyfile == NULL ? KMF_DEFAULT_POLICY_FILE : policyfile, 95499ebb4caSwyllys policyname == NULL ? KMF_DEFAULT_POLICY_NAME : policyname, 95599ebb4caSwyllys newpolicy); 95699ebb4caSwyllys if (ret != KMF_OK) 95799ebb4caSwyllys goto out; 95899ebb4caSwyllys 95930a5e8faSwyllys ret = kmf_verify_policy(newpolicy); 96099ebb4caSwyllys if (ret != KMF_OK) 96199ebb4caSwyllys goto out; 96299ebb4caSwyllys 96399ebb4caSwyllys /* release the existing policy data (if any). */ 96499ebb4caSwyllys if (handle->policy != NULL) { 96530a5e8faSwyllys kmf_free_policy_record(handle->policy); 96699ebb4caSwyllys free(handle->policy); 96799ebb4caSwyllys } 96899ebb4caSwyllys 96999ebb4caSwyllys handle->policy = newpolicy; 97099ebb4caSwyllys 97199ebb4caSwyllys out: 97299ebb4caSwyllys /* Cleanup any data allocated before the error occurred */ 97399ebb4caSwyllys if (ret != KMF_OK) { 97430a5e8faSwyllys kmf_free_policy_record(newpolicy); 97599ebb4caSwyllys free(newpolicy); 97699ebb4caSwyllys } 97799ebb4caSwyllys 97899ebb4caSwyllys return (ret); 97999ebb4caSwyllys } 98099ebb4caSwyllys 98199ebb4caSwyllys 98299ebb4caSwyllys static KMF_RETURN 98399ebb4caSwyllys deletePolicyNode(xmlNodePtr node, char *policy_name) 98499ebb4caSwyllys { 98599ebb4caSwyllys KMF_RETURN ret = KMF_OK; 98699ebb4caSwyllys int found = 0; 98799ebb4caSwyllys xmlNodePtr dnode = NULL; 98899ebb4caSwyllys 98999ebb4caSwyllys while (node != NULL && !found) { 99099ebb4caSwyllys char *c; 99199ebb4caSwyllys /* 99299ebb4caSwyllys * Search for the policy that matches the given name. 99399ebb4caSwyllys */ 99499ebb4caSwyllys if (!xmlStrcmp((const xmlChar *)node->name, 99530a5e8faSwyllys (const xmlChar *)KMF_POLICY_ELEMENT)) { 99699ebb4caSwyllys /* Check the name attribute */ 99799ebb4caSwyllys c = (char *)xmlGetProp(node, 99830a5e8faSwyllys (const xmlChar *)KMF_POLICY_NAME_ATTR); 99999ebb4caSwyllys 100099ebb4caSwyllys /* If a match, parse the rest of the data */ 100199ebb4caSwyllys if (c != NULL) { 100299ebb4caSwyllys if (strcmp(c, policy_name) == 0) { 100399ebb4caSwyllys found = 1; 100499ebb4caSwyllys dnode = node; 100599ebb4caSwyllys } 100699ebb4caSwyllys xmlFree(c); 100799ebb4caSwyllys } 100899ebb4caSwyllys } 100999ebb4caSwyllys if (!found) 101099ebb4caSwyllys node = node->next; 101199ebb4caSwyllys } 101299ebb4caSwyllys 101399ebb4caSwyllys if (found && dnode != NULL) { 101499ebb4caSwyllys /* Unlink the node */ 101599ebb4caSwyllys xmlUnlinkNode(dnode); 101699ebb4caSwyllys 101799ebb4caSwyllys /* Delete it from the document tree */ 101899ebb4caSwyllys xmlFreeNode(dnode); 101999ebb4caSwyllys } else { 102099ebb4caSwyllys ret = KMF_ERR_POLICY_NOT_FOUND; 102199ebb4caSwyllys } 102299ebb4caSwyllys 102399ebb4caSwyllys return (ret); 102499ebb4caSwyllys } 102599ebb4caSwyllys 102699ebb4caSwyllys /* 102799ebb4caSwyllys * update_policyfile 102899ebb4caSwyllys * 102999ebb4caSwyllys * Attempt to do a "safe" file update as follows: 103099ebb4caSwyllys * 1. Lock the original file. 103199ebb4caSwyllys * 2. Create and write to a temporary file 103299ebb4caSwyllys * 3. Replace the original file with the temporary file. 103399ebb4caSwyllys */ 103499ebb4caSwyllys static KMF_RETURN 103599ebb4caSwyllys update_policyfile(xmlDocPtr doc, char *filename) 103699ebb4caSwyllys { 103799ebb4caSwyllys KMF_RETURN ret = KMF_OK; 103899ebb4caSwyllys FILE *pfile, *tmpfile; 103999ebb4caSwyllys char tmpfilename[MAXPATHLEN]; 104099ebb4caSwyllys char *p; 104199ebb4caSwyllys int prefix_len, tmpfd; 104299ebb4caSwyllys mode_t old_mode; 104399ebb4caSwyllys 104499ebb4caSwyllys /* 104599ebb4caSwyllys * Open and lock the DB file. First try to open an existing file, 104699ebb4caSwyllys * if that fails, open it as if it were new. 104799ebb4caSwyllys */ 104899ebb4caSwyllys if ((pfile = fopen(filename, "r+")) == NULL && errno == ENOENT) 104999ebb4caSwyllys pfile = fopen(filename, "w+"); 105099ebb4caSwyllys 105199ebb4caSwyllys if (pfile == NULL) 105299ebb4caSwyllys return (KMF_ERR_POLICY_DB_FILE); 105399ebb4caSwyllys 105499ebb4caSwyllys if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { 105599ebb4caSwyllys (void) fclose(pfile); 105699ebb4caSwyllys return (KMF_ERR_POLICY_DB_FILE); 105799ebb4caSwyllys } 105899ebb4caSwyllys 105999ebb4caSwyllys /* 106099ebb4caSwyllys * Create a temporary file to hold the new data. 106199ebb4caSwyllys */ 106299ebb4caSwyllys (void) memset(tmpfilename, 0, sizeof (tmpfilename)); 106399ebb4caSwyllys p = (char *)strrchr(filename, '/'); 106499ebb4caSwyllys if (p == NULL) { 106599ebb4caSwyllys /* 106699ebb4caSwyllys * filename contains basename only so we 106799ebb4caSwyllys * create a temp file in current directory. 106899ebb4caSwyllys */ 106999ebb4caSwyllys if (strlcpy(tmpfilename, TMPFILE_TEMPLATE, 107099ebb4caSwyllys sizeof (tmpfilename)) >= sizeof (tmpfilename)) 107199ebb4caSwyllys return (KMF_ERR_INTERNAL); 107299ebb4caSwyllys } else { 107399ebb4caSwyllys /* 107499ebb4caSwyllys * create a temp file in the same directory 107599ebb4caSwyllys * as the policy file. 107699ebb4caSwyllys */ 107799ebb4caSwyllys prefix_len = p - filename; 107899ebb4caSwyllys (void) strncpy(tmpfilename, filename, prefix_len); 107999ebb4caSwyllys (void) strncat(tmpfilename, "/", 1); 108099ebb4caSwyllys (void) strncat(tmpfilename, TMPFILE_TEMPLATE, 108199ebb4caSwyllys sizeof (TMPFILE_TEMPLATE)); 108299ebb4caSwyllys } 108399ebb4caSwyllys 108499ebb4caSwyllys old_mode = umask(077); 108599ebb4caSwyllys tmpfd = mkstemp(tmpfilename); 108699ebb4caSwyllys (void) umask(old_mode); 108799ebb4caSwyllys if (tmpfd == -1) { 108899ebb4caSwyllys return (KMF_ERR_POLICY_DB_FILE); 108999ebb4caSwyllys } 109099ebb4caSwyllys 109199ebb4caSwyllys if ((tmpfile = fdopen(tmpfd, "w")) == NULL) { 109299ebb4caSwyllys (void) close(tmpfd); 109399ebb4caSwyllys (void) unlink(tmpfilename); 109499ebb4caSwyllys (void) fclose(pfile); 109599ebb4caSwyllys return (KMF_ERR_POLICY_DB_FILE); 109699ebb4caSwyllys } 109799ebb4caSwyllys 109899ebb4caSwyllys /* 109999ebb4caSwyllys * Write the new info to the temporary file. 110099ebb4caSwyllys */ 110199ebb4caSwyllys if (xmlDocFormatDump(tmpfile, doc, 1) == -1) { 110299ebb4caSwyllys (void) fclose(pfile); 110399ebb4caSwyllys (void) fclose(tmpfile); 110499ebb4caSwyllys (void) unlink(tmpfilename); 110599ebb4caSwyllys return (KMF_ERR_POLICY_ENGINE); 110699ebb4caSwyllys } 110799ebb4caSwyllys 110899ebb4caSwyllys (void) fclose(pfile); 110999ebb4caSwyllys 111030a5e8faSwyllys if (fchmod(tmpfd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 111199ebb4caSwyllys (void) close(tmpfd); 111299ebb4caSwyllys (void) unlink(tmpfilename); 111399ebb4caSwyllys return (KMF_ERR_POLICY_DB_FILE); 111499ebb4caSwyllys } 111599ebb4caSwyllys if (fclose(tmpfile) != 0) 111699ebb4caSwyllys return (KMF_ERR_POLICY_DB_FILE); 111799ebb4caSwyllys 111899ebb4caSwyllys /* 111999ebb4caSwyllys * Replace the original file with the updated tempfile. 112099ebb4caSwyllys */ 112199ebb4caSwyllys if (rename(tmpfilename, filename) == -1) { 112299ebb4caSwyllys ret = KMF_ERR_POLICY_DB_FILE; 112399ebb4caSwyllys } 112499ebb4caSwyllys 112599ebb4caSwyllys if (ret != KMF_OK) { 112699ebb4caSwyllys /* try to remove the tmp file */ 112799ebb4caSwyllys (void) unlink(tmpfilename); 112899ebb4caSwyllys } 112999ebb4caSwyllys 113099ebb4caSwyllys return (ret); 113199ebb4caSwyllys } 113299ebb4caSwyllys 113399ebb4caSwyllys /* 113430a5e8faSwyllys * kmf_delete_policy_from_db 113599ebb4caSwyllys * 113699ebb4caSwyllys * Find a policy by name and remove it from the policy DB file. 113799ebb4caSwyllys * If the policy is not found, return an error. 113899ebb4caSwyllys */ 113999ebb4caSwyllys KMF_RETURN 114030a5e8faSwyllys kmf_delete_policy_from_db(char *policy_name, char *dbfilename) 114199ebb4caSwyllys { 114299ebb4caSwyllys KMF_RETURN ret; 114399ebb4caSwyllys xmlParserCtxtPtr ctxt = NULL; 114499ebb4caSwyllys xmlDocPtr doc = NULL; 114599ebb4caSwyllys xmlNodePtr cur, node; 114699ebb4caSwyllys 114799ebb4caSwyllys if (policy_name == NULL || dbfilename == NULL) 114899ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 114999ebb4caSwyllys 115099ebb4caSwyllys /* 115199ebb4caSwyllys * Cannot delete the default policy record from the system 115299ebb4caSwyllys * default policy database (/etc/security/kmfpolicy.xml). 115399ebb4caSwyllys */ 115499ebb4caSwyllys if (strcmp(dbfilename, KMF_DEFAULT_POLICY_FILE) == 0 && 115599ebb4caSwyllys strcmp(policy_name, KMF_DEFAULT_POLICY_NAME) == 0) 115699ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 115799ebb4caSwyllys 115899ebb4caSwyllys /* Make sure the policy file exists */ 115999ebb4caSwyllys if (access(dbfilename, R_OK | W_OK)) 116099ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 116199ebb4caSwyllys 116299ebb4caSwyllys /* Read the policy DB and verify it against the schema. */ 116399ebb4caSwyllys ctxt = xmlNewParserCtxt(); 116499ebb4caSwyllys if (ctxt == NULL) 116599ebb4caSwyllys return (KMF_ERR_POLICY_DB_FORMAT); 116699ebb4caSwyllys 116799ebb4caSwyllys doc = xmlCtxtReadFile(ctxt, dbfilename, NULL, 116899ebb4caSwyllys XML_PARSE_DTDVALID | XML_PARSE_NOERROR | XML_PARSE_NOWARNING); 116999ebb4caSwyllys if (doc == NULL || ctxt->valid == 0) { 117099ebb4caSwyllys ret = KMF_ERR_POLICY_DB_FORMAT; 117199ebb4caSwyllys goto end; 117299ebb4caSwyllys } 117399ebb4caSwyllys 117499ebb4caSwyllys cur = xmlDocGetRootElement(doc); 117599ebb4caSwyllys if (cur == NULL) { 117699ebb4caSwyllys xmlFreeDoc(doc); 117799ebb4caSwyllys return (KMF_ERR_POLICY_DB_FORMAT); 117899ebb4caSwyllys } 117999ebb4caSwyllys node = cur->xmlChildrenNode; 118099ebb4caSwyllys 118199ebb4caSwyllys ret = deletePolicyNode(node, policy_name); 118299ebb4caSwyllys 118399ebb4caSwyllys if (ret == KMF_OK) 118499ebb4caSwyllys ret = update_policyfile(doc, dbfilename); 118599ebb4caSwyllys 118699ebb4caSwyllys end: 118799ebb4caSwyllys if (ctxt != NULL) 118899ebb4caSwyllys xmlFreeParserCtxt(ctxt); 118999ebb4caSwyllys 119099ebb4caSwyllys if (doc != NULL) 119199ebb4caSwyllys xmlFreeDoc(doc); 119299ebb4caSwyllys 119399ebb4caSwyllys return (ret); 119499ebb4caSwyllys } 119599ebb4caSwyllys 119699ebb4caSwyllys /* 119799ebb4caSwyllys * Add a new policy node to the Policy DB XML tree. 119899ebb4caSwyllys */ 119999ebb4caSwyllys static KMF_RETURN 120099ebb4caSwyllys addPolicyNode(xmlNodePtr pnode, KMF_POLICY_RECORD *policy) 120199ebb4caSwyllys { 120299ebb4caSwyllys KMF_RETURN ret = KMF_OK; 120399ebb4caSwyllys 120499ebb4caSwyllys if (pnode != NULL && policy != NULL) { 120599ebb4caSwyllys if (newprop(pnode, KMF_POLICY_NAME_ATTR, policy->name) != 0) { 120699ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 120799ebb4caSwyllys goto out; 120899ebb4caSwyllys } 120999ebb4caSwyllys if (policy->ignore_date) { 121099ebb4caSwyllys if (newprop(pnode, KMF_OPTIONS_IGNORE_DATE_ATTR, 121130a5e8faSwyllys "TRUE")) { 121299ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 121399ebb4caSwyllys goto out; 121499ebb4caSwyllys } 121599ebb4caSwyllys } 121699ebb4caSwyllys 121799ebb4caSwyllys if (policy->ignore_unknown_ekus) { 121899ebb4caSwyllys if (newprop(pnode, KMF_OPTIONS_IGNORE_UNKNOWN_EKUS, 121930a5e8faSwyllys "TRUE")) { 122099ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 122199ebb4caSwyllys goto out; 122299ebb4caSwyllys } 122399ebb4caSwyllys } 122499ebb4caSwyllys 122599ebb4caSwyllys if (policy->ignore_trust_anchor) { 122699ebb4caSwyllys if (newprop(pnode, KMF_OPTIONS_IGNORE_TRUST_ANCHOR, 122730a5e8faSwyllys "TRUE")) { 122899ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 122999ebb4caSwyllys goto out; 123099ebb4caSwyllys } 123199ebb4caSwyllys } 123299ebb4caSwyllys 123399ebb4caSwyllys if (policy->validity_adjusttime) { 123499ebb4caSwyllys if (newprop(pnode, KMF_OPTIONS_VALIDITY_ADJUSTTIME, 123530a5e8faSwyllys policy->validity_adjusttime)) { 123699ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 123799ebb4caSwyllys goto out; 123899ebb4caSwyllys } 123999ebb4caSwyllys } 124099ebb4caSwyllys 124199ebb4caSwyllys if (newprop(pnode, KMF_POLICY_TA_NAME_ATTR, 124299ebb4caSwyllys policy->ta_name) != 0) { 124399ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 124499ebb4caSwyllys goto out; 124599ebb4caSwyllys } 124699ebb4caSwyllys 124799ebb4caSwyllys if (newprop(pnode, KMF_POLICY_TA_SERIAL_ATTR, 124899ebb4caSwyllys policy->ta_serial) != 0) { 124999ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 125099ebb4caSwyllys goto out; 125199ebb4caSwyllys } 125299ebb4caSwyllys 125399ebb4caSwyllys /* Add a text node for readability */ 125499ebb4caSwyllys addFormatting(pnode, "\n"); 125599ebb4caSwyllys 125699ebb4caSwyllys if (ret = AddValidationNodes(pnode, policy)) { 125799ebb4caSwyllys goto out; 125899ebb4caSwyllys } 125999ebb4caSwyllys 126099ebb4caSwyllys if ((ret = AddKeyUsageNodes(pnode, policy->ku_bits))) { 126199ebb4caSwyllys goto out; 126299ebb4caSwyllys } 126399ebb4caSwyllys 126499ebb4caSwyllys if ((ret = AddExtKeyUsageNodes(pnode, &policy->eku_set))) { 126599ebb4caSwyllys goto out; 126699ebb4caSwyllys } 1267*269e59f9SJan Pechanec if ((ret = AddMapperPolicyNodes(pnode, &policy->mapper))) { 1268*269e59f9SJan Pechanec goto out; 1269*269e59f9SJan Pechanec } 127099ebb4caSwyllys } else { 127199ebb4caSwyllys ret = KMF_ERR_BAD_PARAMETER; 127299ebb4caSwyllys } 127399ebb4caSwyllys out: 127499ebb4caSwyllys if (ret != KMF_OK && pnode != NULL) { 127599ebb4caSwyllys xmlUnlinkNode(pnode); 127699ebb4caSwyllys xmlFreeNode(pnode); 127799ebb4caSwyllys } 127899ebb4caSwyllys 127999ebb4caSwyllys return (ret); 128099ebb4caSwyllys } 128199ebb4caSwyllys 128299ebb4caSwyllys 128399ebb4caSwyllys KMF_RETURN 128430a5e8faSwyllys kmf_verify_policy(KMF_POLICY_RECORD *policy) 128599ebb4caSwyllys { 128699ebb4caSwyllys KMF_RETURN ret = KMF_OK; 128799ebb4caSwyllys boolean_t has_ta; 128899ebb4caSwyllys 128999ebb4caSwyllys if (policy->name == NULL || !strlen(policy->name)) 129099ebb4caSwyllys return (KMF_ERR_POLICY_NAME); 129199ebb4caSwyllys 129299ebb4caSwyllys /* Check the TA related policy */ 129399ebb4caSwyllys if (policy->ta_name != NULL && policy->ta_serial != NULL) { 129499ebb4caSwyllys has_ta = B_TRUE; 129599ebb4caSwyllys } else if (policy->ta_name == NULL && policy->ta_serial == NULL) { 129699ebb4caSwyllys has_ta = B_FALSE; 129799ebb4caSwyllys } else { 129899ebb4caSwyllys /* 129999ebb4caSwyllys * If the TA cert is set, then both name and serial number 130099ebb4caSwyllys * need to be specified. 130199ebb4caSwyllys */ 130299ebb4caSwyllys return (KMF_ERR_TA_POLICY); 130399ebb4caSwyllys } 130499ebb4caSwyllys 130599ebb4caSwyllys if (has_ta == B_FALSE && policy->ignore_trust_anchor == B_FALSE) 130699ebb4caSwyllys return (KMF_ERR_TA_POLICY); 130799ebb4caSwyllys 130899ebb4caSwyllys if (policy->revocation & KMF_REVOCATION_METHOD_OCSP) { 130999ebb4caSwyllys /* 131099ebb4caSwyllys * For OCSP, either use a fixed responder or use the 131199ebb4caSwyllys * value from the cert, but not both. 131299ebb4caSwyllys */ 131399ebb4caSwyllys if ((policy->VAL_OCSP_BASIC.responderURI == NULL && 131499ebb4caSwyllys policy->VAL_OCSP_BASIC.uri_from_cert == B_FALSE) || 131599ebb4caSwyllys (policy->VAL_OCSP_BASIC.responderURI != NULL && 131699ebb4caSwyllys policy->VAL_OCSP_BASIC.uri_from_cert == B_TRUE)) 131799ebb4caSwyllys return (KMF_ERR_OCSP_POLICY); 131899ebb4caSwyllys 131999ebb4caSwyllys /* 132099ebb4caSwyllys * If the OCSP responder cert is set, then both name and serial 132199ebb4caSwyllys * number need to be specified. 132299ebb4caSwyllys */ 132399ebb4caSwyllys if ((policy->VAL_OCSP_RESP_CERT.name != NULL && 132499ebb4caSwyllys policy->VAL_OCSP_RESP_CERT.serial == NULL) || 132599ebb4caSwyllys (policy->VAL_OCSP_RESP_CERT.name == NULL && 132699ebb4caSwyllys policy->VAL_OCSP_RESP_CERT.serial != NULL)) 132799ebb4caSwyllys return (KMF_ERR_OCSP_POLICY); 132899ebb4caSwyllys } 132999ebb4caSwyllys 133099ebb4caSwyllys return (ret); 133199ebb4caSwyllys } 133299ebb4caSwyllys 133399ebb4caSwyllys /* 133499ebb4caSwyllys * Update the KMF policy file by creating a new XML Policy doc tree 133599ebb4caSwyllys * from the data in the KMF_POLICY_RECORD structure. If "check_policy" 133699ebb4caSwyllys * is true, then we check the policy sanity also. 133799ebb4caSwyllys */ 133899ebb4caSwyllys KMF_RETURN 133930a5e8faSwyllys kmf_add_policy_to_db(KMF_POLICY_RECORD *policy, char *dbfilename, 134099ebb4caSwyllys boolean_t check_policy) 134199ebb4caSwyllys { 134299ebb4caSwyllys KMF_RETURN ret = KMF_OK; 134399ebb4caSwyllys xmlDocPtr doc = NULL; 134499ebb4caSwyllys xmlNodePtr root, node; 134599ebb4caSwyllys xmlParserCtxtPtr ctxt = NULL; 134699ebb4caSwyllys 134799ebb4caSwyllys if (policy == NULL || dbfilename == NULL) 134899ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 134999ebb4caSwyllys 135099ebb4caSwyllys if (check_policy == B_TRUE) { 135130a5e8faSwyllys if (ret = kmf_verify_policy(policy)) 135230a5e8faSwyllys return (ret); 135399ebb4caSwyllys } 135499ebb4caSwyllys 135599ebb4caSwyllys /* If the policyDB exists, load it into memory */ 135699ebb4caSwyllys if (!access(dbfilename, R_OK)) { 135799ebb4caSwyllys 135899ebb4caSwyllys /* Create a parser context */ 135999ebb4caSwyllys ctxt = xmlNewParserCtxt(); 136099ebb4caSwyllys if (ctxt == NULL) 136199ebb4caSwyllys return (KMF_ERR_POLICY_DB_FORMAT); 136299ebb4caSwyllys 136399ebb4caSwyllys doc = xmlCtxtReadFile(ctxt, dbfilename, NULL, 136499ebb4caSwyllys XML_PARSE_DTDVALID | XML_PARSE_NOERROR | 136599ebb4caSwyllys XML_PARSE_NOWARNING); 136699ebb4caSwyllys if (doc == NULL || ctxt->valid == 0) { 136799ebb4caSwyllys ret = KMF_ERR_POLICY_DB_FORMAT; 136899ebb4caSwyllys goto out; 136999ebb4caSwyllys } 137099ebb4caSwyllys 137199ebb4caSwyllys root = xmlDocGetRootElement(doc); 137299ebb4caSwyllys if (root == NULL) { 137399ebb4caSwyllys ret = KMF_ERR_POLICY_DB_FORMAT; 137499ebb4caSwyllys goto out; 137599ebb4caSwyllys } 137699ebb4caSwyllys 137799ebb4caSwyllys node = root->xmlChildrenNode; 137899ebb4caSwyllys /* 137999ebb4caSwyllys * If the DB has an existing policy of the 138099ebb4caSwyllys * same name, delete it from the tree. 138199ebb4caSwyllys */ 138299ebb4caSwyllys ret = deletePolicyNode(node, policy->name); 138399ebb4caSwyllys if (ret == KMF_ERR_POLICY_NOT_FOUND) 138499ebb4caSwyllys ret = KMF_OK; 138599ebb4caSwyllys } else { 138699ebb4caSwyllys /* Initialize a new DB tree */ 138799ebb4caSwyllys doc = xmlNewDoc((const xmlChar *)"1.0"); 138899ebb4caSwyllys if (doc == NULL) 138999ebb4caSwyllys return (KMF_ERR_POLICY_ENGINE); 139099ebb4caSwyllys 139199ebb4caSwyllys /* 139299ebb4caSwyllys * Add the DOCTYPE header to the tree so the 139399ebb4caSwyllys * DTD link is embedded 139499ebb4caSwyllys */ 139599ebb4caSwyllys doc->intSubset = xmlCreateIntSubset(doc, 139630a5e8faSwyllys (const xmlChar *)KMF_POLICY_ROOT, 139730a5e8faSwyllys NULL, (const xmlChar *)KMF_POLICY_DTD); 139899ebb4caSwyllys 139999ebb4caSwyllys root = xmlNewDocNode(doc, NULL, 140030a5e8faSwyllys (const xmlChar *)KMF_POLICY_ROOT, NULL); 140199ebb4caSwyllys if (root != NULL) { 14025ad42b1bSSurya Prakki (void) xmlDocSetRootElement(doc, root); 140399ebb4caSwyllys } 140499ebb4caSwyllys } 140599ebb4caSwyllys 140699ebb4caSwyllys /* Append the new policy info to the root node. */ 140799ebb4caSwyllys if (root != NULL) { 140899ebb4caSwyllys xmlNodePtr pnode; 140999ebb4caSwyllys 141099ebb4caSwyllys pnode = xmlNewChild(root, NULL, 141130a5e8faSwyllys (const xmlChar *)KMF_POLICY_ELEMENT, NULL); 141299ebb4caSwyllys 141399ebb4caSwyllys ret = addPolicyNode(pnode, policy); 141499ebb4caSwyllys /* If that worked, update the DB file. */ 141599ebb4caSwyllys if (ret == KMF_OK) 141699ebb4caSwyllys ret = update_policyfile(doc, dbfilename); 141799ebb4caSwyllys } else { 141899ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE; 141999ebb4caSwyllys } 142099ebb4caSwyllys 142199ebb4caSwyllys 142299ebb4caSwyllys out: 142399ebb4caSwyllys if (ctxt != NULL) 142499ebb4caSwyllys xmlFreeParserCtxt(ctxt); 142599ebb4caSwyllys 142699ebb4caSwyllys if (doc != NULL) 142799ebb4caSwyllys xmlFreeDoc(doc); 142899ebb4caSwyllys 142999ebb4caSwyllys return (ret); 143099ebb4caSwyllys } 1431