]>
Commit | Line | Data |
---|---|---|
0f113f3e | 1 | /* |
4333b89f | 2 | * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. |
142fcca8 | 3 | * |
4286ca47 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
d2e9e320 RS |
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 | |
142fcca8 DSH |
8 | */ |
9 | ||
10 | #include <stdio.h> | |
b39fc560 | 11 | #include "internal/cryptlib.h" |
ad6ac174 | 12 | #include "crypto/x509.h" |
ec577822 BM |
13 | #include <openssl/conf.h> |
14 | #include <openssl/x509v3.h> | |
bb4f3911 | 15 | #include <openssl/bio.h> |
df2ee0e2 | 16 | #include "ext_dat.h" |
142fcca8 | 17 | |
0f113f3e MC |
18 | static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, |
19 | X509V3_CTX *ctx, | |
20 | STACK_OF(CONF_VALUE) *nval); | |
21 | static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, | |
22 | X509V3_CTX *ctx, | |
23 | STACK_OF(CONF_VALUE) *nval); | |
c9fd77e9 | 24 | static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p); |
9d6b1ce6 | 25 | static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens); |
c8f717fe F |
26 | static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx); |
27 | static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx); | |
9ea1b878 | 28 | |
47864aea | 29 | const X509V3_EXT_METHOD ossl_v3_alt[3] = { |
0f113f3e MC |
30 | {NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), |
31 | 0, 0, 0, 0, | |
32 | 0, 0, | |
33 | (X509V3_EXT_I2V) i2v_GENERAL_NAMES, | |
34 | (X509V3_EXT_V2I)v2i_subject_alt, | |
35 | NULL, NULL, NULL}, | |
36 | ||
37 | {NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), | |
38 | 0, 0, 0, 0, | |
39 | 0, 0, | |
40 | (X509V3_EXT_I2V) i2v_GENERAL_NAMES, | |
41 | (X509V3_EXT_V2I)v2i_issuer_alt, | |
42 | NULL, NULL, NULL}, | |
43 | ||
44 | {NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES), | |
45 | 0, 0, 0, 0, | |
46 | 0, 0, | |
47 | (X509V3_EXT_I2V) i2v_GENERAL_NAMES, | |
48 | NULL, NULL, NULL, NULL}, | |
142fcca8 DSH |
49 | }; |
50 | ||
ba404b5e | 51 | STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method, |
0f113f3e MC |
52 | GENERAL_NAMES *gens, |
53 | STACK_OF(CONF_VALUE) *ret) | |
142fcca8 | 54 | { |
0f113f3e MC |
55 | int i; |
56 | GENERAL_NAME *gen; | |
45b24462 MC |
57 | STACK_OF(CONF_VALUE) *tmpret = NULL, *origret = ret; |
58 | ||
0f113f3e MC |
59 | for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { |
60 | gen = sk_GENERAL_NAME_value(gens, i); | |
45b24462 MC |
61 | /* |
62 | * i2v_GENERAL_NAME allocates ret if it is NULL. If something goes | |
63 | * wrong we need to free the stack - but only if it was empty when we | |
64 | * originally entered this function. | |
65 | */ | |
66 | tmpret = i2v_GENERAL_NAME(method, gen, ret); | |
67 | if (tmpret == NULL) { | |
68 | if (origret == NULL) | |
69 | sk_CONF_VALUE_pop_free(ret, X509V3_conf_free); | |
70 | return NULL; | |
71 | } | |
72 | ret = tmpret; | |
0f113f3e | 73 | } |
45b24462 | 74 | if (ret == NULL) |
0f113f3e MC |
75 | return sk_CONF_VALUE_new_null(); |
76 | return ret; | |
d08d8da4 DSH |
77 | } |
78 | ||
ba404b5e | 79 | STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, |
0f113f3e MC |
80 | GENERAL_NAME *gen, |
81 | STACK_OF(CONF_VALUE) *ret) | |
d08d8da4 | 82 | { |
d0bcad73 | 83 | char othername[300]; |
278260bf | 84 | char oline[256], *tmp; |
1a78a33a | 85 | |
0f113f3e MC |
86 | switch (gen->type) { |
87 | case GEN_OTHERNAME: | |
4baee2d7 DB |
88 | switch (OBJ_obj2nid(gen->d.otherName->type_id)) { |
89 | case NID_id_on_SmtpUTF8Mailbox: | |
aec9667b | 90 | if (gen->d.otherName->value->type != V_ASN1_UTF8STRING |
ad6ac174 | 91 | || !x509v3_add_len_value_uchar("othername: SmtpUTF8Mailbox:", |
aec9667b | 92 | gen->d.otherName->value->value.utf8string->data, |
ad6ac174 | 93 | gen->d.otherName->value->value.utf8string->length, |
aec9667b | 94 | &ret)) |
4baee2d7 DB |
95 | return NULL; |
96 | break; | |
97 | case NID_XmppAddr: | |
aec9667b | 98 | if (gen->d.otherName->value->type != V_ASN1_UTF8STRING |
ad6ac174 | 99 | || !x509v3_add_len_value_uchar("othername: XmppAddr:", |
aec9667b | 100 | gen->d.otherName->value->value.utf8string->data, |
ad6ac174 | 101 | gen->d.otherName->value->value.utf8string->length, |
aec9667b | 102 | &ret)) |
4baee2d7 DB |
103 | return NULL; |
104 | break; | |
105 | case NID_SRVName: | |
aec9667b | 106 | if (gen->d.otherName->value->type != V_ASN1_IA5STRING |
ad6ac174 | 107 | || !x509v3_add_len_value_uchar("othername: SRVName:", |
aec9667b | 108 | gen->d.otherName->value->value.ia5string->data, |
ad6ac174 | 109 | gen->d.otherName->value->value.ia5string->length, |
aec9667b | 110 | &ret)) |
4baee2d7 DB |
111 | return NULL; |
112 | break; | |
113 | case NID_ms_upn: | |
aec9667b | 114 | if (gen->d.otherName->value->type != V_ASN1_UTF8STRING |
ad6ac174 | 115 | || !x509v3_add_len_value_uchar("othername: UPN:", |
aec9667b | 116 | gen->d.otherName->value->value.utf8string->data, |
ad6ac174 | 117 | gen->d.otherName->value->value.utf8string->length, |
aec9667b | 118 | &ret)) |
4baee2d7 DB |
119 | return NULL; |
120 | break; | |
f5e77bb0 JFR |
121 | case NID_NAIRealm: |
122 | if (gen->d.otherName->value->type != V_ASN1_UTF8STRING | |
ad6ac174 | 123 | || !x509v3_add_len_value_uchar("othername: NAIRealm:", |
f5e77bb0 | 124 | gen->d.otherName->value->value.utf8string->data, |
ad6ac174 | 125 | gen->d.otherName->value->value.utf8string->length, |
f5e77bb0 JFR |
126 | &ret)) |
127 | return NULL; | |
128 | break; | |
4baee2d7 | 129 | default: |
47f387e9 | 130 | if (OBJ_obj2txt(oline, sizeof(oline), gen->d.otherName->type_id, 0) > 0) |
bb4f3911 SL |
131 | BIO_snprintf(othername, sizeof(othername), "othername: %s:", |
132 | oline); | |
47f387e9 | 133 | else |
2de64666 | 134 | OPENSSL_strlcpy(othername, "othername:", sizeof(othername)); |
47f387e9 DWG |
135 | |
136 | /* check if the value is something printable */ | |
137 | if (gen->d.otherName->value->type == V_ASN1_IA5STRING) { | |
ad6ac174 | 138 | if (x509v3_add_len_value_uchar(othername, |
47f387e9 | 139 | gen->d.otherName->value->value.ia5string->data, |
ad6ac174 | 140 | gen->d.otherName->value->value.ia5string->length, |
47f387e9 DWG |
141 | &ret)) |
142 | return ret; | |
143 | } | |
144 | if (gen->d.otherName->value->type == V_ASN1_UTF8STRING) { | |
ad6ac174 | 145 | if (x509v3_add_len_value_uchar(othername, |
47f387e9 | 146 | gen->d.otherName->value->value.utf8string->data, |
ad6ac174 | 147 | gen->d.otherName->value->value.utf8string->length, |
47f387e9 DWG |
148 | &ret)) |
149 | return ret; | |
150 | } | |
151 | if (!X509V3_add_value(othername, "<unsupported>", &ret)) | |
4baee2d7 DB |
152 | return NULL; |
153 | break; | |
154 | } | |
0f113f3e MC |
155 | break; |
156 | ||
157 | case GEN_X400: | |
75a3e392 MC |
158 | if (!X509V3_add_value("X400Name", "<unsupported>", &ret)) |
159 | return NULL; | |
0f113f3e MC |
160 | break; |
161 | ||
162 | case GEN_EDIPARTY: | |
75a3e392 MC |
163 | if (!X509V3_add_value("EdiPartyName", "<unsupported>", &ret)) |
164 | return NULL; | |
0f113f3e MC |
165 | break; |
166 | ||
167 | case GEN_EMAIL: | |
ad6ac174 MC |
168 | if (!x509v3_add_len_value_uchar("email", gen->d.ia5->data, |
169 | gen->d.ia5->length, &ret)) | |
75a3e392 | 170 | return NULL; |
0f113f3e MC |
171 | break; |
172 | ||
173 | case GEN_DNS: | |
ad6ac174 MC |
174 | if (!x509v3_add_len_value_uchar("DNS", gen->d.ia5->data, |
175 | gen->d.ia5->length, &ret)) | |
75a3e392 | 176 | return NULL; |
0f113f3e MC |
177 | break; |
178 | ||
179 | case GEN_URI: | |
ad6ac174 MC |
180 | if (!x509v3_add_len_value_uchar("URI", gen->d.ia5->data, |
181 | gen->d.ia5->length, &ret)) | |
75a3e392 | 182 | return NULL; |
0f113f3e MC |
183 | break; |
184 | ||
185 | case GEN_DIRNAME: | |
1a78a33a | 186 | if (X509_NAME_oneline(gen->d.dirn, oline, sizeof(oline)) == NULL |
75a3e392 MC |
187 | || !X509V3_add_value("DirName", oline, &ret)) |
188 | return NULL; | |
0f113f3e MC |
189 | break; |
190 | ||
191 | case GEN_IPADD: | |
9500c823 | 192 | tmp = ossl_ipaddr_to_asc(gen->d.ip->data, gen->d.ip->length); |
278260bf DDO |
193 | if (tmp == NULL || !X509V3_add_value("IP Address", tmp, &ret)) |
194 | ret = NULL; | |
195 | OPENSSL_free(tmp); | |
0f113f3e MC |
196 | break; |
197 | ||
198 | case GEN_RID: | |
199 | i2t_ASN1_OBJECT(oline, 256, gen->d.rid); | |
75a3e392 MC |
200 | if (!X509V3_add_value("Registered ID", oline, &ret)) |
201 | return NULL; | |
0f113f3e MC |
202 | break; |
203 | } | |
204 | return ret; | |
2c15d426 DSH |
205 | } |
206 | ||
207 | int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen) | |
208 | { | |
278260bf DDO |
209 | char *tmp; |
210 | int nid; | |
aec9667b | 211 | |
0f113f3e MC |
212 | switch (gen->type) { |
213 | case GEN_OTHERNAME: | |
aec9667b MC |
214 | nid = OBJ_obj2nid(gen->d.otherName->type_id); |
215 | /* Validate the types are as we expect before we use them */ | |
216 | if ((nid == NID_SRVName | |
217 | && gen->d.otherName->value->type != V_ASN1_IA5STRING) | |
218 | || (nid != NID_SRVName | |
219 | && gen->d.otherName->value->type != V_ASN1_UTF8STRING)) { | |
220 | BIO_printf(out, "othername:<unsupported>"); | |
221 | break; | |
222 | } | |
223 | ||
224 | switch (nid) { | |
4baee2d7 | 225 | case NID_id_on_SmtpUTF8Mailbox: |
b2b3b9c9 MC |
226 | BIO_printf(out, "othername:SmtpUTF8Mailbox:%.*s", |
227 | gen->d.otherName->value->value.utf8string->length, | |
aec9667b | 228 | gen->d.otherName->value->value.utf8string->data); |
4baee2d7 DB |
229 | break; |
230 | case NID_XmppAddr: | |
b2b3b9c9 MC |
231 | BIO_printf(out, "othername:XmppAddr:%.*s", |
232 | gen->d.otherName->value->value.utf8string->length, | |
aec9667b | 233 | gen->d.otherName->value->value.utf8string->data); |
4baee2d7 DB |
234 | break; |
235 | case NID_SRVName: | |
b2b3b9c9 MC |
236 | BIO_printf(out, "othername:SRVName:%.*s", |
237 | gen->d.otherName->value->value.ia5string->length, | |
aec9667b | 238 | gen->d.otherName->value->value.ia5string->data); |
4baee2d7 DB |
239 | break; |
240 | case NID_ms_upn: | |
b2b3b9c9 MC |
241 | BIO_printf(out, "othername:UPN:%.*s", |
242 | gen->d.otherName->value->value.utf8string->length, | |
aec9667b | 243 | gen->d.otherName->value->value.utf8string->data); |
4baee2d7 | 244 | break; |
f5e77bb0 | 245 | case NID_NAIRealm: |
b2b3b9c9 MC |
246 | BIO_printf(out, "othername:NAIRealm:%.*s", |
247 | gen->d.otherName->value->value.utf8string->length, | |
f5e77bb0 JFR |
248 | gen->d.otherName->value->value.utf8string->data); |
249 | break; | |
4baee2d7 DB |
250 | default: |
251 | BIO_printf(out, "othername:<unsupported>"); | |
252 | break; | |
253 | } | |
0f113f3e MC |
254 | break; |
255 | ||
256 | case GEN_X400: | |
257 | BIO_printf(out, "X400Name:<unsupported>"); | |
258 | break; | |
259 | ||
260 | case GEN_EDIPARTY: | |
261 | /* Maybe fix this: it is supported now */ | |
262 | BIO_printf(out, "EdiPartyName:<unsupported>"); | |
263 | break; | |
264 | ||
265 | case GEN_EMAIL: | |
bab60461 AB |
266 | BIO_printf(out, "email:"); |
267 | ASN1_STRING_print(out, gen->d.ia5); | |
0f113f3e MC |
268 | break; |
269 | ||
270 | case GEN_DNS: | |
bab60461 AB |
271 | BIO_printf(out, "DNS:"); |
272 | ASN1_STRING_print(out, gen->d.ia5); | |
0f113f3e MC |
273 | break; |
274 | ||
275 | case GEN_URI: | |
bab60461 AB |
276 | BIO_printf(out, "URI:"); |
277 | ASN1_STRING_print(out, gen->d.ia5); | |
0f113f3e MC |
278 | break; |
279 | ||
280 | case GEN_DIRNAME: | |
ca1cb0d4 | 281 | BIO_printf(out, "DirName:"); |
0f113f3e MC |
282 | X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE); |
283 | break; | |
284 | ||
285 | case GEN_IPADD: | |
9500c823 | 286 | tmp = ossl_ipaddr_to_asc(gen->d.ip->data, gen->d.ip->length); |
278260bf DDO |
287 | if (tmp == NULL) |
288 | return 0; | |
289 | BIO_printf(out, "IP Address:%s", tmp); | |
290 | OPENSSL_free(tmp); | |
0f113f3e MC |
291 | break; |
292 | ||
293 | case GEN_RID: | |
ca1cb0d4 | 294 | BIO_printf(out, "Registered ID:"); |
0f113f3e MC |
295 | i2a_ASN1_OBJECT(out, gen->d.rid); |
296 | break; | |
297 | } | |
298 | return 1; | |
142fcca8 DSH |
299 | } |
300 | ||
9d6b1ce6 | 301 | static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, |
0f113f3e MC |
302 | X509V3_CTX *ctx, |
303 | STACK_OF(CONF_VALUE) *nval) | |
aa066b9e | 304 | { |
270a4bba | 305 | const int num = sk_CONF_VALUE_num(nval); |
7a908204 | 306 | GENERAL_NAMES *gens = sk_GENERAL_NAME_new_reserve(NULL, num); |
0f113f3e | 307 | int i; |
75ebbd9a | 308 | |
7a908204 | 309 | if (gens == NULL) { |
9311d0c4 | 310 | ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); |
270a4bba | 311 | sk_GENERAL_NAME_free(gens); |
0f113f3e MC |
312 | return NULL; |
313 | } | |
270a4bba F |
314 | for (i = 0; i < num; i++) { |
315 | CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i); | |
316 | ||
47864aea | 317 | if (!ossl_v3_name_cmp(cnf->name, "issuer") |
86885c28 | 318 | && cnf->value && strcmp(cnf->value, "copy") == 0) { |
0f113f3e MC |
319 | if (!copy_issuer(ctx, gens)) |
320 | goto err; | |
321 | } else { | |
270a4bba F |
322 | GENERAL_NAME *gen = v2i_GENERAL_NAME(method, ctx, cnf); |
323 | ||
324 | if (gen == NULL) | |
0f113f3e | 325 | goto err; |
270a4bba | 326 | sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */ |
0f113f3e MC |
327 | } |
328 | } | |
329 | return gens; | |
330 | err: | |
331 | sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); | |
332 | return NULL; | |
aa066b9e DSH |
333 | } |
334 | ||
335 | /* Append subject altname of issuer to issuer alt name of subject */ | |
336 | ||
9d6b1ce6 | 337 | static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens) |
aa066b9e | 338 | { |
0f113f3e MC |
339 | GENERAL_NAMES *ialt; |
340 | GENERAL_NAME *gen; | |
341 | X509_EXTENSION *ext; | |
270a4bba | 342 | int i, num; |
75ebbd9a | 343 | |
2ed63033 | 344 | if (ctx != NULL && (ctx->flags & X509V3_CTX_TEST) != 0) |
0f113f3e MC |
345 | return 1; |
346 | if (!ctx || !ctx->issuer_cert) { | |
9311d0c4 | 347 | ERR_raise(ERR_LIB_X509V3, X509V3_R_NO_ISSUER_DETAILS); |
0f113f3e MC |
348 | goto err; |
349 | } | |
350 | i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1); | |
351 | if (i < 0) | |
352 | return 1; | |
75ebbd9a RS |
353 | if ((ext = X509_get_ext(ctx->issuer_cert, i)) == NULL |
354 | || (ialt = X509V3_EXT_d2i(ext)) == NULL) { | |
9311d0c4 | 355 | ERR_raise(ERR_LIB_X509V3, X509V3_R_ISSUER_DECODE_ERROR); |
0f113f3e MC |
356 | goto err; |
357 | } | |
358 | ||
270a4bba F |
359 | num = sk_GENERAL_NAME_num(ialt); |
360 | if (!sk_GENERAL_NAME_reserve(gens, num)) { | |
9311d0c4 | 361 | ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); |
270a4bba F |
362 | goto err; |
363 | } | |
364 | ||
365 | for (i = 0; i < num; i++) { | |
0f113f3e | 366 | gen = sk_GENERAL_NAME_value(ialt, i); |
270a4bba | 367 | sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */ |
0f113f3e MC |
368 | } |
369 | sk_GENERAL_NAME_free(ialt); | |
370 | ||
371 | return 1; | |
372 | ||
373 | err: | |
374 | return 0; | |
375 | ||
aa066b9e DSH |
376 | } |
377 | ||
9d6b1ce6 | 378 | static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, |
0f113f3e MC |
379 | X509V3_CTX *ctx, |
380 | STACK_OF(CONF_VALUE) *nval) | |
aa066b9e | 381 | { |
270a4bba | 382 | GENERAL_NAMES *gens; |
0f113f3e | 383 | CONF_VALUE *cnf; |
270a4bba | 384 | const int num = sk_CONF_VALUE_num(nval); |
0f113f3e | 385 | int i; |
75ebbd9a | 386 | |
7a908204 PY |
387 | gens = sk_GENERAL_NAME_new_reserve(NULL, num); |
388 | if (gens == NULL) { | |
9311d0c4 | 389 | ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); |
270a4bba | 390 | sk_GENERAL_NAME_free(gens); |
0f113f3e MC |
391 | return NULL; |
392 | } | |
270a4bba F |
393 | |
394 | for (i = 0; i < num; i++) { | |
0f113f3e | 395 | cnf = sk_CONF_VALUE_value(nval, i); |
47864aea | 396 | if (!ossl_v3_name_cmp(cnf->name, "email") |
86885c28 | 397 | && cnf->value && strcmp(cnf->value, "copy") == 0) { |
0f113f3e MC |
398 | if (!copy_email(ctx, gens, 0)) |
399 | goto err; | |
47864aea | 400 | } else if (!ossl_v3_name_cmp(cnf->name, "email") |
86885c28 | 401 | && cnf->value && strcmp(cnf->value, "move") == 0) { |
0f113f3e MC |
402 | if (!copy_email(ctx, gens, 1)) |
403 | goto err; | |
404 | } else { | |
405 | GENERAL_NAME *gen; | |
75ebbd9a | 406 | if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL) |
0f113f3e | 407 | goto err; |
270a4bba | 408 | sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */ |
0f113f3e MC |
409 | } |
410 | } | |
411 | return gens; | |
412 | err: | |
413 | sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); | |
414 | return NULL; | |
aa066b9e DSH |
415 | } |
416 | ||
0f113f3e MC |
417 | /* |
418 | * Copy any email addresses in a certificate or request to GENERAL_NAMES | |
aa066b9e DSH |
419 | */ |
420 | ||
c9fd77e9 | 421 | static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p) |
aa066b9e | 422 | { |
0f113f3e MC |
423 | X509_NAME *nm; |
424 | ASN1_IA5STRING *email = NULL; | |
425 | X509_NAME_ENTRY *ne; | |
426 | GENERAL_NAME *gen = NULL; | |
d2a56999 F |
427 | int i = -1; |
428 | ||
2ed63033 | 429 | if (ctx != NULL && (ctx->flags & X509V3_CTX_TEST) != 0) |
0f113f3e | 430 | return 1; |
bd91e3c8 | 431 | if (ctx == NULL |
d2a56999 | 432 | || (ctx->subject_cert == NULL && ctx->subject_req == NULL)) { |
9311d0c4 | 433 | ERR_raise(ERR_LIB_X509V3, X509V3_R_NO_SUBJECT_DETAILS); |
41e597a0 | 434 | return 0; |
0f113f3e MC |
435 | } |
436 | /* Find the subject name */ | |
437 | if (ctx->subject_cert) | |
438 | nm = X509_get_subject_name(ctx->subject_cert); | |
439 | else | |
440 | nm = X509_REQ_get_subject_name(ctx->subject_req); | |
441 | ||
442 | /* Now add any email address(es) to STACK */ | |
0f113f3e MC |
443 | while ((i = X509_NAME_get_index_by_NID(nm, |
444 | NID_pkcs9_emailAddress, i)) >= 0) { | |
445 | ne = X509_NAME_get_entry(nm, i); | |
f422a514 | 446 | email = ASN1_STRING_dup(X509_NAME_ENTRY_get_data(ne)); |
0f113f3e MC |
447 | if (move_p) { |
448 | X509_NAME_delete_entry(nm, i); | |
449 | X509_NAME_ENTRY_free(ne); | |
450 | i--; | |
451 | } | |
75ebbd9a | 452 | if (email == NULL || (gen = GENERAL_NAME_new()) == NULL) { |
9311d0c4 | 453 | ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); |
0f113f3e MC |
454 | goto err; |
455 | } | |
456 | gen->d.ia5 = email; | |
457 | email = NULL; | |
458 | gen->type = GEN_EMAIL; | |
459 | if (!sk_GENERAL_NAME_push(gens, gen)) { | |
9311d0c4 | 460 | ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); |
0f113f3e MC |
461 | goto err; |
462 | } | |
463 | gen = NULL; | |
464 | } | |
465 | ||
466 | return 1; | |
467 | ||
468 | err: | |
469 | GENERAL_NAME_free(gen); | |
f422a514 | 470 | ASN1_IA5STRING_free(email); |
0f113f3e MC |
471 | return 0; |
472 | ||
aa066b9e DSH |
473 | } |
474 | ||
babb3798 | 475 | GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method, |
0f113f3e | 476 | X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) |
d08d8da4 | 477 | { |
0f113f3e | 478 | GENERAL_NAME *gen; |
270a4bba | 479 | GENERAL_NAMES *gens; |
0f113f3e | 480 | CONF_VALUE *cnf; |
270a4bba | 481 | const int num = sk_CONF_VALUE_num(nval); |
0f113f3e | 482 | int i; |
75ebbd9a | 483 | |
7a908204 PY |
484 | gens = sk_GENERAL_NAME_new_reserve(NULL, num); |
485 | if (gens == NULL) { | |
9311d0c4 | 486 | ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); |
270a4bba | 487 | sk_GENERAL_NAME_free(gens); |
0f113f3e MC |
488 | return NULL; |
489 | } | |
270a4bba F |
490 | |
491 | for (i = 0; i < num; i++) { | |
0f113f3e | 492 | cnf = sk_CONF_VALUE_value(nval, i); |
75ebbd9a | 493 | if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL) |
0f113f3e | 494 | goto err; |
270a4bba | 495 | sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */ |
0f113f3e MC |
496 | } |
497 | return gens; | |
498 | err: | |
499 | sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); | |
500 | return NULL; | |
d08d8da4 DSH |
501 | } |
502 | ||
0f113f3e MC |
503 | GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, |
504 | X509V3_CTX *ctx, CONF_VALUE *cnf) | |
505 | { | |
506 | return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0); | |
507 | } | |
d08d8da4 | 508 | |
be86c7fc | 509 | GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out, |
0f113f3e | 510 | const X509V3_EXT_METHOD *method, |
c8f717fe | 511 | X509V3_CTX *ctx, int gen_type, const char *value, |
0f113f3e MC |
512 | int is_nc) |
513 | { | |
514 | char is_string = 0; | |
515 | GENERAL_NAME *gen = NULL; | |
516 | ||
517 | if (!value) { | |
9311d0c4 | 518 | ERR_raise(ERR_LIB_X509V3, X509V3_R_MISSING_VALUE); |
0f113f3e MC |
519 | return NULL; |
520 | } | |
521 | ||
522 | if (out) | |
523 | gen = out; | |
524 | else { | |
525 | gen = GENERAL_NAME_new(); | |
526 | if (gen == NULL) { | |
9311d0c4 | 527 | ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); |
0f113f3e MC |
528 | return NULL; |
529 | } | |
530 | } | |
531 | ||
532 | switch (gen_type) { | |
533 | case GEN_URI: | |
534 | case GEN_EMAIL: | |
535 | case GEN_DNS: | |
536 | is_string = 1; | |
537 | break; | |
538 | ||
539 | case GEN_RID: | |
540 | { | |
541 | ASN1_OBJECT *obj; | |
75ebbd9a | 542 | if ((obj = OBJ_txt2obj(value, 0)) == NULL) { |
a150f8e1 RL |
543 | ERR_raise_data(ERR_LIB_X509V3, X509V3_R_BAD_OBJECT, |
544 | "value=%s", value); | |
0f113f3e MC |
545 | goto err; |
546 | } | |
547 | gen->d.rid = obj; | |
548 | } | |
549 | break; | |
550 | ||
551 | case GEN_IPADD: | |
552 | if (is_nc) | |
553 | gen->d.ip = a2i_IPADDRESS_NC(value); | |
554 | else | |
555 | gen->d.ip = a2i_IPADDRESS(value); | |
556 | if (gen->d.ip == NULL) { | |
a150f8e1 RL |
557 | ERR_raise_data(ERR_LIB_X509V3, X509V3_R_BAD_IP_ADDRESS, |
558 | "value=%s", value); | |
0f113f3e MC |
559 | goto err; |
560 | } | |
561 | break; | |
562 | ||
563 | case GEN_DIRNAME: | |
564 | if (!do_dirname(gen, value, ctx)) { | |
9311d0c4 | 565 | ERR_raise(ERR_LIB_X509V3, X509V3_R_DIRNAME_ERROR); |
0f113f3e MC |
566 | goto err; |
567 | } | |
568 | break; | |
569 | ||
570 | case GEN_OTHERNAME: | |
571 | if (!do_othername(gen, value, ctx)) { | |
9311d0c4 | 572 | ERR_raise(ERR_LIB_X509V3, X509V3_R_OTHERNAME_ERROR); |
0f113f3e MC |
573 | goto err; |
574 | } | |
575 | break; | |
576 | default: | |
9311d0c4 | 577 | ERR_raise(ERR_LIB_X509V3, X509V3_R_UNSUPPORTED_TYPE); |
0f113f3e MC |
578 | goto err; |
579 | } | |
580 | ||
581 | if (is_string) { | |
75ebbd9a | 582 | if ((gen->d.ia5 = ASN1_IA5STRING_new()) == NULL || |
0f113f3e MC |
583 | !ASN1_STRING_set(gen->d.ia5, (unsigned char *)value, |
584 | strlen(value))) { | |
9311d0c4 | 585 | ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); |
0f113f3e MC |
586 | goto err; |
587 | } | |
588 | } | |
589 | ||
590 | gen->type = gen_type; | |
591 | ||
592 | return gen; | |
593 | ||
594 | err: | |
595 | if (!out) | |
596 | GENERAL_NAME_free(gen); | |
597 | return NULL; | |
598 | } | |
9ea1b878 | 599 | |
be86c7fc | 600 | GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out, |
0f113f3e MC |
601 | const X509V3_EXT_METHOD *method, |
602 | X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc) | |
603 | { | |
604 | int type; | |
605 | ||
606 | char *name, *value; | |
607 | ||
608 | name = cnf->name; | |
609 | value = cnf->value; | |
610 | ||
611 | if (!value) { | |
9311d0c4 | 612 | ERR_raise(ERR_LIB_X509V3, X509V3_R_MISSING_VALUE); |
0f113f3e MC |
613 | return NULL; |
614 | } | |
615 | ||
47864aea | 616 | if (!ossl_v3_name_cmp(name, "email")) |
0f113f3e | 617 | type = GEN_EMAIL; |
47864aea | 618 | else if (!ossl_v3_name_cmp(name, "URI")) |
0f113f3e | 619 | type = GEN_URI; |
47864aea | 620 | else if (!ossl_v3_name_cmp(name, "DNS")) |
0f113f3e | 621 | type = GEN_DNS; |
47864aea | 622 | else if (!ossl_v3_name_cmp(name, "RID")) |
0f113f3e | 623 | type = GEN_RID; |
47864aea | 624 | else if (!ossl_v3_name_cmp(name, "IP")) |
0f113f3e | 625 | type = GEN_IPADD; |
47864aea | 626 | else if (!ossl_v3_name_cmp(name, "dirName")) |
0f113f3e | 627 | type = GEN_DIRNAME; |
47864aea | 628 | else if (!ossl_v3_name_cmp(name, "otherName")) |
0f113f3e MC |
629 | type = GEN_OTHERNAME; |
630 | else { | |
a150f8e1 RL |
631 | ERR_raise_data(ERR_LIB_X509V3, X509V3_R_UNSUPPORTED_OPTION, |
632 | "name=%s", name); | |
0f113f3e MC |
633 | return NULL; |
634 | } | |
635 | ||
636 | return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc); | |
637 | ||
638 | } | |
be86c7fc | 639 | |
c8f717fe | 640 | static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx) |
0f113f3e MC |
641 | { |
642 | char *objtmp = NULL, *p; | |
643 | int objlen; | |
75ebbd9a RS |
644 | |
645 | if ((p = strchr(value, ';')) == NULL) | |
0f113f3e | 646 | return 0; |
75ebbd9a | 647 | if ((gen->d.otherName = OTHERNAME_new()) == NULL) |
0f113f3e MC |
648 | return 0; |
649 | /* | |
650 | * Free this up because we will overwrite it. no need to free type_id | |
651 | * because it is static | |
652 | */ | |
653 | ASN1_TYPE_free(gen->d.otherName->value); | |
75ebbd9a | 654 | if ((gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)) == NULL) |
0f113f3e MC |
655 | return 0; |
656 | objlen = p - value; | |
5e04cfde | 657 | objtmp = OPENSSL_strndup(value, objlen); |
0f113f3e MC |
658 | if (objtmp == NULL) |
659 | return 0; | |
0f113f3e MC |
660 | gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0); |
661 | OPENSSL_free(objtmp); | |
662 | if (!gen->d.otherName->type_id) | |
663 | return 0; | |
664 | return 1; | |
665 | } | |
f0dc08e6 | 666 | |
c8f717fe | 667 | static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx) |
0f113f3e | 668 | { |
8ec5c5dd KR |
669 | int ret = 0; |
670 | STACK_OF(CONF_VALUE) *sk = NULL; | |
75ebbd9a RS |
671 | X509_NAME *nm; |
672 | ||
673 | if ((nm = X509_NAME_new()) == NULL) | |
8ec5c5dd | 674 | goto err; |
0f113f3e MC |
675 | sk = X509V3_get_section(ctx, value); |
676 | if (!sk) { | |
a150f8e1 RL |
677 | ERR_raise_data(ERR_LIB_X509V3, X509V3_R_SECTION_NOT_FOUND, |
678 | "section=%s", value); | |
8ec5c5dd | 679 | goto err; |
0f113f3e MC |
680 | } |
681 | /* FIXME: should allow other character types... */ | |
682 | ret = X509V3_NAME_from_section(nm, sk, MBSTRING_ASC); | |
683 | if (!ret) | |
8ec5c5dd | 684 | goto err; |
0f113f3e | 685 | gen->d.dirn = nm; |
0f113f3e | 686 | |
8ec5c5dd KR |
687 | err: |
688 | if (ret == 0) | |
689 | X509_NAME_free(nm); | |
690 | X509V3_section_free(ctx, sk); | |
0f113f3e MC |
691 | return ret; |
692 | } |