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