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