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