xref: /openbsd-src/lib/libcrypto/x509/x509_cpols.c (revision 3374c67d44f9b75b98444cbf63020f777792342e)
1 /* $OpenBSD: x509_cpols.c,v 1.6 2022/11/26 16:08:54 tb Exp $ */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project 1999.
4  */
5 /* ====================================================================
6  * Copyright (c) 1999-2004 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58 
59 #include <stdio.h>
60 #include <string.h>
61 
62 #include <openssl/asn1.h>
63 #include <openssl/asn1t.h>
64 #include <openssl/conf.h>
65 #include <openssl/err.h>
66 #include <openssl/x509v3.h>
67 
68 #include "pcy_int.h"
69 #include "x509_local.h"
70 
71 /* Certificate policies extension support: this one is a bit complex... */
72 
73 static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol,
74     BIO *out, int indent);
75 static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
76     X509V3_CTX *ctx, char *value);
77 static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
78     int indent);
79 static void print_notice(BIO *out, USERNOTICE *notice, int indent);
80 static POLICYINFO *policy_section(X509V3_CTX *ctx,
81     STACK_OF(CONF_VALUE) *polstrs, int ia5org);
82 static POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
83     STACK_OF(CONF_VALUE) *unot, int ia5org);
84 static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos);
85 
86 const X509V3_EXT_METHOD v3_cpols = {
87 	.ext_nid = NID_certificate_policies,
88 	.ext_flags = 0,
89 	.it = &CERTIFICATEPOLICIES_it,
90 	.ext_new = NULL,
91 	.ext_free = NULL,
92 	.d2i = NULL,
93 	.i2d = NULL,
94 	.i2s = NULL,
95 	.s2i = NULL,
96 	.i2v = NULL,
97 	.v2i = NULL,
98 	.i2r = (X509V3_EXT_I2R)i2r_certpol,
99 	.r2i = (X509V3_EXT_R2I)r2i_certpol,
100 	.usr_data = NULL,
101 };
102 
103 static const ASN1_TEMPLATE CERTIFICATEPOLICIES_item_tt = {
104 	.flags = ASN1_TFLG_SEQUENCE_OF,
105 	.tag = 0,
106 	.offset = 0,
107 	.field_name = "CERTIFICATEPOLICIES",
108 	.item = &POLICYINFO_it,
109 };
110 
111 const ASN1_ITEM CERTIFICATEPOLICIES_it = {
112 	.itype = ASN1_ITYPE_PRIMITIVE,
113 	.utype = -1,
114 	.templates = &CERTIFICATEPOLICIES_item_tt,
115 	.tcount = 0,
116 	.funcs = NULL,
117 	.size = 0,
118 	.sname = "CERTIFICATEPOLICIES",
119 };
120 
121 
122 CERTIFICATEPOLICIES *
123 d2i_CERTIFICATEPOLICIES(CERTIFICATEPOLICIES **a, const unsigned char **in, long len)
124 {
125 	return (CERTIFICATEPOLICIES *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
126 	    &CERTIFICATEPOLICIES_it);
127 }
128 LCRYPTO_ALIAS(d2i_CERTIFICATEPOLICIES)
129 
130 int
131 i2d_CERTIFICATEPOLICIES(CERTIFICATEPOLICIES *a, unsigned char **out)
132 {
133 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &CERTIFICATEPOLICIES_it);
134 }
135 LCRYPTO_ALIAS(i2d_CERTIFICATEPOLICIES)
136 
137 CERTIFICATEPOLICIES *
138 CERTIFICATEPOLICIES_new(void)
139 {
140 	return (CERTIFICATEPOLICIES *)ASN1_item_new(&CERTIFICATEPOLICIES_it);
141 }
142 LCRYPTO_ALIAS(CERTIFICATEPOLICIES_new)
143 
144 void
145 CERTIFICATEPOLICIES_free(CERTIFICATEPOLICIES *a)
146 {
147 	ASN1_item_free((ASN1_VALUE *)a, &CERTIFICATEPOLICIES_it);
148 }
149 LCRYPTO_ALIAS(CERTIFICATEPOLICIES_free)
150 
151 static const ASN1_TEMPLATE POLICYINFO_seq_tt[] = {
152 	{
153 		.flags = 0,
154 		.tag = 0,
155 		.offset = offsetof(POLICYINFO, policyid),
156 		.field_name = "policyid",
157 		.item = &ASN1_OBJECT_it,
158 	},
159 	{
160 		.flags = ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
161 		.tag = 0,
162 		.offset = offsetof(POLICYINFO, qualifiers),
163 		.field_name = "qualifiers",
164 		.item = &POLICYQUALINFO_it,
165 	},
166 };
167 
168 const ASN1_ITEM POLICYINFO_it = {
169 	.itype = ASN1_ITYPE_SEQUENCE,
170 	.utype = V_ASN1_SEQUENCE,
171 	.templates = POLICYINFO_seq_tt,
172 	.tcount = sizeof(POLICYINFO_seq_tt) / sizeof(ASN1_TEMPLATE),
173 	.funcs = NULL,
174 	.size = sizeof(POLICYINFO),
175 	.sname = "POLICYINFO",
176 };
177 
178 
179 POLICYINFO *
180 d2i_POLICYINFO(POLICYINFO **a, const unsigned char **in, long len)
181 {
182 	return (POLICYINFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
183 	    &POLICYINFO_it);
184 }
185 LCRYPTO_ALIAS(d2i_POLICYINFO)
186 
187 int
188 i2d_POLICYINFO(POLICYINFO *a, unsigned char **out)
189 {
190 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &POLICYINFO_it);
191 }
192 LCRYPTO_ALIAS(i2d_POLICYINFO)
193 
194 POLICYINFO *
195 POLICYINFO_new(void)
196 {
197 	return (POLICYINFO *)ASN1_item_new(&POLICYINFO_it);
198 }
199 LCRYPTO_ALIAS(POLICYINFO_new)
200 
201 void
202 POLICYINFO_free(POLICYINFO *a)
203 {
204 	ASN1_item_free((ASN1_VALUE *)a, &POLICYINFO_it);
205 }
206 LCRYPTO_ALIAS(POLICYINFO_free)
207 
208 static const ASN1_TEMPLATE policydefault_tt = {
209 	.flags = 0,
210 	.tag = 0,
211 	.offset = offsetof(POLICYQUALINFO, d.other),
212 	.field_name = "d.other",
213 	.item = &ASN1_ANY_it,
214 };
215 
216 static const ASN1_ADB_TABLE POLICYQUALINFO_adbtbl[] = {
217 	{
218 		.value = NID_id_qt_cps,
219 		.tt = {
220 			.flags = 0,
221 			.tag = 0,
222 			.offset = offsetof(POLICYQUALINFO, d.cpsuri),
223 			.field_name = "d.cpsuri",
224 			.item = &ASN1_IA5STRING_it,
225 		},
226 
227 	},
228 	{
229 		.value = NID_id_qt_unotice,
230 		.tt = {
231 			.flags = 0,
232 			.tag = 0,
233 			.offset = offsetof(POLICYQUALINFO, d.usernotice),
234 			.field_name = "d.usernotice",
235 			.item = &USERNOTICE_it,
236 		},
237 
238 	},
239 };
240 
241 static const ASN1_ADB POLICYQUALINFO_adb = {
242 	.flags = 0,
243 	.offset = offsetof(POLICYQUALINFO, pqualid),
244 	.tbl = POLICYQUALINFO_adbtbl,
245 	.tblcount = sizeof(POLICYQUALINFO_adbtbl) / sizeof(ASN1_ADB_TABLE),
246 	.default_tt = &policydefault_tt,
247 	.null_tt = NULL,
248 };
249 
250 static const ASN1_TEMPLATE POLICYQUALINFO_seq_tt[] = {
251 	{
252 		.flags = 0,
253 		.tag = 0,
254 		.offset = offsetof(POLICYQUALINFO, pqualid),
255 		.field_name = "pqualid",
256 		.item = &ASN1_OBJECT_it,
257 	},
258 	{
259 		.flags = ASN1_TFLG_ADB_OID,
260 		.tag = -1,
261 		.offset = 0,
262 		.field_name = "POLICYQUALINFO",
263 		.item = (const ASN1_ITEM *)&POLICYQUALINFO_adb,
264 	},
265 };
266 
267 const ASN1_ITEM POLICYQUALINFO_it = {
268 	.itype = ASN1_ITYPE_SEQUENCE,
269 	.utype = V_ASN1_SEQUENCE,
270 	.templates = POLICYQUALINFO_seq_tt,
271 	.tcount = sizeof(POLICYQUALINFO_seq_tt) / sizeof(ASN1_TEMPLATE),
272 	.funcs = NULL,
273 	.size = sizeof(POLICYQUALINFO),
274 	.sname = "POLICYQUALINFO",
275 };
276 
277 
278 POLICYQUALINFO *
279 d2i_POLICYQUALINFO(POLICYQUALINFO **a, const unsigned char **in, long len)
280 {
281 	return (POLICYQUALINFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
282 	    &POLICYQUALINFO_it);
283 }
284 LCRYPTO_ALIAS(d2i_POLICYQUALINFO)
285 
286 int
287 i2d_POLICYQUALINFO(POLICYQUALINFO *a, unsigned char **out)
288 {
289 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &POLICYQUALINFO_it);
290 }
291 LCRYPTO_ALIAS(i2d_POLICYQUALINFO)
292 
293 POLICYQUALINFO *
294 POLICYQUALINFO_new(void)
295 {
296 	return (POLICYQUALINFO *)ASN1_item_new(&POLICYQUALINFO_it);
297 }
298 LCRYPTO_ALIAS(POLICYQUALINFO_new)
299 
300 void
301 POLICYQUALINFO_free(POLICYQUALINFO *a)
302 {
303 	ASN1_item_free((ASN1_VALUE *)a, &POLICYQUALINFO_it);
304 }
305 LCRYPTO_ALIAS(POLICYQUALINFO_free)
306 
307 static const ASN1_TEMPLATE USERNOTICE_seq_tt[] = {
308 	{
309 		.flags = ASN1_TFLG_OPTIONAL,
310 		.tag = 0,
311 		.offset = offsetof(USERNOTICE, noticeref),
312 		.field_name = "noticeref",
313 		.item = &NOTICEREF_it,
314 	},
315 	{
316 		.flags = ASN1_TFLG_OPTIONAL,
317 		.tag = 0,
318 		.offset = offsetof(USERNOTICE, exptext),
319 		.field_name = "exptext",
320 		.item = &DISPLAYTEXT_it,
321 	},
322 };
323 
324 const ASN1_ITEM USERNOTICE_it = {
325 	.itype = ASN1_ITYPE_SEQUENCE,
326 	.utype = V_ASN1_SEQUENCE,
327 	.templates = USERNOTICE_seq_tt,
328 	.tcount = sizeof(USERNOTICE_seq_tt) / sizeof(ASN1_TEMPLATE),
329 	.funcs = NULL,
330 	.size = sizeof(USERNOTICE),
331 	.sname = "USERNOTICE",
332 };
333 
334 
335 USERNOTICE *
336 d2i_USERNOTICE(USERNOTICE **a, const unsigned char **in, long len)
337 {
338 	return (USERNOTICE *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
339 	    &USERNOTICE_it);
340 }
341 LCRYPTO_ALIAS(d2i_USERNOTICE)
342 
343 int
344 i2d_USERNOTICE(USERNOTICE *a, unsigned char **out)
345 {
346 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &USERNOTICE_it);
347 }
348 LCRYPTO_ALIAS(i2d_USERNOTICE)
349 
350 USERNOTICE *
351 USERNOTICE_new(void)
352 {
353 	return (USERNOTICE *)ASN1_item_new(&USERNOTICE_it);
354 }
355 LCRYPTO_ALIAS(USERNOTICE_new)
356 
357 void
358 USERNOTICE_free(USERNOTICE *a)
359 {
360 	ASN1_item_free((ASN1_VALUE *)a, &USERNOTICE_it);
361 }
362 LCRYPTO_ALIAS(USERNOTICE_free)
363 
364 static const ASN1_TEMPLATE NOTICEREF_seq_tt[] = {
365 	{
366 		.flags = 0,
367 		.tag = 0,
368 		.offset = offsetof(NOTICEREF, organization),
369 		.field_name = "organization",
370 		.item = &DISPLAYTEXT_it,
371 	},
372 	{
373 		.flags = ASN1_TFLG_SEQUENCE_OF,
374 		.tag = 0,
375 		.offset = offsetof(NOTICEREF, noticenos),
376 		.field_name = "noticenos",
377 		.item = &ASN1_INTEGER_it,
378 	},
379 };
380 
381 const ASN1_ITEM NOTICEREF_it = {
382 	.itype = ASN1_ITYPE_SEQUENCE,
383 	.utype = V_ASN1_SEQUENCE,
384 	.templates = NOTICEREF_seq_tt,
385 	.tcount = sizeof(NOTICEREF_seq_tt) / sizeof(ASN1_TEMPLATE),
386 	.funcs = NULL,
387 	.size = sizeof(NOTICEREF),
388 	.sname = "NOTICEREF",
389 };
390 
391 
392 NOTICEREF *
393 d2i_NOTICEREF(NOTICEREF **a, const unsigned char **in, long len)
394 {
395 	return (NOTICEREF *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
396 	    &NOTICEREF_it);
397 }
398 LCRYPTO_ALIAS(d2i_NOTICEREF)
399 
400 int
401 i2d_NOTICEREF(NOTICEREF *a, unsigned char **out)
402 {
403 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &NOTICEREF_it);
404 }
405 LCRYPTO_ALIAS(i2d_NOTICEREF)
406 
407 NOTICEREF *
408 NOTICEREF_new(void)
409 {
410 	return (NOTICEREF *)ASN1_item_new(&NOTICEREF_it);
411 }
412 LCRYPTO_ALIAS(NOTICEREF_new)
413 
414 void
415 NOTICEREF_free(NOTICEREF *a)
416 {
417 	ASN1_item_free((ASN1_VALUE *)a, &NOTICEREF_it);
418 }
419 LCRYPTO_ALIAS(NOTICEREF_free)
420 
421 static STACK_OF(POLICYINFO) *
422 r2i_certpol(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *value)
423 {
424 	STACK_OF(POLICYINFO) *pols = NULL;
425 	char *pstr;
426 	POLICYINFO *pol;
427 	ASN1_OBJECT *pobj;
428 	STACK_OF(CONF_VALUE) *vals;
429 	CONF_VALUE *cnf;
430 	int i, ia5org;
431 
432 	pols = sk_POLICYINFO_new_null();
433 	if (pols == NULL) {
434 		X509V3error(ERR_R_MALLOC_FAILURE);
435 		return NULL;
436 	}
437 	vals = X509V3_parse_list(value);
438 	if (vals == NULL) {
439 		X509V3error(ERR_R_X509V3_LIB);
440 		goto err;
441 	}
442 	ia5org = 0;
443 	for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
444 		cnf = sk_CONF_VALUE_value(vals, i);
445 		if (cnf->value || !cnf->name) {
446 			X509V3error(X509V3_R_INVALID_POLICY_IDENTIFIER);
447 			X509V3_conf_err(cnf);
448 			goto err;
449 		}
450 		pstr = cnf->name;
451 		if (!strcmp(pstr, "ia5org")) {
452 			ia5org = 1;
453 			continue;
454 		} else if (*pstr == '@') {
455 			STACK_OF(CONF_VALUE) *polsect;
456 			polsect = X509V3_get_section(ctx, pstr + 1);
457 			if (!polsect) {
458 				X509V3error(X509V3_R_INVALID_SECTION);
459 				X509V3_conf_err(cnf);
460 				goto err;
461 			}
462 			pol = policy_section(ctx, polsect, ia5org);
463 			X509V3_section_free(ctx, polsect);
464 			if (!pol)
465 				goto err;
466 		} else {
467 			if (!(pobj = OBJ_txt2obj(cnf->name, 0))) {
468 				X509V3error(X509V3_R_INVALID_OBJECT_IDENTIFIER);
469 				X509V3_conf_err(cnf);
470 				goto err;
471 			}
472 			pol = POLICYINFO_new();
473 			pol->policyid = pobj;
474 		}
475 		if (!sk_POLICYINFO_push(pols, pol)){
476 			POLICYINFO_free(pol);
477 			X509V3error(ERR_R_MALLOC_FAILURE);
478 			goto err;
479 		}
480 	}
481 	sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
482 	return pols;
483 
484 err:
485 	sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
486 	sk_POLICYINFO_pop_free(pols, POLICYINFO_free);
487 	return NULL;
488 }
489 
490 static POLICYINFO *
491 policy_section(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *polstrs, int ia5org)
492 {
493 	int i;
494 	CONF_VALUE *cnf;
495 	POLICYINFO *pol;
496 	POLICYQUALINFO *nqual = NULL;
497 
498 	if ((pol = POLICYINFO_new()) == NULL)
499 		goto merr;
500 	for (i = 0; i < sk_CONF_VALUE_num(polstrs); i++) {
501 		cnf = sk_CONF_VALUE_value(polstrs, i);
502 		if (strcmp(cnf->name, "policyIdentifier") == 0) {
503 			ASN1_OBJECT *pobj;
504 
505 			if ((pobj = OBJ_txt2obj(cnf->value, 0)) == NULL) {
506 				X509V3error(X509V3_R_INVALID_OBJECT_IDENTIFIER);
507 				X509V3_conf_err(cnf);
508 				goto err;
509 			}
510 			pol->policyid = pobj;
511 		} else if (name_cmp(cnf->name, "CPS") == 0) {
512 			if ((nqual = POLICYQUALINFO_new()) == NULL)
513 				goto merr;
514 			nqual->pqualid = OBJ_nid2obj(NID_id_qt_cps);
515 			nqual->d.cpsuri = ASN1_IA5STRING_new();
516 			if (nqual->d.cpsuri == NULL)
517 				goto merr;
518 			if (ASN1_STRING_set(nqual->d.cpsuri, cnf->value,
519 			    strlen(cnf->value)) == 0)
520 				goto merr;
521 
522 			if (pol->qualifiers == NULL) {
523 				pol->qualifiers = sk_POLICYQUALINFO_new_null();
524 				if (pol->qualifiers == NULL)
525 					goto merr;
526 			}
527 			if (sk_POLICYQUALINFO_push(pol->qualifiers, nqual) == 0)
528 				goto merr;
529 			nqual = NULL;
530 		} else if (name_cmp(cnf->name, "userNotice") == 0) {
531 			STACK_OF(CONF_VALUE) *unot;
532 			POLICYQUALINFO *qual;
533 
534 			if (*cnf->value != '@') {
535 				X509V3error(X509V3_R_EXPECTED_A_SECTION_NAME);
536 				X509V3_conf_err(cnf);
537 				goto err;
538 			}
539 			unot = X509V3_get_section(ctx, cnf->value + 1);
540 			if (unot == NULL) {
541 				X509V3error(X509V3_R_INVALID_SECTION);
542 				X509V3_conf_err(cnf);
543 				goto err;
544 			}
545 			qual = notice_section(ctx, unot, ia5org);
546 			X509V3_section_free(ctx, unot);
547 			if (qual == NULL)
548 				goto err;
549 
550 			if (pol->qualifiers == NULL) {
551 				pol->qualifiers = sk_POLICYQUALINFO_new_null();
552 				if (pol->qualifiers == NULL)
553 					goto merr;
554 			}
555 			if (sk_POLICYQUALINFO_push(pol->qualifiers, qual) == 0)
556 				goto merr;
557 		} else {
558 			X509V3error(X509V3_R_INVALID_OPTION);
559 			X509V3_conf_err(cnf);
560 			goto err;
561 		}
562 	}
563 	if (pol->policyid == NULL) {
564 		X509V3error(X509V3_R_NO_POLICY_IDENTIFIER);
565 		goto err;
566 	}
567 
568 	return pol;
569 
570 merr:
571 	X509V3error(ERR_R_MALLOC_FAILURE);
572 
573 err:
574 	POLICYQUALINFO_free(nqual);
575 	POLICYINFO_free(pol);
576 	return NULL;
577 }
578 
579 static POLICYQUALINFO *
580 notice_section(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *unot, int ia5org)
581 {
582 	int i, ret;
583 	CONF_VALUE *cnf;
584 	USERNOTICE *not;
585 	POLICYQUALINFO *qual;
586 
587 	if (!(qual = POLICYQUALINFO_new()))
588 		goto merr;
589 	qual->pqualid = OBJ_nid2obj(NID_id_qt_unotice);
590 	if (!(not = USERNOTICE_new()))
591 		goto merr;
592 	qual->d.usernotice = not;
593 	for (i = 0; i < sk_CONF_VALUE_num(unot); i++) {
594 		cnf = sk_CONF_VALUE_value(unot, i);
595 		if (!strcmp(cnf->name, "explicitText")) {
596 			if (not->exptext == NULL) {
597 				not->exptext = ASN1_VISIBLESTRING_new();
598 				if (not->exptext == NULL)
599 					goto merr;
600 			}
601 			if (!ASN1_STRING_set(not->exptext, cnf->value,
602 			    strlen(cnf->value)))
603 				goto merr;
604 		} else if (!strcmp(cnf->name, "organization")) {
605 			NOTICEREF *nref;
606 			if (!not->noticeref) {
607 				if (!(nref = NOTICEREF_new()))
608 					goto merr;
609 				not->noticeref = nref;
610 			} else
611 				nref = not->noticeref;
612 			if (ia5org)
613 				nref->organization->type = V_ASN1_IA5STRING;
614 			else
615 				nref->organization->type = V_ASN1_VISIBLESTRING;
616 			if (!ASN1_STRING_set(nref->organization, cnf->value,
617 			    strlen(cnf->value)))
618 				goto merr;
619 		} else if (!strcmp(cnf->name, "noticeNumbers")) {
620 			NOTICEREF *nref;
621 			STACK_OF(CONF_VALUE) *nos;
622 			if (!not->noticeref) {
623 				if (!(nref = NOTICEREF_new()))
624 					goto merr;
625 				not->noticeref = nref;
626 			} else
627 				nref = not->noticeref;
628 			nos = X509V3_parse_list(cnf->value);
629 			if (!nos || !sk_CONF_VALUE_num(nos)) {
630 				X509V3error(X509V3_R_INVALID_NUMBERS);
631 				X509V3_conf_err(cnf);
632 				if (nos != NULL)
633 					sk_CONF_VALUE_pop_free(nos,
634 					    X509V3_conf_free);
635 				goto err;
636 			}
637 			ret = nref_nos(nref->noticenos, nos);
638 			sk_CONF_VALUE_pop_free(nos, X509V3_conf_free);
639 			if (!ret)
640 				goto err;
641 		} else {
642 			X509V3error(X509V3_R_INVALID_OPTION);
643 			X509V3_conf_err(cnf);
644 			goto err;
645 		}
646 	}
647 
648 	if (not->noticeref &&
649 	    (!not->noticeref->noticenos || !not->noticeref->organization)) {
650 		X509V3error(X509V3_R_NEED_ORGANIZATION_AND_NUMBERS);
651 		goto err;
652 	}
653 
654 	return qual;
655 
656 merr:
657 	X509V3error(ERR_R_MALLOC_FAILURE);
658 
659 err:
660 	POLICYQUALINFO_free(qual);
661 	return NULL;
662 }
663 
664 static int
665 nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos)
666 {
667 	CONF_VALUE *cnf;
668 	ASN1_INTEGER *aint;
669 	int i;
670 
671 	for (i = 0; i < sk_CONF_VALUE_num(nos); i++) {
672 		cnf = sk_CONF_VALUE_value(nos, i);
673 		if (!(aint = s2i_ASN1_INTEGER(NULL, cnf->name))) {
674 			X509V3error(X509V3_R_INVALID_NUMBER);
675 			goto err;
676 		}
677 		if (!sk_ASN1_INTEGER_push(nnums, aint))
678 			goto merr;
679 	}
680 	return 1;
681 
682 merr:
683 	X509V3error(ERR_R_MALLOC_FAILURE);
684 
685 err:
686 	sk_ASN1_INTEGER_pop_free(nnums, ASN1_STRING_free);
687 	return 0;
688 }
689 
690 static int
691 i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol, BIO *out,
692     int indent)
693 {
694 	int i;
695 	POLICYINFO *pinfo;
696 
697 	/* First print out the policy OIDs */
698 	for (i = 0; i < sk_POLICYINFO_num(pol); i++) {
699 		pinfo = sk_POLICYINFO_value(pol, i);
700 		BIO_printf(out, "%*sPolicy: ", indent, "");
701 		i2a_ASN1_OBJECT(out, pinfo->policyid);
702 		BIO_puts(out, "\n");
703 		if (pinfo->qualifiers)
704 			print_qualifiers(out, pinfo->qualifiers, indent + 2);
705 	}
706 	return 1;
707 }
708 
709 static void
710 print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals, int indent)
711 {
712 	POLICYQUALINFO *qualinfo;
713 	int i;
714 
715 	for (i = 0; i < sk_POLICYQUALINFO_num(quals); i++) {
716 		qualinfo = sk_POLICYQUALINFO_value(quals, i);
717 		switch (OBJ_obj2nid(qualinfo->pqualid)) {
718 		case NID_id_qt_cps:
719 			BIO_printf(out, "%*sCPS: %.*s\n", indent, "",
720 			    qualinfo->d.cpsuri->length,
721 			    qualinfo->d.cpsuri->data);
722 			break;
723 
724 		case NID_id_qt_unotice:
725 			BIO_printf(out, "%*sUser Notice:\n", indent, "");
726 			print_notice(out, qualinfo->d.usernotice, indent + 2);
727 			break;
728 
729 		default:
730 			BIO_printf(out, "%*sUnknown Qualifier: ",
731 			    indent + 2, "");
732 
733 			i2a_ASN1_OBJECT(out, qualinfo->pqualid);
734 			BIO_puts(out, "\n");
735 			break;
736 		}
737 	}
738 }
739 
740 static void
741 print_notice(BIO *out, USERNOTICE *notice, int indent)
742 {
743 	int i;
744 
745 	if (notice->noticeref) {
746 		NOTICEREF *ref;
747 		ref = notice->noticeref;
748 		BIO_printf(out, "%*sOrganization: %.*s\n", indent, "",
749 		    ref->organization->length, ref->organization->data);
750 		BIO_printf(out, "%*sNumber%s: ", indent, "",
751 		    sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : "");
752 		for (i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) {
753 			ASN1_INTEGER *num;
754 			char *tmp;
755 			num = sk_ASN1_INTEGER_value(ref->noticenos, i);
756 			if (i)
757 				BIO_puts(out, ", ");
758 			tmp = i2s_ASN1_INTEGER(NULL, num);
759 			BIO_puts(out, tmp);
760 			free(tmp);
761 		}
762 		BIO_puts(out, "\n");
763 	}
764 	if (notice->exptext)
765 		BIO_printf(out, "%*sExplicit Text: %.*s\n", indent, "",
766 		    notice->exptext->length, notice->exptext->data);
767 }
768 
769 void
770 X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent)
771 {
772 	const X509_POLICY_DATA *dat = node->data;
773 
774 	BIO_printf(out, "%*sPolicy: ", indent, "");
775 
776 	i2a_ASN1_OBJECT(out, dat->valid_policy);
777 	BIO_puts(out, "\n");
778 	BIO_printf(out, "%*s%s\n", indent + 2, "",
779 	    node_data_critical(dat) ? "Critical" : "Non Critical");
780 	if (dat->qualifier_set)
781 		print_qualifiers(out, dat->qualifier_set, indent + 2);
782 	else
783 		BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, "");
784 }
785 LCRYPTO_ALIAS(X509_POLICY_NODE_print)
786