Fixed a crash in print_notice.
[openssl.git] / crypto / x509v3 / v3_cpols.c
1 /*
2  * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include <stdio.h>
11 #include "internal/cryptlib.h"
12 #include <openssl/conf.h>
13 #include <openssl/asn1.h>
14 #include <openssl/asn1t.h>
15 #include <openssl/x509v3.h>
16
17 #include "pcy_int.h"
18 #include "ext_dat.h"
19
20 /* Certificate policies extension support: this one is a bit complex... */
21
22 static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol,
23                        BIO *out, int indent);
24 static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
25                                          X509V3_CTX *ctx, const char *value);
26 static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
27                              int indent);
28 static void print_notice(BIO *out, USERNOTICE *notice, int indent);
29 static POLICYINFO *policy_section(X509V3_CTX *ctx,
30                                   STACK_OF(CONF_VALUE) *polstrs, int ia5org);
31 static POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
32                                       STACK_OF(CONF_VALUE) *unot, int ia5org);
33 static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos);
34
35 const X509V3_EXT_METHOD v3_cpols = {
36     NID_certificate_policies, 0, ASN1_ITEM_ref(CERTIFICATEPOLICIES),
37     0, 0, 0, 0,
38     0, 0,
39     0, 0,
40     (X509V3_EXT_I2R)i2r_certpol,
41     (X509V3_EXT_R2I)r2i_certpol,
42     NULL
43 };
44
45 ASN1_ITEM_TEMPLATE(CERTIFICATEPOLICIES) =
46         ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CERTIFICATEPOLICIES, POLICYINFO)
47 ASN1_ITEM_TEMPLATE_END(CERTIFICATEPOLICIES)
48
49 IMPLEMENT_ASN1_FUNCTIONS(CERTIFICATEPOLICIES)
50
51 ASN1_SEQUENCE(POLICYINFO) = {
52         ASN1_SIMPLE(POLICYINFO, policyid, ASN1_OBJECT),
53         ASN1_SEQUENCE_OF_OPT(POLICYINFO, qualifiers, POLICYQUALINFO)
54 } ASN1_SEQUENCE_END(POLICYINFO)
55
56 IMPLEMENT_ASN1_FUNCTIONS(POLICYINFO)
57
58 ASN1_ADB_TEMPLATE(policydefault) = ASN1_SIMPLE(POLICYQUALINFO, d.other, ASN1_ANY);
59
60 ASN1_ADB(POLICYQUALINFO) = {
61         ADB_ENTRY(NID_id_qt_cps, ASN1_SIMPLE(POLICYQUALINFO, d.cpsuri, ASN1_IA5STRING)),
62         ADB_ENTRY(NID_id_qt_unotice, ASN1_SIMPLE(POLICYQUALINFO, d.usernotice, USERNOTICE))
63 } ASN1_ADB_END(POLICYQUALINFO, 0, pqualid, 0, &policydefault_tt, NULL);
64
65 ASN1_SEQUENCE(POLICYQUALINFO) = {
66         ASN1_SIMPLE(POLICYQUALINFO, pqualid, ASN1_OBJECT),
67         ASN1_ADB_OBJECT(POLICYQUALINFO)
68 } ASN1_SEQUENCE_END(POLICYQUALINFO)
69
70 IMPLEMENT_ASN1_FUNCTIONS(POLICYQUALINFO)
71
72 ASN1_SEQUENCE(USERNOTICE) = {
73         ASN1_OPT(USERNOTICE, noticeref, NOTICEREF),
74         ASN1_OPT(USERNOTICE, exptext, DISPLAYTEXT)
75 } ASN1_SEQUENCE_END(USERNOTICE)
76
77 IMPLEMENT_ASN1_FUNCTIONS(USERNOTICE)
78
79 ASN1_SEQUENCE(NOTICEREF) = {
80         ASN1_SIMPLE(NOTICEREF, organization, DISPLAYTEXT),
81         ASN1_SEQUENCE_OF(NOTICEREF, noticenos, ASN1_INTEGER)
82 } ASN1_SEQUENCE_END(NOTICEREF)
83
84 IMPLEMENT_ASN1_FUNCTIONS(NOTICEREF)
85
86 static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
87                                          X509V3_CTX *ctx, const char *value)
88 {
89     STACK_OF(POLICYINFO) *pols = NULL;
90     char *pstr;
91     POLICYINFO *pol;
92     ASN1_OBJECT *pobj;
93     STACK_OF(CONF_VALUE) *vals;
94     CONF_VALUE *cnf;
95     int i, ia5org;
96     pols = sk_POLICYINFO_new_null();
97     if (pols == NULL) {
98         X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE);
99         return NULL;
100     }
101     vals = X509V3_parse_list(value);
102     if (vals == NULL) {
103         X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_X509V3_LIB);
104         goto err;
105     }
106     ia5org = 0;
107     for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
108         cnf = sk_CONF_VALUE_value(vals, i);
109         if (cnf->value || !cnf->name) {
110             X509V3err(X509V3_F_R2I_CERTPOL,
111                       X509V3_R_INVALID_POLICY_IDENTIFIER);
112             X509V3_conf_err(cnf);
113             goto err;
114         }
115         pstr = cnf->name;
116         if (strcmp(pstr, "ia5org") == 0) {
117             ia5org = 1;
118             continue;
119         } else if (*pstr == '@') {
120             STACK_OF(CONF_VALUE) *polsect;
121             polsect = X509V3_get_section(ctx, pstr + 1);
122             if (!polsect) {
123                 X509V3err(X509V3_F_R2I_CERTPOL, X509V3_R_INVALID_SECTION);
124
125                 X509V3_conf_err(cnf);
126                 goto err;
127             }
128             pol = policy_section(ctx, polsect, ia5org);
129             X509V3_section_free(ctx, polsect);
130             if (pol == NULL)
131                 goto err;
132         } else {
133             if ((pobj = OBJ_txt2obj(cnf->name, 0)) == NULL) {
134                 X509V3err(X509V3_F_R2I_CERTPOL,
135                           X509V3_R_INVALID_OBJECT_IDENTIFIER);
136                 X509V3_conf_err(cnf);
137                 goto err;
138             }
139             pol = POLICYINFO_new();
140             if (pol == NULL) {
141                 X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE);
142                 ASN1_OBJECT_free(pobj);
143                 goto err;
144             }
145             pol->policyid = pobj;
146         }
147         if (!sk_POLICYINFO_push(pols, pol)) {
148             POLICYINFO_free(pol);
149             X509V3err(X509V3_F_R2I_CERTPOL, ERR_R_MALLOC_FAILURE);
150             goto err;
151         }
152     }
153     sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
154     return pols;
155  err:
156     sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
157     sk_POLICYINFO_pop_free(pols, POLICYINFO_free);
158     return NULL;
159 }
160
161 static POLICYINFO *policy_section(X509V3_CTX *ctx,
162                                   STACK_OF(CONF_VALUE) *polstrs, int ia5org)
163 {
164     int i;
165     CONF_VALUE *cnf;
166     POLICYINFO *pol;
167     POLICYQUALINFO *qual;
168
169     if ((pol = POLICYINFO_new()) == NULL)
170         goto merr;
171     for (i = 0; i < sk_CONF_VALUE_num(polstrs); i++) {
172         cnf = sk_CONF_VALUE_value(polstrs, i);
173         if (strcmp(cnf->name, "policyIdentifier") == 0) {
174             ASN1_OBJECT *pobj;
175             if ((pobj = OBJ_txt2obj(cnf->value, 0)) == NULL) {
176                 X509V3err(X509V3_F_POLICY_SECTION,
177                           X509V3_R_INVALID_OBJECT_IDENTIFIER);
178                 X509V3_conf_err(cnf);
179                 goto err;
180             }
181             pol->policyid = pobj;
182
183         } else if (!name_cmp(cnf->name, "CPS")) {
184             if (pol->qualifiers == NULL)
185                 pol->qualifiers = sk_POLICYQUALINFO_new_null();
186             if ((qual = POLICYQUALINFO_new()) == NULL)
187                 goto merr;
188             if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
189                 goto merr;
190             if ((qual->pqualid = OBJ_nid2obj(NID_id_qt_cps)) == NULL) {
191                 X509V3err(X509V3_F_POLICY_SECTION, ERR_R_INTERNAL_ERROR);
192                 goto err;
193             }
194             if ((qual->d.cpsuri = ASN1_IA5STRING_new()) == NULL)
195                 goto merr;
196             if (!ASN1_STRING_set(qual->d.cpsuri, cnf->value,
197                                  strlen(cnf->value)))
198                 goto merr;
199         } else if (!name_cmp(cnf->name, "userNotice")) {
200             STACK_OF(CONF_VALUE) *unot;
201             if (*cnf->value != '@') {
202                 X509V3err(X509V3_F_POLICY_SECTION,
203                           X509V3_R_EXPECTED_A_SECTION_NAME);
204                 X509V3_conf_err(cnf);
205                 goto err;
206             }
207             unot = X509V3_get_section(ctx, cnf->value + 1);
208             if (!unot) {
209                 X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_INVALID_SECTION);
210
211                 X509V3_conf_err(cnf);
212                 goto err;
213             }
214             qual = notice_section(ctx, unot, ia5org);
215             X509V3_section_free(ctx, unot);
216             if (!qual)
217                 goto err;
218             if (!pol->qualifiers)
219                 pol->qualifiers = sk_POLICYQUALINFO_new_null();
220             if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
221                 goto merr;
222         } else {
223             X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_INVALID_OPTION);
224
225             X509V3_conf_err(cnf);
226             goto err;
227         }
228     }
229     if (!pol->policyid) {
230         X509V3err(X509V3_F_POLICY_SECTION, X509V3_R_NO_POLICY_IDENTIFIER);
231         goto err;
232     }
233
234     return pol;
235
236  merr:
237     X509V3err(X509V3_F_POLICY_SECTION, ERR_R_MALLOC_FAILURE);
238
239  err:
240     POLICYINFO_free(pol);
241     return NULL;
242
243 }
244
245 static POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
246                                       STACK_OF(CONF_VALUE) *unot, int ia5org)
247 {
248     int i, ret;
249     CONF_VALUE *cnf;
250     USERNOTICE *not;
251     POLICYQUALINFO *qual;
252
253     if ((qual = POLICYQUALINFO_new()) == NULL)
254         goto merr;
255     if ((qual->pqualid = OBJ_nid2obj(NID_id_qt_unotice)) == NULL) {
256         X509V3err(X509V3_F_NOTICE_SECTION, ERR_R_INTERNAL_ERROR);
257         goto err;
258     }
259     if ((not = USERNOTICE_new()) == NULL)
260         goto merr;
261     qual->d.usernotice = not;
262     for (i = 0; i < sk_CONF_VALUE_num(unot); i++) {
263         cnf = sk_CONF_VALUE_value(unot, i);
264         if (strcmp(cnf->name, "explicitText") == 0) {
265             if ((not->exptext = ASN1_VISIBLESTRING_new()) == NULL)
266                 goto merr;
267             if (!ASN1_STRING_set(not->exptext, cnf->value,
268                                  strlen(cnf->value)))
269                 goto merr;
270         } else if (strcmp(cnf->name, "organization") == 0) {
271             NOTICEREF *nref;
272             if (!not->noticeref) {
273                 if ((nref = NOTICEREF_new()) == NULL)
274                     goto merr;
275                 not->noticeref = nref;
276             } else
277                 nref = not->noticeref;
278             if (ia5org)
279                 nref->organization->type = V_ASN1_IA5STRING;
280             else
281                 nref->organization->type = V_ASN1_VISIBLESTRING;
282             if (!ASN1_STRING_set(nref->organization, cnf->value,
283                                  strlen(cnf->value)))
284                 goto merr;
285         } else if (strcmp(cnf->name, "noticeNumbers") == 0) {
286             NOTICEREF *nref;
287             STACK_OF(CONF_VALUE) *nos;
288             if (!not->noticeref) {
289                 if ((nref = NOTICEREF_new()) == NULL)
290                     goto merr;
291                 not->noticeref = nref;
292             } else
293                 nref = not->noticeref;
294             nos = X509V3_parse_list(cnf->value);
295             if (!nos || !sk_CONF_VALUE_num(nos)) {
296                 X509V3err(X509V3_F_NOTICE_SECTION, X509V3_R_INVALID_NUMBERS);
297                 X509V3_conf_err(cnf);
298                 sk_CONF_VALUE_pop_free(nos, X509V3_conf_free);
299                 goto err;
300             }
301             ret = nref_nos(nref->noticenos, nos);
302             sk_CONF_VALUE_pop_free(nos, X509V3_conf_free);
303             if (!ret)
304                 goto err;
305         } else {
306             X509V3err(X509V3_F_NOTICE_SECTION, X509V3_R_INVALID_OPTION);
307             X509V3_conf_err(cnf);
308             goto err;
309         }
310     }
311
312     if (not->noticeref &&
313         (!not->noticeref->noticenos || !not->noticeref->organization)) {
314         X509V3err(X509V3_F_NOTICE_SECTION,
315                   X509V3_R_NEED_ORGANIZATION_AND_NUMBERS);
316         goto err;
317     }
318
319     return qual;
320
321  merr:
322     X509V3err(X509V3_F_NOTICE_SECTION, ERR_R_MALLOC_FAILURE);
323
324  err:
325     POLICYQUALINFO_free(qual);
326     return NULL;
327 }
328
329 static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos)
330 {
331     CONF_VALUE *cnf;
332     ASN1_INTEGER *aint;
333
334     int i;
335
336     for (i = 0; i < sk_CONF_VALUE_num(nos); i++) {
337         cnf = sk_CONF_VALUE_value(nos, i);
338         if ((aint = s2i_ASN1_INTEGER(NULL, cnf->name)) == NULL) {
339             X509V3err(X509V3_F_NREF_NOS, X509V3_R_INVALID_NUMBER);
340             goto err;
341         }
342         if (!sk_ASN1_INTEGER_push(nnums, aint))
343             goto merr;
344     }
345     return 1;
346
347  merr:
348     ASN1_INTEGER_free(aint);
349     X509V3err(X509V3_F_NREF_NOS, ERR_R_MALLOC_FAILURE);
350
351  err:
352     return 0;
353 }
354
355 static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol,
356                        BIO *out, int indent)
357 {
358     int i;
359     POLICYINFO *pinfo;
360     /* First print out the policy OIDs */
361     for (i = 0; i < sk_POLICYINFO_num(pol); i++) {
362         pinfo = sk_POLICYINFO_value(pol, i);
363         BIO_printf(out, "%*sPolicy: ", indent, "");
364         i2a_ASN1_OBJECT(out, pinfo->policyid);
365         BIO_puts(out, "\n");
366         if (pinfo->qualifiers)
367             print_qualifiers(out, pinfo->qualifiers, indent + 2);
368     }
369     return 1;
370 }
371
372 static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
373                              int indent)
374 {
375     POLICYQUALINFO *qualinfo;
376     int i;
377     for (i = 0; i < sk_POLICYQUALINFO_num(quals); i++) {
378         qualinfo = sk_POLICYQUALINFO_value(quals, i);
379         switch (OBJ_obj2nid(qualinfo->pqualid)) {
380         case NID_id_qt_cps:
381             BIO_printf(out, "%*sCPS: %s\n", indent, "",
382                        qualinfo->d.cpsuri->data);
383             break;
384
385         case NID_id_qt_unotice:
386             BIO_printf(out, "%*sUser Notice:\n", indent, "");
387             print_notice(out, qualinfo->d.usernotice, indent + 2);
388             break;
389
390         default:
391             BIO_printf(out, "%*sUnknown Qualifier: ", indent + 2, "");
392
393             i2a_ASN1_OBJECT(out, qualinfo->pqualid);
394             BIO_puts(out, "\n");
395             break;
396         }
397     }
398 }
399
400 static void print_notice(BIO *out, USERNOTICE *notice, int indent)
401 {
402     int i;
403     if (notice->noticeref) {
404         NOTICEREF *ref;
405         ref = notice->noticeref;
406         BIO_printf(out, "%*sOrganization: %s\n", indent, "",
407                    ref->organization->data);
408         BIO_printf(out, "%*sNumber%s: ", indent, "",
409                    sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : "");
410         for (i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) {
411             ASN1_INTEGER *num;
412             char *tmp;
413             num = sk_ASN1_INTEGER_value(ref->noticenos, i);
414             if (i)
415                 BIO_puts(out, ", ");
416             if (num == NULL)
417                 BIO_puts(out, "(null)");
418             else {
419                 tmp = i2s_ASN1_INTEGER(NULL, num);
420                 if (tmp == NULL)
421                     return;
422                 BIO_puts(out, tmp);
423                 OPENSSL_free(tmp);
424             }
425         }
426         BIO_puts(out, "\n");
427     }
428     if (notice->exptext)
429         BIO_printf(out, "%*sExplicit Text: %s\n", indent, "",
430                    notice->exptext->data);
431 }
432
433 void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent)
434 {
435     const X509_POLICY_DATA *dat = node->data;
436
437     BIO_printf(out, "%*sPolicy: ", indent, "");
438
439     i2a_ASN1_OBJECT(out, dat->valid_policy);
440     BIO_puts(out, "\n");
441     BIO_printf(out, "%*s%s\n", indent + 2, "",
442                node_data_critical(dat) ? "Critical" : "Non Critical");
443     if (dat->qualifier_set)
444         print_qualifiers(out, dat->qualifier_set, indent + 2);
445     else
446         BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, "");
447 }