1 // Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <stdio.h>
16 #include <string.h>
17
18 #include <openssl/asn1.h>
19 #include <openssl/conf.h>
20 #include <openssl/err.h>
21 #include <openssl/mem.h>
22 #include <openssl/obj.h>
23 #include <openssl/x509.h>
24
25 #include "internal.h"
26
27
28 static void *v2i_subject_alt(const X509V3_EXT_METHOD *method,
29 const X509V3_CTX *ctx,
30 const STACK_OF(CONF_VALUE) *nval);
31 static void *v2i_issuer_alt(const X509V3_EXT_METHOD *method,
32 const X509V3_CTX *ctx,
33 const STACK_OF(CONF_VALUE) *nval);
34 static int copy_email(const X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p);
35 static int copy_issuer(const X509V3_CTX *ctx, GENERAL_NAMES *gens);
36 static int do_othername(GENERAL_NAME *gen, const char *value,
37 const X509V3_CTX *ctx);
38 static int do_dirname(GENERAL_NAME *gen, const char *value,
39 const X509V3_CTX *ctx);
40
STACK_OF(CONF_VALUE)41 static STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES_cb(
42 const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *ret) {
43 return i2v_GENERAL_NAMES(method, reinterpret_cast<GENERAL_NAMES *>(ext), ret);
44 }
45
46 const X509V3_EXT_METHOD v3_subject_alt_name = {
47 NID_subject_alt_name,
48 0,
49 ASN1_ITEM_ref(GENERAL_NAMES),
50 0,
51 0,
52 0,
53 0,
54 0,
55 0,
56 i2v_GENERAL_NAMES_cb,
57 v2i_subject_alt,
58 nullptr,
59 nullptr,
60 nullptr,
61 };
62
63 const X509V3_EXT_METHOD v3_issuer_alt_name = {
64 NID_issuer_alt_name,
65 0,
66 ASN1_ITEM_ref(GENERAL_NAMES),
67 0,
68 0,
69 0,
70 0,
71 0,
72 0,
73 i2v_GENERAL_NAMES_cb,
74 v2i_issuer_alt,
75 nullptr,
76 nullptr,
77 nullptr,
78 };
79
80 const X509V3_EXT_METHOD v3_certificate_issuer = {
81 NID_certificate_issuer,
82 0,
83 ASN1_ITEM_ref(GENERAL_NAMES),
84 0,
85 0,
86 0,
87 0,
88 0,
89 0,
90 i2v_GENERAL_NAMES_cb,
91 NULL,
92 NULL,
93 NULL,
94 NULL,
95 };
96
STACK_OF(CONF_VALUE)97 STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
98 const GENERAL_NAMES *gens,
99 STACK_OF(CONF_VALUE) *ret) {
100 int ret_was_null = ret == NULL;
101 for (size_t i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
102 const GENERAL_NAME *gen = sk_GENERAL_NAME_value(gens, i);
103 STACK_OF(CONF_VALUE) *tmp = i2v_GENERAL_NAME(method, gen, ret);
104 if (tmp == NULL) {
105 if (ret_was_null) {
106 sk_CONF_VALUE_pop_free(ret, X509V3_conf_free);
107 }
108 return NULL;
109 }
110 ret = tmp;
111 }
112 if (!ret) {
113 return sk_CONF_VALUE_new_null();
114 }
115 return ret;
116 }
117
STACK_OF(CONF_VALUE)118 STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(const X509V3_EXT_METHOD *method,
119 const GENERAL_NAME *gen,
120 STACK_OF(CONF_VALUE) *ret) {
121 // Note the error-handling for this function relies on there being at most
122 // one |X509V3_add_value| call. If there were two and the second failed, we
123 // would need to sometimes free the first call's result.
124 unsigned char *p;
125 char oline[256], htmp[5];
126 int i;
127 switch (gen->type) {
128 case GEN_OTHERNAME:
129 if (!X509V3_add_value("othername", "<unsupported>", &ret)) {
130 return NULL;
131 }
132 break;
133
134 case GEN_X400:
135 if (!X509V3_add_value("X400Name", "<unsupported>", &ret)) {
136 return NULL;
137 }
138 break;
139
140 case GEN_EDIPARTY:
141 if (!X509V3_add_value("EdiPartyName", "<unsupported>", &ret)) {
142 return NULL;
143 }
144 break;
145
146 case GEN_EMAIL:
147 if (!x509V3_add_value_asn1_string("email", gen->d.ia5, &ret)) {
148 return NULL;
149 }
150 break;
151
152 case GEN_DNS:
153 if (!x509V3_add_value_asn1_string("DNS", gen->d.ia5, &ret)) {
154 return NULL;
155 }
156 break;
157
158 case GEN_URI:
159 if (!x509V3_add_value_asn1_string("URI", gen->d.ia5, &ret)) {
160 return NULL;
161 }
162 break;
163
164 case GEN_DIRNAME:
165 if (X509_NAME_oneline(gen->d.dirn, oline, 256) == NULL ||
166 !X509V3_add_value("DirName", oline, &ret)) {
167 return NULL;
168 }
169 break;
170
171 case GEN_IPADD:
172 p = gen->d.ip->data;
173 if (gen->d.ip->length == 4) {
174 snprintf(oline, sizeof(oline), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
175 } else if (gen->d.ip->length == 16) {
176 oline[0] = 0;
177 for (i = 0; i < 8; i++) {
178 uint16_t v = ((uint16_t)p[0] << 8) | p[1];
179 snprintf(htmp, sizeof(htmp), "%X", v);
180 p += 2;
181 OPENSSL_strlcat(oline, htmp, sizeof(oline));
182 if (i != 7) {
183 OPENSSL_strlcat(oline, ":", sizeof(oline));
184 }
185 }
186 } else {
187 if (!X509V3_add_value("IP Address", "<invalid>", &ret)) {
188 return NULL;
189 }
190 break;
191 }
192 if (!X509V3_add_value("IP Address", oline, &ret)) {
193 return NULL;
194 }
195 break;
196
197 case GEN_RID:
198 i2t_ASN1_OBJECT(oline, 256, gen->d.rid);
199 if (!X509V3_add_value("Registered ID", oline, &ret)) {
200 return NULL;
201 }
202 break;
203 }
204 return ret;
205 }
206
GENERAL_NAME_print(BIO * out,const GENERAL_NAME * gen)207 int GENERAL_NAME_print(BIO *out, const GENERAL_NAME *gen) {
208 switch (gen->type) {
209 case GEN_OTHERNAME:
210 BIO_printf(out, "othername:<unsupported>");
211 break;
212
213 case GEN_X400:
214 BIO_printf(out, "X400Name:<unsupported>");
215 break;
216
217 case GEN_EDIPARTY:
218 // Maybe fix this: it is supported now
219 BIO_printf(out, "EdiPartyName:<unsupported>");
220 break;
221
222 case GEN_EMAIL:
223 BIO_printf(out, "email:");
224 ASN1_STRING_print(out, gen->d.ia5);
225 break;
226
227 case GEN_DNS:
228 BIO_printf(out, "DNS:");
229 ASN1_STRING_print(out, gen->d.ia5);
230 break;
231
232 case GEN_URI:
233 BIO_printf(out, "URI:");
234 ASN1_STRING_print(out, gen->d.ia5);
235 break;
236
237 case GEN_DIRNAME:
238 BIO_printf(out, "DirName: ");
239 X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE);
240 break;
241
242 case GEN_IPADD: {
243 const unsigned char *p = gen->d.ip->data;
244 if (gen->d.ip->length == 4) {
245 BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
246 } else if (gen->d.ip->length == 16) {
247 BIO_printf(out, "IP Address");
248 for (int i = 0; i < 8; i++) {
249 uint16_t v = ((uint16_t)p[0] << 8) | p[1];
250 BIO_printf(out, ":%X", v);
251 p += 2;
252 }
253 BIO_puts(out, "\n");
254 } else {
255 BIO_printf(out, "IP Address:<invalid>");
256 break;
257 }
258 break;
259 }
260
261 case GEN_RID:
262 BIO_printf(out, "Registered ID");
263 i2a_ASN1_OBJECT(out, gen->d.rid);
264 break;
265 }
266 return 1;
267 }
268
v2i_issuer_alt(const X509V3_EXT_METHOD * method,const X509V3_CTX * ctx,const STACK_OF (CONF_VALUE)* nval)269 static void *v2i_issuer_alt(const X509V3_EXT_METHOD *method,
270 const X509V3_CTX *ctx,
271 const STACK_OF(CONF_VALUE) *nval) {
272 GENERAL_NAMES *gens = sk_GENERAL_NAME_new_null();
273 if (gens == NULL) {
274 return NULL;
275 }
276 for (size_t i = 0; i < sk_CONF_VALUE_num(nval); i++) {
277 const CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i);
278 if (x509v3_conf_name_matches(cnf->name, "issuer") && cnf->value &&
279 !strcmp(cnf->value, "copy")) {
280 if (!copy_issuer(ctx, gens)) {
281 goto err;
282 }
283 } else {
284 GENERAL_NAME *gen = v2i_GENERAL_NAME(method, ctx, cnf);
285 if (gen == NULL || !sk_GENERAL_NAME_push(gens, gen)) {
286 GENERAL_NAME_free(gen);
287 goto err;
288 }
289 }
290 }
291 return gens;
292 err:
293 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
294 return NULL;
295 }
296
297 // Append subject altname of issuer to issuer alt name of subject
298
copy_issuer(const X509V3_CTX * ctx,GENERAL_NAMES * gens)299 static int copy_issuer(const X509V3_CTX *ctx, GENERAL_NAMES *gens) {
300 if (ctx && (ctx->flags == X509V3_CTX_TEST)) {
301 return 1;
302 }
303 if (!ctx || !ctx->issuer_cert) {
304 OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_ISSUER_DETAILS);
305 return 0;
306 }
307 int i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
308 if (i < 0) {
309 return 1;
310 }
311
312 int ret = 0;
313 GENERAL_NAMES *ialt = NULL;
314 X509_EXTENSION *ext;
315 if (!(ext = X509_get_ext(ctx->issuer_cert, i)) ||
316 !(ialt = reinterpret_cast<GENERAL_NAMES *>(X509V3_EXT_d2i(ext)))) {
317 OPENSSL_PUT_ERROR(X509V3, X509V3_R_ISSUER_DECODE_ERROR);
318 goto err;
319 }
320
321 for (size_t j = 0; j < sk_GENERAL_NAME_num(ialt); j++) {
322 GENERAL_NAME *gen = sk_GENERAL_NAME_value(ialt, j);
323 if (!sk_GENERAL_NAME_push(gens, gen)) {
324 goto err;
325 }
326 // Ownership of |gen| has moved from |ialt| to |gens|.
327 sk_GENERAL_NAME_set(ialt, j, NULL);
328 }
329
330 ret = 1;
331
332 err:
333 GENERAL_NAMES_free(ialt);
334 return ret;
335 }
336
v2i_subject_alt(const X509V3_EXT_METHOD * method,const X509V3_CTX * ctx,const STACK_OF (CONF_VALUE)* nval)337 static void *v2i_subject_alt(const X509V3_EXT_METHOD *method,
338 const X509V3_CTX *ctx,
339 const STACK_OF(CONF_VALUE) *nval) {
340 GENERAL_NAMES *gens = sk_GENERAL_NAME_new_null();
341 if (gens == NULL) {
342 return NULL;
343 }
344 for (size_t i = 0; i < sk_CONF_VALUE_num(nval); i++) {
345 const CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i);
346 if (x509v3_conf_name_matches(cnf->name, "email") && cnf->value &&
347 !strcmp(cnf->value, "copy")) {
348 if (!copy_email(ctx, gens, 0)) {
349 goto err;
350 }
351 } else if (x509v3_conf_name_matches(cnf->name, "email") && cnf->value &&
352 !strcmp(cnf->value, "move")) {
353 if (!copy_email(ctx, gens, 1)) {
354 goto err;
355 }
356 } else {
357 GENERAL_NAME *gen = v2i_GENERAL_NAME(method, ctx, cnf);
358 if (gen == NULL || !sk_GENERAL_NAME_push(gens, gen)) {
359 GENERAL_NAME_free(gen);
360 goto err;
361 }
362 }
363 }
364 return gens;
365 err:
366 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
367 return NULL;
368 }
369
370 // Copy any email addresses in a certificate or request to GENERAL_NAMES
371
copy_email(const X509V3_CTX * ctx,GENERAL_NAMES * gens,int move_p)372 static int copy_email(const X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p) {
373 X509_NAME *nm;
374 ASN1_IA5STRING *email = NULL;
375 X509_NAME_ENTRY *ne;
376 GENERAL_NAME *gen = NULL;
377 int i;
378 if (ctx != NULL && ctx->flags == X509V3_CTX_TEST) {
379 return 1;
380 }
381 if (!ctx || (!ctx->subject_cert && !ctx->subject_req)) {
382 OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_SUBJECT_DETAILS);
383 goto err;
384 }
385 // Find the subject name
386 if (ctx->subject_cert) {
387 nm = X509_get_subject_name(ctx->subject_cert);
388 } else {
389 nm = X509_REQ_get_subject_name(ctx->subject_req);
390 }
391
392 // Now add any email address(es) to STACK
393 i = -1;
394 while ((i = X509_NAME_get_index_by_NID(nm, NID_pkcs9_emailAddress, i)) >= 0) {
395 ne = X509_NAME_get_entry(nm, i);
396 email = ASN1_STRING_dup(X509_NAME_ENTRY_get_data(ne));
397 if (move_p) {
398 X509_NAME_delete_entry(nm, i);
399 X509_NAME_ENTRY_free(ne);
400 i--;
401 }
402 if (!email || !(gen = GENERAL_NAME_new())) {
403 goto err;
404 }
405 gen->d.ia5 = email;
406 email = NULL;
407 gen->type = GEN_EMAIL;
408 if (!sk_GENERAL_NAME_push(gens, gen)) {
409 goto err;
410 }
411 gen = NULL;
412 }
413
414 return 1;
415
416 err:
417 GENERAL_NAME_free(gen);
418 ASN1_IA5STRING_free(email);
419 return 0;
420 }
421
v2i_GENERAL_NAMES(const X509V3_EXT_METHOD * method,const X509V3_CTX * ctx,const STACK_OF (CONF_VALUE)* nval)422 GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
423 const X509V3_CTX *ctx,
424 const STACK_OF(CONF_VALUE) *nval) {
425 GENERAL_NAMES *gens = sk_GENERAL_NAME_new_null();
426 if (gens == NULL) {
427 return NULL;
428 }
429 for (size_t i = 0; i < sk_CONF_VALUE_num(nval); i++) {
430 const CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i);
431 GENERAL_NAME *gen = v2i_GENERAL_NAME(method, ctx, cnf);
432 if (gen == NULL || !sk_GENERAL_NAME_push(gens, gen)) {
433 GENERAL_NAME_free(gen);
434 goto err;
435 }
436 }
437 return gens;
438 err:
439 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
440 return NULL;
441 }
442
v2i_GENERAL_NAME(const X509V3_EXT_METHOD * method,const X509V3_CTX * ctx,const CONF_VALUE * cnf)443 GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method,
444 const X509V3_CTX *ctx, const CONF_VALUE *cnf) {
445 return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
446 }
447
a2i_GENERAL_NAME(GENERAL_NAME * out,const X509V3_EXT_METHOD * method,const X509V3_CTX * ctx,int gen_type,const char * value,int is_nc)448 static GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out,
449 const X509V3_EXT_METHOD *method,
450 const X509V3_CTX *ctx, int gen_type,
451 const char *value, int is_nc) {
452 if (!value) {
453 OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE);
454 return NULL;
455 }
456
457 GENERAL_NAME *gen = NULL;
458 if (out) {
459 gen = out;
460 } else {
461 gen = GENERAL_NAME_new();
462 if (gen == NULL) {
463 return NULL;
464 }
465 }
466
467 switch (gen_type) {
468 case GEN_URI:
469 case GEN_EMAIL:
470 case GEN_DNS: {
471 ASN1_IA5STRING *str = ASN1_IA5STRING_new();
472 if (str == NULL || !ASN1_STRING_set(str, value, strlen(value))) {
473 ASN1_STRING_free(str);
474 goto err;
475 }
476 gen->type = gen_type;
477 gen->d.ia5 = str;
478 break;
479 }
480
481 case GEN_RID: {
482 ASN1_OBJECT *obj;
483 if (!(obj = OBJ_txt2obj(value, 0))) {
484 OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT);
485 ERR_add_error_data(2, "value=", value);
486 goto err;
487 }
488 gen->type = GEN_RID;
489 gen->d.rid = obj;
490 break;
491 }
492
493 case GEN_IPADD:
494 gen->type = GEN_IPADD;
495 if (is_nc) {
496 gen->d.ip = a2i_IPADDRESS_NC(value);
497 } else {
498 gen->d.ip = a2i_IPADDRESS(value);
499 }
500 if (gen->d.ip == NULL) {
501 OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_IP_ADDRESS);
502 ERR_add_error_data(2, "value=", value);
503 goto err;
504 }
505 break;
506
507 case GEN_DIRNAME:
508 if (!do_dirname(gen, value, ctx)) {
509 OPENSSL_PUT_ERROR(X509V3, X509V3_R_DIRNAME_ERROR);
510 goto err;
511 }
512 break;
513
514 case GEN_OTHERNAME:
515 if (!do_othername(gen, value, ctx)) {
516 OPENSSL_PUT_ERROR(X509V3, X509V3_R_OTHERNAME_ERROR);
517 goto err;
518 }
519 break;
520 default:
521 OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_TYPE);
522 goto err;
523 }
524
525 return gen;
526
527 err:
528 if (!out) {
529 GENERAL_NAME_free(gen);
530 }
531 return NULL;
532 }
533
v2i_GENERAL_NAME_ex(GENERAL_NAME * out,const X509V3_EXT_METHOD * method,const X509V3_CTX * ctx,const CONF_VALUE * cnf,int is_nc)534 GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
535 const X509V3_EXT_METHOD *method,
536 const X509V3_CTX *ctx, const CONF_VALUE *cnf,
537 int is_nc) {
538 const char *name = cnf->name;
539 const char *value = cnf->value;
540 if (!value) {
541 OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE);
542 return NULL;
543 }
544
545 int type;
546 if (x509v3_conf_name_matches(name, "email")) {
547 type = GEN_EMAIL;
548 } else if (x509v3_conf_name_matches(name, "URI")) {
549 type = GEN_URI;
550 } else if (x509v3_conf_name_matches(name, "DNS")) {
551 type = GEN_DNS;
552 } else if (x509v3_conf_name_matches(name, "RID")) {
553 type = GEN_RID;
554 } else if (x509v3_conf_name_matches(name, "IP")) {
555 type = GEN_IPADD;
556 } else if (x509v3_conf_name_matches(name, "dirName")) {
557 type = GEN_DIRNAME;
558 } else if (x509v3_conf_name_matches(name, "otherName")) {
559 type = GEN_OTHERNAME;
560 } else {
561 OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_OPTION);
562 ERR_add_error_data(2, "name=", name);
563 return NULL;
564 }
565
566 return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc);
567 }
568
do_othername(GENERAL_NAME * gen,const char * value,const X509V3_CTX * ctx)569 static int do_othername(GENERAL_NAME *gen, const char *value,
570 const X509V3_CTX *ctx) {
571 const char *semicolon = strchr(value, ';');
572 if (semicolon == NULL) {
573 return 0;
574 }
575
576 OTHERNAME *name = OTHERNAME_new();
577 if (name == NULL) {
578 return 0;
579 }
580
581 char *objtmp = OPENSSL_strndup(value, semicolon - value);
582 if (objtmp == NULL) {
583 goto err;
584 }
585 ASN1_OBJECT_free(name->type_id);
586 name->type_id = OBJ_txt2obj(objtmp, /*dont_search_names=*/0);
587 OPENSSL_free(objtmp);
588 if (name->type_id == NULL) {
589 goto err;
590 }
591
592 ASN1_TYPE_free(name->value);
593 name->value = ASN1_generate_v3(semicolon + 1, ctx);
594 if (name->value == NULL) {
595 goto err;
596 }
597
598 gen->type = GEN_OTHERNAME;
599 gen->d.otherName = name;
600 return 1;
601
602 err:
603 OTHERNAME_free(name);
604 return 0;
605 }
606
do_dirname(GENERAL_NAME * gen,const char * value,const X509V3_CTX * ctx)607 static int do_dirname(GENERAL_NAME *gen, const char *value,
608 const X509V3_CTX *ctx) {
609 int ret = 0;
610 const STACK_OF(CONF_VALUE) *sk = X509V3_get_section(ctx, value);
611 X509_NAME *nm = X509_NAME_new();
612 if (nm == NULL) {
613 goto err;
614 }
615 if (sk == NULL) {
616 OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND);
617 ERR_add_error_data(2, "section=", value);
618 goto err;
619 }
620 // FIXME: should allow other character types...
621 if (!X509V3_NAME_from_section(nm, sk, MBSTRING_ASC)) {
622 goto err;
623 }
624 gen->type = GEN_DIRNAME;
625 gen->d.dirn = nm;
626 ret = 1;
627
628 err:
629 if (!ret) {
630 X509_NAME_free(nm);
631 }
632 return ret;
633 }
634