xref: /dragonfly/crypto/libressl/crypto/x509/x509_cpols.c (revision 961e30ea7dc61d1112b778ea4981eac68129fb86)
1 /* $OpenBSD: x509_cpols.c,v 1.4 2022/01/14 08:16:13 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_lcl.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 *
d2i_CERTIFICATEPOLICIES(CERTIFICATEPOLICIES ** a,const unsigned char ** in,long len)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 
129 int
i2d_CERTIFICATEPOLICIES(CERTIFICATEPOLICIES * a,unsigned char ** out)130 i2d_CERTIFICATEPOLICIES(CERTIFICATEPOLICIES *a, unsigned char **out)
131 {
132           return ASN1_item_i2d((ASN1_VALUE *)a, out, &CERTIFICATEPOLICIES_it);
133 }
134 
135 CERTIFICATEPOLICIES *
CERTIFICATEPOLICIES_new(void)136 CERTIFICATEPOLICIES_new(void)
137 {
138           return (CERTIFICATEPOLICIES *)ASN1_item_new(&CERTIFICATEPOLICIES_it);
139 }
140 
141 void
CERTIFICATEPOLICIES_free(CERTIFICATEPOLICIES * a)142 CERTIFICATEPOLICIES_free(CERTIFICATEPOLICIES *a)
143 {
144           ASN1_item_free((ASN1_VALUE *)a, &CERTIFICATEPOLICIES_it);
145 }
146 
147 static const ASN1_TEMPLATE POLICYINFO_seq_tt[] = {
148           {
149                     .flags = 0,
150                     .tag = 0,
151                     .offset = offsetof(POLICYINFO, policyid),
152                     .field_name = "policyid",
153                     .item = &ASN1_OBJECT_it,
154           },
155           {
156                     .flags = ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
157                     .tag = 0,
158                     .offset = offsetof(POLICYINFO, qualifiers),
159                     .field_name = "qualifiers",
160                     .item = &POLICYQUALINFO_it,
161           },
162 };
163 
164 const ASN1_ITEM POLICYINFO_it = {
165           .itype = ASN1_ITYPE_SEQUENCE,
166           .utype = V_ASN1_SEQUENCE,
167           .templates = POLICYINFO_seq_tt,
168           .tcount = sizeof(POLICYINFO_seq_tt) / sizeof(ASN1_TEMPLATE),
169           .funcs = NULL,
170           .size = sizeof(POLICYINFO),
171           .sname = "POLICYINFO",
172 };
173 
174 
175 POLICYINFO *
d2i_POLICYINFO(POLICYINFO ** a,const unsigned char ** in,long len)176 d2i_POLICYINFO(POLICYINFO **a, const unsigned char **in, long len)
177 {
178           return (POLICYINFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
179               &POLICYINFO_it);
180 }
181 
182 int
i2d_POLICYINFO(POLICYINFO * a,unsigned char ** out)183 i2d_POLICYINFO(POLICYINFO *a, unsigned char **out)
184 {
185           return ASN1_item_i2d((ASN1_VALUE *)a, out, &POLICYINFO_it);
186 }
187 
188 POLICYINFO *
POLICYINFO_new(void)189 POLICYINFO_new(void)
190 {
191           return (POLICYINFO *)ASN1_item_new(&POLICYINFO_it);
192 }
193 
194 void
POLICYINFO_free(POLICYINFO * a)195 POLICYINFO_free(POLICYINFO *a)
196 {
197           ASN1_item_free((ASN1_VALUE *)a, &POLICYINFO_it);
198 }
199 
200 static const ASN1_TEMPLATE policydefault_tt = {
201           .flags = 0,
202           .tag = 0,
203           .offset = offsetof(POLICYQUALINFO, d.other),
204           .field_name = "d.other",
205           .item = &ASN1_ANY_it,
206 };
207 
208 static const ASN1_ADB_TABLE POLICYQUALINFO_adbtbl[] = {
209           {
210                     .value = NID_id_qt_cps,
211                     .tt = {
212                               .flags = 0,
213                               .tag = 0,
214                               .offset = offsetof(POLICYQUALINFO, d.cpsuri),
215                               .field_name = "d.cpsuri",
216                               .item = &ASN1_IA5STRING_it,
217                     },
218 
219           },
220           {
221                     .value = NID_id_qt_unotice,
222                     .tt = {
223                               .flags = 0,
224                               .tag = 0,
225                               .offset = offsetof(POLICYQUALINFO, d.usernotice),
226                               .field_name = "d.usernotice",
227                               .item = &USERNOTICE_it,
228                     },
229 
230           },
231 };
232 
233 static const ASN1_ADB POLICYQUALINFO_adb = {
234           .flags = 0,
235           .offset = offsetof(POLICYQUALINFO, pqualid),
236           .tbl = POLICYQUALINFO_adbtbl,
237           .tblcount = sizeof(POLICYQUALINFO_adbtbl) / sizeof(ASN1_ADB_TABLE),
238           .default_tt = &policydefault_tt,
239           .null_tt = NULL,
240 };
241 
242 static const ASN1_TEMPLATE POLICYQUALINFO_seq_tt[] = {
243           {
244                     .flags = 0,
245                     .tag = 0,
246                     .offset = offsetof(POLICYQUALINFO, pqualid),
247                     .field_name = "pqualid",
248                     .item = &ASN1_OBJECT_it,
249           },
250           {
251                     .flags = ASN1_TFLG_ADB_OID,
252                     .tag = -1,
253                     .offset = 0,
254                     .field_name = "POLICYQUALINFO",
255                     .item = (const ASN1_ITEM *)&POLICYQUALINFO_adb,
256           },
257 };
258 
259 const ASN1_ITEM POLICYQUALINFO_it = {
260           .itype = ASN1_ITYPE_SEQUENCE,
261           .utype = V_ASN1_SEQUENCE,
262           .templates = POLICYQUALINFO_seq_tt,
263           .tcount = sizeof(POLICYQUALINFO_seq_tt) / sizeof(ASN1_TEMPLATE),
264           .funcs = NULL,
265           .size = sizeof(POLICYQUALINFO),
266           .sname = "POLICYQUALINFO",
267 };
268 
269 
270 POLICYQUALINFO *
d2i_POLICYQUALINFO(POLICYQUALINFO ** a,const unsigned char ** in,long len)271 d2i_POLICYQUALINFO(POLICYQUALINFO **a, const unsigned char **in, long len)
272 {
273           return (POLICYQUALINFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
274               &POLICYQUALINFO_it);
275 }
276 
277 int
i2d_POLICYQUALINFO(POLICYQUALINFO * a,unsigned char ** out)278 i2d_POLICYQUALINFO(POLICYQUALINFO *a, unsigned char **out)
279 {
280           return ASN1_item_i2d((ASN1_VALUE *)a, out, &POLICYQUALINFO_it);
281 }
282 
283 POLICYQUALINFO *
POLICYQUALINFO_new(void)284 POLICYQUALINFO_new(void)
285 {
286           return (POLICYQUALINFO *)ASN1_item_new(&POLICYQUALINFO_it);
287 }
288 
289 void
POLICYQUALINFO_free(POLICYQUALINFO * a)290 POLICYQUALINFO_free(POLICYQUALINFO *a)
291 {
292           ASN1_item_free((ASN1_VALUE *)a, &POLICYQUALINFO_it);
293 }
294 
295 static const ASN1_TEMPLATE USERNOTICE_seq_tt[] = {
296           {
297                     .flags = ASN1_TFLG_OPTIONAL,
298                     .tag = 0,
299                     .offset = offsetof(USERNOTICE, noticeref),
300                     .field_name = "noticeref",
301                     .item = &NOTICEREF_it,
302           },
303           {
304                     .flags = ASN1_TFLG_OPTIONAL,
305                     .tag = 0,
306                     .offset = offsetof(USERNOTICE, exptext),
307                     .field_name = "exptext",
308                     .item = &DISPLAYTEXT_it,
309           },
310 };
311 
312 const ASN1_ITEM USERNOTICE_it = {
313           .itype = ASN1_ITYPE_SEQUENCE,
314           .utype = V_ASN1_SEQUENCE,
315           .templates = USERNOTICE_seq_tt,
316           .tcount = sizeof(USERNOTICE_seq_tt) / sizeof(ASN1_TEMPLATE),
317           .funcs = NULL,
318           .size = sizeof(USERNOTICE),
319           .sname = "USERNOTICE",
320 };
321 
322 
323 USERNOTICE *
d2i_USERNOTICE(USERNOTICE ** a,const unsigned char ** in,long len)324 d2i_USERNOTICE(USERNOTICE **a, const unsigned char **in, long len)
325 {
326           return (USERNOTICE *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
327               &USERNOTICE_it);
328 }
329 
330 int
i2d_USERNOTICE(USERNOTICE * a,unsigned char ** out)331 i2d_USERNOTICE(USERNOTICE *a, unsigned char **out)
332 {
333           return ASN1_item_i2d((ASN1_VALUE *)a, out, &USERNOTICE_it);
334 }
335 
336 USERNOTICE *
USERNOTICE_new(void)337 USERNOTICE_new(void)
338 {
339           return (USERNOTICE *)ASN1_item_new(&USERNOTICE_it);
340 }
341 
342 void
USERNOTICE_free(USERNOTICE * a)343 USERNOTICE_free(USERNOTICE *a)
344 {
345           ASN1_item_free((ASN1_VALUE *)a, &USERNOTICE_it);
346 }
347 
348 static const ASN1_TEMPLATE NOTICEREF_seq_tt[] = {
349           {
350                     .flags = 0,
351                     .tag = 0,
352                     .offset = offsetof(NOTICEREF, organization),
353                     .field_name = "organization",
354                     .item = &DISPLAYTEXT_it,
355           },
356           {
357                     .flags = ASN1_TFLG_SEQUENCE_OF,
358                     .tag = 0,
359                     .offset = offsetof(NOTICEREF, noticenos),
360                     .field_name = "noticenos",
361                     .item = &ASN1_INTEGER_it,
362           },
363 };
364 
365 const ASN1_ITEM NOTICEREF_it = {
366           .itype = ASN1_ITYPE_SEQUENCE,
367           .utype = V_ASN1_SEQUENCE,
368           .templates = NOTICEREF_seq_tt,
369           .tcount = sizeof(NOTICEREF_seq_tt) / sizeof(ASN1_TEMPLATE),
370           .funcs = NULL,
371           .size = sizeof(NOTICEREF),
372           .sname = "NOTICEREF",
373 };
374 
375 
376 NOTICEREF *
d2i_NOTICEREF(NOTICEREF ** a,const unsigned char ** in,long len)377 d2i_NOTICEREF(NOTICEREF **a, const unsigned char **in, long len)
378 {
379           return (NOTICEREF *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
380               &NOTICEREF_it);
381 }
382 
383 int
i2d_NOTICEREF(NOTICEREF * a,unsigned char ** out)384 i2d_NOTICEREF(NOTICEREF *a, unsigned char **out)
385 {
386           return ASN1_item_i2d((ASN1_VALUE *)a, out, &NOTICEREF_it);
387 }
388 
389 NOTICEREF *
NOTICEREF_new(void)390 NOTICEREF_new(void)
391 {
392           return (NOTICEREF *)ASN1_item_new(&NOTICEREF_it);
393 }
394 
395 void
NOTICEREF_free(NOTICEREF * a)396 NOTICEREF_free(NOTICEREF *a)
397 {
398           ASN1_item_free((ASN1_VALUE *)a, &NOTICEREF_it);
399 }
400 
STACK_OF(POLICYINFO)401 static STACK_OF(POLICYINFO) *
402 r2i_certpol(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *value)
403 {
404           STACK_OF(POLICYINFO) *pols = NULL;
405           char *pstr;
406           POLICYINFO *pol;
407           ASN1_OBJECT *pobj;
408           STACK_OF(CONF_VALUE) *vals;
409           CONF_VALUE *cnf;
410           int i, ia5org;
411 
412           pols = sk_POLICYINFO_new_null();
413           if (pols == NULL) {
414                     X509V3error(ERR_R_MALLOC_FAILURE);
415                     return NULL;
416           }
417           vals = X509V3_parse_list(value);
418           if (vals == NULL) {
419                     X509V3error(ERR_R_X509V3_LIB);
420                     goto err;
421           }
422           ia5org = 0;
423           for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
424                     cnf = sk_CONF_VALUE_value(vals, i);
425                     if (cnf->value || !cnf->name) {
426                               X509V3error(X509V3_R_INVALID_POLICY_IDENTIFIER);
427                               X509V3_conf_err(cnf);
428                               goto err;
429                     }
430                     pstr = cnf->name;
431                     if (!strcmp(pstr, "ia5org")) {
432                               ia5org = 1;
433                               continue;
434                     } else if (*pstr == '@') {
435                               STACK_OF(CONF_VALUE) *polsect;
436                               polsect = X509V3_get_section(ctx, pstr + 1);
437                               if (!polsect) {
438                                         X509V3error(X509V3_R_INVALID_SECTION);
439                                         X509V3_conf_err(cnf);
440                                         goto err;
441                               }
442                               pol = policy_section(ctx, polsect, ia5org);
443                               X509V3_section_free(ctx, polsect);
444                               if (!pol)
445                                         goto err;
446                     } else {
447                               if (!(pobj = OBJ_txt2obj(cnf->name, 0))) {
448                                         X509V3error(X509V3_R_INVALID_OBJECT_IDENTIFIER);
449                                         X509V3_conf_err(cnf);
450                                         goto err;
451                               }
452                               pol = POLICYINFO_new();
453                               pol->policyid = pobj;
454                     }
455                     if (!sk_POLICYINFO_push(pols, pol)){
456                               POLICYINFO_free(pol);
457                               X509V3error(ERR_R_MALLOC_FAILURE);
458                               goto err;
459                     }
460           }
461           sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
462           return pols;
463 
464 err:
465           sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
466           sk_POLICYINFO_pop_free(pols, POLICYINFO_free);
467           return NULL;
468 }
469 
470 static POLICYINFO *
policy_section(X509V3_CTX * ctx,STACK_OF (CONF_VALUE)* polstrs,int ia5org)471 policy_section(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *polstrs, int ia5org)
472 {
473           int i;
474           CONF_VALUE *cnf;
475           POLICYINFO *pol;
476           POLICYQUALINFO *nqual = NULL;
477 
478           if ((pol = POLICYINFO_new()) == NULL)
479                     goto merr;
480           for (i = 0; i < sk_CONF_VALUE_num(polstrs); i++) {
481                     cnf = sk_CONF_VALUE_value(polstrs, i);
482                     if (strcmp(cnf->name, "policyIdentifier") == 0) {
483                               ASN1_OBJECT *pobj;
484 
485                               if ((pobj = OBJ_txt2obj(cnf->value, 0)) == NULL) {
486                                         X509V3error(X509V3_R_INVALID_OBJECT_IDENTIFIER);
487                                         X509V3_conf_err(cnf);
488                                         goto err;
489                               }
490                               pol->policyid = pobj;
491                     } else if (name_cmp(cnf->name, "CPS") == 0) {
492                               if ((nqual = POLICYQUALINFO_new()) == NULL)
493                                         goto merr;
494                               nqual->pqualid = OBJ_nid2obj(NID_id_qt_cps);
495                               nqual->d.cpsuri = ASN1_IA5STRING_new();
496                               if (nqual->d.cpsuri == NULL)
497                                         goto merr;
498                               if (ASN1_STRING_set(nqual->d.cpsuri, cnf->value,
499                                   strlen(cnf->value)) == 0)
500                                         goto merr;
501 
502                               if (pol->qualifiers == NULL) {
503                                         pol->qualifiers = sk_POLICYQUALINFO_new_null();
504                                         if (pol->qualifiers == NULL)
505                                                   goto merr;
506                               }
507                               if (sk_POLICYQUALINFO_push(pol->qualifiers, nqual) == 0)
508                                         goto merr;
509                               nqual = NULL;
510                     } else if (name_cmp(cnf->name, "userNotice") == 0) {
511                               STACK_OF(CONF_VALUE) *unot;
512                               POLICYQUALINFO *qual;
513 
514                               if (*cnf->value != '@') {
515                                         X509V3error(X509V3_R_EXPECTED_A_SECTION_NAME);
516                                         X509V3_conf_err(cnf);
517                                         goto err;
518                               }
519                               unot = X509V3_get_section(ctx, cnf->value + 1);
520                               if (unot == NULL) {
521                                         X509V3error(X509V3_R_INVALID_SECTION);
522                                         X509V3_conf_err(cnf);
523                                         goto err;
524                               }
525                               qual = notice_section(ctx, unot, ia5org);
526                               X509V3_section_free(ctx, unot);
527                               if (qual == NULL)
528                                         goto err;
529 
530                               if (pol->qualifiers == NULL) {
531                                         pol->qualifiers = sk_POLICYQUALINFO_new_null();
532                                         if (pol->qualifiers == NULL)
533                                                   goto merr;
534                               }
535                               if (sk_POLICYQUALINFO_push(pol->qualifiers, qual) == 0)
536                                         goto merr;
537                     } else {
538                               X509V3error(X509V3_R_INVALID_OPTION);
539                               X509V3_conf_err(cnf);
540                               goto err;
541                     }
542           }
543           if (pol->policyid == NULL) {
544                     X509V3error(X509V3_R_NO_POLICY_IDENTIFIER);
545                     goto err;
546           }
547 
548           return pol;
549 
550 merr:
551           X509V3error(ERR_R_MALLOC_FAILURE);
552 
553 err:
554           POLICYQUALINFO_free(nqual);
555           POLICYINFO_free(pol);
556           return NULL;
557 }
558 
559 static POLICYQUALINFO *
notice_section(X509V3_CTX * ctx,STACK_OF (CONF_VALUE)* unot,int ia5org)560 notice_section(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *unot, int ia5org)
561 {
562           int i, ret;
563           CONF_VALUE *cnf;
564           USERNOTICE *not;
565           POLICYQUALINFO *qual;
566 
567           if (!(qual = POLICYQUALINFO_new()))
568                     goto merr;
569           qual->pqualid = OBJ_nid2obj(NID_id_qt_unotice);
570           if (!(not = USERNOTICE_new()))
571                     goto merr;
572           qual->d.usernotice = not;
573           for (i = 0; i < sk_CONF_VALUE_num(unot); i++) {
574                     cnf = sk_CONF_VALUE_value(unot, i);
575                     if (!strcmp(cnf->name, "explicitText")) {
576                               if (not->exptext == NULL) {
577                                         not->exptext = ASN1_VISIBLESTRING_new();
578                                         if (not->exptext == NULL)
579                                                   goto merr;
580                               }
581                               if (!ASN1_STRING_set(not->exptext, cnf->value,
582                                   strlen(cnf->value)))
583                                         goto merr;
584                     } else if (!strcmp(cnf->name, "organization")) {
585                               NOTICEREF *nref;
586                               if (!not->noticeref) {
587                                         if (!(nref = NOTICEREF_new()))
588                                                   goto merr;
589                                         not->noticeref = nref;
590                               } else
591                                         nref = not->noticeref;
592                               if (ia5org)
593                                         nref->organization->type = V_ASN1_IA5STRING;
594                               else
595                                         nref->organization->type = V_ASN1_VISIBLESTRING;
596                               if (!ASN1_STRING_set(nref->organization, cnf->value,
597                                   strlen(cnf->value)))
598                                         goto merr;
599                     } else if (!strcmp(cnf->name, "noticeNumbers")) {
600                               NOTICEREF *nref;
601                               STACK_OF(CONF_VALUE) *nos;
602                               if (!not->noticeref) {
603                                         if (!(nref = NOTICEREF_new()))
604                                                   goto merr;
605                                         not->noticeref = nref;
606                               } else
607                                         nref = not->noticeref;
608                               nos = X509V3_parse_list(cnf->value);
609                               if (!nos || !sk_CONF_VALUE_num(nos)) {
610                                         X509V3error(X509V3_R_INVALID_NUMBERS);
611                                         X509V3_conf_err(cnf);
612                                         if (nos != NULL)
613                                                   sk_CONF_VALUE_pop_free(nos,
614                                                       X509V3_conf_free);
615                                         goto err;
616                               }
617                               ret = nref_nos(nref->noticenos, nos);
618                               sk_CONF_VALUE_pop_free(nos, X509V3_conf_free);
619                               if (!ret)
620                                         goto err;
621                     } else {
622                               X509V3error(X509V3_R_INVALID_OPTION);
623                               X509V3_conf_err(cnf);
624                               goto err;
625                     }
626           }
627 
628           if (not->noticeref &&
629               (!not->noticeref->noticenos || !not->noticeref->organization)) {
630                     X509V3error(X509V3_R_NEED_ORGANIZATION_AND_NUMBERS);
631                     goto err;
632           }
633 
634           return qual;
635 
636 merr:
637           X509V3error(ERR_R_MALLOC_FAILURE);
638 
639 err:
640           POLICYQUALINFO_free(qual);
641           return NULL;
642 }
643 
644 static int
nref_nos(STACK_OF (ASN1_INTEGER)* nnums,STACK_OF (CONF_VALUE)* nos)645 nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos)
646 {
647           CONF_VALUE *cnf;
648           ASN1_INTEGER *aint;
649           int i;
650 
651           for (i = 0; i < sk_CONF_VALUE_num(nos); i++) {
652                     cnf = sk_CONF_VALUE_value(nos, i);
653                     if (!(aint = s2i_ASN1_INTEGER(NULL, cnf->name))) {
654                               X509V3error(X509V3_R_INVALID_NUMBER);
655                               goto err;
656                     }
657                     if (!sk_ASN1_INTEGER_push(nnums, aint))
658                               goto merr;
659           }
660           return 1;
661 
662 merr:
663           X509V3error(ERR_R_MALLOC_FAILURE);
664 
665 err:
666           sk_ASN1_INTEGER_pop_free(nnums, ASN1_STRING_free);
667           return 0;
668 }
669 
670 static int
i2r_certpol(X509V3_EXT_METHOD * method,STACK_OF (POLICYINFO)* pol,BIO * out,int indent)671 i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol, BIO *out,
672     int indent)
673 {
674           int i;
675           POLICYINFO *pinfo;
676 
677           /* First print out the policy OIDs */
678           for (i = 0; i < sk_POLICYINFO_num(pol); i++) {
679                     pinfo = sk_POLICYINFO_value(pol, i);
680                     BIO_printf(out, "%*sPolicy: ", indent, "");
681                     i2a_ASN1_OBJECT(out, pinfo->policyid);
682                     BIO_puts(out, "\n");
683                     if (pinfo->qualifiers)
684                               print_qualifiers(out, pinfo->qualifiers, indent + 2);
685           }
686           return 1;
687 }
688 
689 static void
print_qualifiers(BIO * out,STACK_OF (POLICYQUALINFO)* quals,int indent)690 print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals, int indent)
691 {
692           POLICYQUALINFO *qualinfo;
693           int i;
694 
695           for (i = 0; i < sk_POLICYQUALINFO_num(quals); i++) {
696                     qualinfo = sk_POLICYQUALINFO_value(quals, i);
697                     switch (OBJ_obj2nid(qualinfo->pqualid)) {
698                     case NID_id_qt_cps:
699                               BIO_printf(out, "%*sCPS: %.*s\n", indent, "",
700                                   qualinfo->d.cpsuri->length,
701                                   qualinfo->d.cpsuri->data);
702                               break;
703 
704                     case NID_id_qt_unotice:
705                               BIO_printf(out, "%*sUser Notice:\n", indent, "");
706                               print_notice(out, qualinfo->d.usernotice, indent + 2);
707                               break;
708 
709                     default:
710                               BIO_printf(out, "%*sUnknown Qualifier: ",
711                                   indent + 2, "");
712 
713                               i2a_ASN1_OBJECT(out, qualinfo->pqualid);
714                               BIO_puts(out, "\n");
715                               break;
716                     }
717           }
718 }
719 
720 static void
print_notice(BIO * out,USERNOTICE * notice,int indent)721 print_notice(BIO *out, USERNOTICE *notice, int indent)
722 {
723           int i;
724 
725           if (notice->noticeref) {
726                     NOTICEREF *ref;
727                     ref = notice->noticeref;
728                     BIO_printf(out, "%*sOrganization: %.*s\n", indent, "",
729                         ref->organization->length, ref->organization->data);
730                     BIO_printf(out, "%*sNumber%s: ", indent, "",
731                         sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : "");
732                     for (i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) {
733                               ASN1_INTEGER *num;
734                               char *tmp;
735                               num = sk_ASN1_INTEGER_value(ref->noticenos, i);
736                               if (i)
737                                         BIO_puts(out, ", ");
738                               tmp = i2s_ASN1_INTEGER(NULL, num);
739                               BIO_puts(out, tmp);
740                               free(tmp);
741                     }
742                     BIO_puts(out, "\n");
743           }
744           if (notice->exptext)
745                     BIO_printf(out, "%*sExplicit Text: %.*s\n", indent, "",
746                         notice->exptext->length, notice->exptext->data);
747 }
748 
749 void
X509_POLICY_NODE_print(BIO * out,X509_POLICY_NODE * node,int indent)750 X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent)
751 {
752           const X509_POLICY_DATA *dat = node->data;
753 
754           BIO_printf(out, "%*sPolicy: ", indent, "");
755 
756           i2a_ASN1_OBJECT(out, dat->valid_policy);
757           BIO_puts(out, "\n");
758           BIO_printf(out, "%*s%s\n", indent + 2, "",
759               node_data_critical(dat) ? "Critical" : "Non Critical");
760           if (dat->qualifier_set)
761                     print_qualifiers(out, dat->qualifier_set, indent + 2);
762           else
763                     BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, "");
764 }
765