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
20269e59f9SJan Pechanec *
21269e59f9SJan 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>
29269e59f9SJan 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
addFormatting(xmlNodePtr parent,char * text)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
parseOCSPValidation(xmlNodePtr node,KMF_VALIDATION_POLICY * vinfo)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
parseValidation(xmlNodePtr node,KMF_VALIDATION_POLICY * vinfo,KMF_POLICY_RECORD * policy)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 *
kmf_ku_to_string(uint32_t bitfield)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
kmf_string_to_ku(char * kustring)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
parseKeyUsageSet(xmlNodePtr node,uint32_t * kubits)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 *
dup_oid(KMF_OID * oldoid)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 *
kmf_ekuname_to_oid(char * ekuname)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 *
kmf_oid_to_ekuname(KMF_OID * oid)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
parseExtKeyUsage(xmlNodePtr node,KMF_EKU_POLICY * ekus)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
388269e59f9SJan Pechanec static KMF_RETURN
parseMapper(xmlNodePtr node,KMF_MAPPER_RECORD * mapper)389269e59f9SJan Pechanec parseMapper(xmlNodePtr node, KMF_MAPPER_RECORD *mapper)
390269e59f9SJan Pechanec {
391269e59f9SJan Pechanec xmlNodePtr n;
392269e59f9SJan Pechanec
393269e59f9SJan Pechanec n = node;
394269e59f9SJan Pechanec mapper->mapname = (char *)xmlGetProp(n,
395269e59f9SJan Pechanec (const xmlChar *)KMF_CERT_MAPPER_NAME_ATTR);
396269e59f9SJan Pechanec mapper->dir = (char *)xmlGetProp(n,
397269e59f9SJan Pechanec (const xmlChar *)KMF_CERT_MAPPER_DIR_ATTR);
398269e59f9SJan Pechanec mapper->pathname = (char *)xmlGetProp(n,
399269e59f9SJan Pechanec (const xmlChar *)KMF_CERT_MAPPER_PATH_ATTR);
400269e59f9SJan Pechanec mapper->options = (char *)xmlGetProp(n,
401269e59f9SJan Pechanec (const xmlChar *)KMF_CERT_MAPPER_OPTIONS_ATTR);
402269e59f9SJan Pechanec
403269e59f9SJan Pechanec /*
404269e59f9SJan Pechanec * These are set according to whether mapper setting is taken from the
405269e59f9SJan Pechanec * database or init function attributes.
406269e59f9SJan Pechanec */
407269e59f9SJan Pechanec mapper->curpathname = NULL;
408269e59f9SJan Pechanec mapper->curoptions = NULL;
409269e59f9SJan Pechanec
410269e59f9SJan Pechanec return (KMF_OK);
411269e59f9SJan Pechanec }
412269e59f9SJan Pechanec
41399ebb4caSwyllys int
parsePolicyElement(xmlNodePtr node,KMF_POLICY_RECORD * policy)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);
475269e59f9SJan Pechanec } else if (!xmlStrcmp((const xmlChar *)n->name,
476269e59f9SJan Pechanec (const xmlChar *)KMF_CERT_MAPPER_ELEMENT)) {
477269e59f9SJan Pechanec ret = parseMapper(n, &policy->mapper);
478269e59f9SJan Pechanec if (ret != KMF_OK)
479269e59f9SJan Pechanec return (ret);
48099ebb4caSwyllys }
48199ebb4caSwyllys
48299ebb4caSwyllys n = n->next;
48399ebb4caSwyllys }
48499ebb4caSwyllys }
48599ebb4caSwyllys
48699ebb4caSwyllys return (ret);
48799ebb4caSwyllys }
48899ebb4caSwyllys
48999ebb4caSwyllys static int
newprop(xmlNodePtr node,char * attrname,char * src)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
AddCRLNodes(xmlNodePtr node,KMF_CRL_POLICY * crlinfo)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
AddOCSPNodes(xmlNodePtr parent,KMF_OCSP_POLICY * ocsp)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
AddValidationNodes(xmlNodePtr parent,KMF_POLICY_RECORD * policy)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
667269e59f9SJan Pechanec /*
668269e59f9SJan Pechanec * Add mapper policy info to the policy tree.
669269e59f9SJan Pechanec * Return non-zero on any failure, else 0 for success.
670269e59f9SJan Pechanec */
671269e59f9SJan Pechanec static KMF_RETURN
AddMapperPolicyNodes(xmlNodePtr parent,KMF_MAPPER_RECORD * mapper)672269e59f9SJan Pechanec AddMapperPolicyNodes(xmlNodePtr parent, KMF_MAPPER_RECORD *mapper)
673269e59f9SJan Pechanec {
674269e59f9SJan Pechanec KMF_RETURN ret = KMF_OK;
675269e59f9SJan Pechanec xmlNodePtr mapper_node;
676269e59f9SJan Pechanec
677269e59f9SJan Pechanec addFormatting(parent, "\n\t");
678269e59f9SJan Pechanec mapper_node = xmlNewChild(parent, NULL,
679269e59f9SJan Pechanec (const xmlChar *)KMF_CERT_MAPPER_ELEMENT, NULL);
680269e59f9SJan Pechanec if (mapper_node == NULL)
681269e59f9SJan Pechanec return (KMF_ERR_POLICY_ENGINE);
682269e59f9SJan Pechanec
683269e59f9SJan Pechanec if (mapper->mapname != NULL &&
684269e59f9SJan Pechanec newprop(mapper_node, KMF_CERT_MAPPER_NAME_ATTR, mapper->mapname)) {
685269e59f9SJan Pechanec ret = KMF_ERR_POLICY_ENGINE;
686269e59f9SJan Pechanec goto end;
687269e59f9SJan Pechanec }
688269e59f9SJan Pechanec
689269e59f9SJan Pechanec if (mapper->pathname != NULL &&
690269e59f9SJan Pechanec newprop(mapper_node, KMF_CERT_MAPPER_PATH_ATTR, mapper->pathname)) {
691269e59f9SJan Pechanec ret = KMF_ERR_POLICY_ENGINE;
692269e59f9SJan Pechanec goto end;
693269e59f9SJan Pechanec }
694269e59f9SJan Pechanec
695269e59f9SJan Pechanec if (mapper->dir != NULL &&
696269e59f9SJan Pechanec newprop(mapper_node, KMF_CERT_MAPPER_DIR_ATTR, mapper->dir)) {
697269e59f9SJan Pechanec ret = KMF_ERR_POLICY_ENGINE;
698269e59f9SJan Pechanec goto end;
699269e59f9SJan Pechanec }
700269e59f9SJan Pechanec
701269e59f9SJan Pechanec if (mapper->options != NULL &&
702269e59f9SJan Pechanec newprop(mapper_node, KMF_CERT_MAPPER_OPTIONS_ATTR, mapper->options))
703269e59f9SJan Pechanec ret = KMF_ERR_POLICY_ENGINE;
704269e59f9SJan Pechanec
705269e59f9SJan Pechanec if (ret == KMF_OK) {
706269e59f9SJan Pechanec addFormatting(mapper_node, "\n\t");
707269e59f9SJan Pechanec addFormatting(parent, "\n");
708269e59f9SJan Pechanec }
709269e59f9SJan Pechanec
710269e59f9SJan Pechanec end:
711269e59f9SJan Pechanec if (ret != KMF_OK) {
712269e59f9SJan Pechanec xmlUnlinkNode(mapper_node);
713269e59f9SJan Pechanec xmlFreeNode(mapper_node);
714269e59f9SJan Pechanec }
715269e59f9SJan Pechanec return (ret);
716269e59f9SJan Pechanec }
717269e59f9SJan 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
AddKeyUsageNodes(xmlNodePtr parent,uint32_t kubits)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
AddExtKeyUsageNodes(xmlNodePtr parent,KMF_EKU_POLICY * ekus)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
kmf_free_eku_policy(KMF_EKU_POLICY * ekus)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
kmf_free_policy_record(KMF_POLICY_RECORD * policy)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)
842269e59f9SJan Pechanec FREE_POLICY_STR(policy->mapper.mapname)
843269e59f9SJan Pechanec FREE_POLICY_STR(policy->mapper.pathname)
844269e59f9SJan Pechanec FREE_POLICY_STR(policy->mapper.options)
845269e59f9SJan 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
kmf_get_policy(char * filename,char * policy_name,KMF_POLICY_RECORD * plc)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
kmf_set_policy(KMF_HANDLE_T handle,char * policyfile,char * policyname)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
deletePolicyNode(xmlNodePtr node,char * policy_name)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
update_policyfile(xmlDocPtr doc,char * filename)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
kmf_delete_policy_from_db(char * policy_name,char * dbfilename)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
addPolicyNode(xmlNodePtr pnode,KMF_POLICY_RECORD * policy)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 }
1267269e59f9SJan Pechanec if ((ret = AddMapperPolicyNodes(pnode, &policy->mapper))) {
1268269e59f9SJan Pechanec goto out;
1269269e59f9SJan 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 KMF_RETURN
kmf_verify_policy(KMF_POLICY_RECORD * policy)128330a5e8faSwyllys kmf_verify_policy(KMF_POLICY_RECORD *policy)
128499ebb4caSwyllys {
128599ebb4caSwyllys KMF_RETURN ret = KMF_OK;
128699ebb4caSwyllys boolean_t has_ta;
128799ebb4caSwyllys
128899ebb4caSwyllys if (policy->name == NULL || !strlen(policy->name))
128999ebb4caSwyllys return (KMF_ERR_POLICY_NAME);
129099ebb4caSwyllys
129199ebb4caSwyllys /* Check the TA related policy */
1292*fc2613b0SWyllys Ingersoll if (policy->ta_name != NULL &&
1293*fc2613b0SWyllys Ingersoll strcasecmp(policy->ta_name, "search") == 0) {
1294*fc2613b0SWyllys Ingersoll has_ta = B_TRUE;
1295*fc2613b0SWyllys Ingersoll } else if (policy->ta_name != NULL && policy->ta_serial != NULL) {
129699ebb4caSwyllys has_ta = B_TRUE;
129799ebb4caSwyllys } else if (policy->ta_name == NULL && policy->ta_serial == NULL) {
129899ebb4caSwyllys has_ta = B_FALSE;
129999ebb4caSwyllys } else {
130099ebb4caSwyllys /*
130199ebb4caSwyllys * If the TA cert is set, then both name and serial number
130299ebb4caSwyllys * need to be specified.
130399ebb4caSwyllys */
130499ebb4caSwyllys return (KMF_ERR_TA_POLICY);
130599ebb4caSwyllys }
130699ebb4caSwyllys
130799ebb4caSwyllys if (has_ta == B_FALSE && policy->ignore_trust_anchor == B_FALSE)
130899ebb4caSwyllys return (KMF_ERR_TA_POLICY);
130999ebb4caSwyllys
131099ebb4caSwyllys if (policy->revocation & KMF_REVOCATION_METHOD_OCSP) {
131199ebb4caSwyllys /*
131299ebb4caSwyllys * For OCSP, either use a fixed responder or use the
131399ebb4caSwyllys * value from the cert, but not both.
131499ebb4caSwyllys */
131599ebb4caSwyllys if ((policy->VAL_OCSP_BASIC.responderURI == NULL &&
131699ebb4caSwyllys policy->VAL_OCSP_BASIC.uri_from_cert == B_FALSE) ||
131799ebb4caSwyllys (policy->VAL_OCSP_BASIC.responderURI != NULL &&
131899ebb4caSwyllys policy->VAL_OCSP_BASIC.uri_from_cert == B_TRUE))
131999ebb4caSwyllys return (KMF_ERR_OCSP_POLICY);
132099ebb4caSwyllys
132199ebb4caSwyllys /*
132299ebb4caSwyllys * If the OCSP responder cert is set, then both name and serial
132399ebb4caSwyllys * number need to be specified.
132499ebb4caSwyllys */
132599ebb4caSwyllys if ((policy->VAL_OCSP_RESP_CERT.name != NULL &&
132699ebb4caSwyllys policy->VAL_OCSP_RESP_CERT.serial == NULL) ||
132799ebb4caSwyllys (policy->VAL_OCSP_RESP_CERT.name == NULL &&
132899ebb4caSwyllys policy->VAL_OCSP_RESP_CERT.serial != NULL))
132999ebb4caSwyllys return (KMF_ERR_OCSP_POLICY);
133099ebb4caSwyllys }
133199ebb4caSwyllys
133299ebb4caSwyllys return (ret);
133399ebb4caSwyllys }
133499ebb4caSwyllys
133599ebb4caSwyllys /*
133699ebb4caSwyllys * Update the KMF policy file by creating a new XML Policy doc tree
133799ebb4caSwyllys * from the data in the KMF_POLICY_RECORD structure. If "check_policy"
133899ebb4caSwyllys * is true, then we check the policy sanity also.
133999ebb4caSwyllys */
134099ebb4caSwyllys KMF_RETURN
kmf_add_policy_to_db(KMF_POLICY_RECORD * policy,char * dbfilename,boolean_t check_policy)134130a5e8faSwyllys kmf_add_policy_to_db(KMF_POLICY_RECORD *policy, char *dbfilename,
134299ebb4caSwyllys boolean_t check_policy)
134399ebb4caSwyllys {
134499ebb4caSwyllys KMF_RETURN ret = KMF_OK;
134599ebb4caSwyllys xmlDocPtr doc = NULL;
134699ebb4caSwyllys xmlNodePtr root, node;
134799ebb4caSwyllys xmlParserCtxtPtr ctxt = NULL;
134899ebb4caSwyllys
134999ebb4caSwyllys if (policy == NULL || dbfilename == NULL)
135099ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
135199ebb4caSwyllys
135299ebb4caSwyllys if (check_policy == B_TRUE) {
135330a5e8faSwyllys if (ret = kmf_verify_policy(policy))
135430a5e8faSwyllys return (ret);
135599ebb4caSwyllys }
135699ebb4caSwyllys
135799ebb4caSwyllys /* If the policyDB exists, load it into memory */
135899ebb4caSwyllys if (!access(dbfilename, R_OK)) {
135999ebb4caSwyllys
136099ebb4caSwyllys /* Create a parser context */
136199ebb4caSwyllys ctxt = xmlNewParserCtxt();
136299ebb4caSwyllys if (ctxt == NULL)
136399ebb4caSwyllys return (KMF_ERR_POLICY_DB_FORMAT);
136499ebb4caSwyllys
136599ebb4caSwyllys doc = xmlCtxtReadFile(ctxt, dbfilename, NULL,
136699ebb4caSwyllys XML_PARSE_DTDVALID | XML_PARSE_NOERROR |
136799ebb4caSwyllys XML_PARSE_NOWARNING);
136899ebb4caSwyllys if (doc == NULL || ctxt->valid == 0) {
136999ebb4caSwyllys ret = KMF_ERR_POLICY_DB_FORMAT;
137099ebb4caSwyllys goto out;
137199ebb4caSwyllys }
137299ebb4caSwyllys
137399ebb4caSwyllys root = xmlDocGetRootElement(doc);
137499ebb4caSwyllys if (root == NULL) {
137599ebb4caSwyllys ret = KMF_ERR_POLICY_DB_FORMAT;
137699ebb4caSwyllys goto out;
137799ebb4caSwyllys }
137899ebb4caSwyllys
137999ebb4caSwyllys node = root->xmlChildrenNode;
138099ebb4caSwyllys /*
138199ebb4caSwyllys * If the DB has an existing policy of the
138299ebb4caSwyllys * same name, delete it from the tree.
138399ebb4caSwyllys */
138499ebb4caSwyllys ret = deletePolicyNode(node, policy->name);
138599ebb4caSwyllys if (ret == KMF_ERR_POLICY_NOT_FOUND)
138699ebb4caSwyllys ret = KMF_OK;
138799ebb4caSwyllys } else {
138899ebb4caSwyllys /* Initialize a new DB tree */
138999ebb4caSwyllys doc = xmlNewDoc((const xmlChar *)"1.0");
139099ebb4caSwyllys if (doc == NULL)
139199ebb4caSwyllys return (KMF_ERR_POLICY_ENGINE);
139299ebb4caSwyllys
139399ebb4caSwyllys /*
139499ebb4caSwyllys * Add the DOCTYPE header to the tree so the
139599ebb4caSwyllys * DTD link is embedded
139699ebb4caSwyllys */
139799ebb4caSwyllys doc->intSubset = xmlCreateIntSubset(doc,
139830a5e8faSwyllys (const xmlChar *)KMF_POLICY_ROOT,
139930a5e8faSwyllys NULL, (const xmlChar *)KMF_POLICY_DTD);
140099ebb4caSwyllys
140199ebb4caSwyllys root = xmlNewDocNode(doc, NULL,
140230a5e8faSwyllys (const xmlChar *)KMF_POLICY_ROOT, NULL);
140399ebb4caSwyllys if (root != NULL) {
14045ad42b1bSSurya Prakki (void) xmlDocSetRootElement(doc, root);
140599ebb4caSwyllys }
140699ebb4caSwyllys }
140799ebb4caSwyllys
140899ebb4caSwyllys /* Append the new policy info to the root node. */
140999ebb4caSwyllys if (root != NULL) {
141099ebb4caSwyllys xmlNodePtr pnode;
141199ebb4caSwyllys
141299ebb4caSwyllys pnode = xmlNewChild(root, NULL,
141330a5e8faSwyllys (const xmlChar *)KMF_POLICY_ELEMENT, NULL);
141499ebb4caSwyllys
141599ebb4caSwyllys ret = addPolicyNode(pnode, policy);
141699ebb4caSwyllys /* If that worked, update the DB file. */
141799ebb4caSwyllys if (ret == KMF_OK)
141899ebb4caSwyllys ret = update_policyfile(doc, dbfilename);
141999ebb4caSwyllys } else {
142099ebb4caSwyllys ret = KMF_ERR_POLICY_ENGINE;
142199ebb4caSwyllys }
142299ebb4caSwyllys
142399ebb4caSwyllys
142499ebb4caSwyllys out:
142599ebb4caSwyllys if (ctxt != NULL)
142699ebb4caSwyllys xmlFreeParserCtxt(ctxt);
142799ebb4caSwyllys
142899ebb4caSwyllys if (doc != NULL)
142999ebb4caSwyllys xmlFreeDoc(doc);
143099ebb4caSwyllys
143199ebb4caSwyllys return (ret);
143299ebb4caSwyllys }
1433