52c4f54679cbb011601876299c717ba8d7456d87
[openssl.git] / crypto / x509v3 / v3_alt.c
1 /* v3_alt.c */
2 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
3  * project 1999.
4  */
5 /* ====================================================================
6  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer. 
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58
59 #include <stdio.h>
60 #include "cryptlib.h"
61 #include <openssl/conf.h>
62 #include <openssl/x509v3.h>
63
64 static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
65 static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
66 static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens);
67 static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens);
68 X509V3_EXT_METHOD v3_alt[] = {
69 { NID_subject_alt_name, 0,
70 (X509V3_EXT_NEW)GENERAL_NAMES_new,
71 (X509V3_EXT_FREE)GENERAL_NAMES_free,
72 (X509V3_EXT_D2I)d2i_GENERAL_NAMES,
73 (X509V3_EXT_I2D)i2d_GENERAL_NAMES,
74 NULL, NULL,
75 (X509V3_EXT_I2V)i2v_GENERAL_NAMES,
76 (X509V3_EXT_V2I)v2i_subject_alt,
77 NULL, NULL, NULL},
78 { NID_issuer_alt_name, 0,
79 (X509V3_EXT_NEW)GENERAL_NAMES_new,
80 (X509V3_EXT_FREE)GENERAL_NAMES_free,
81 (X509V3_EXT_D2I)d2i_GENERAL_NAMES,
82 (X509V3_EXT_I2D)i2d_GENERAL_NAMES,
83 NULL, NULL,
84 (X509V3_EXT_I2V)i2v_GENERAL_NAMES,
85 (X509V3_EXT_V2I)v2i_issuer_alt,
86 NULL, NULL, NULL},
87 };
88
89 STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
90                 GENERAL_NAMES *gens, STACK_OF(CONF_VALUE) *ret)
91 {
92         int i;
93         GENERAL_NAME *gen;
94         for(i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
95                 gen = sk_GENERAL_NAME_value(gens, i);
96                 ret = i2v_GENERAL_NAME(method, gen, ret);
97         }
98         if(!ret) return sk_CONF_VALUE_new_null();
99         return ret;
100 }
101
102 STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
103                                 GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret)
104 {
105         char oline[256];
106         unsigned char *p;
107         switch (gen->type)
108         {
109                 case GEN_OTHERNAME:
110                 X509V3_add_value("othername","<unsupported>", &ret);
111                 break;
112
113                 case GEN_X400:
114                 X509V3_add_value("X400Name","<unsupported>", &ret);
115                 break;
116
117                 case GEN_EDIPARTY:
118                 X509V3_add_value("EdiPartyName","<unsupported>", &ret);
119                 break;
120
121                 case GEN_EMAIL:
122                 X509V3_add_value_uchar("email",gen->d.ia5->data, &ret);
123                 break;
124
125                 case GEN_DNS:
126                 X509V3_add_value_uchar("DNS",gen->d.ia5->data, &ret);
127                 break;
128
129                 case GEN_URI:
130                 X509V3_add_value_uchar("URI",gen->d.ia5->data, &ret);
131                 break;
132
133                 case GEN_DIRNAME:
134                 X509_NAME_oneline(gen->d.dirn, oline, 256);
135                 X509V3_add_value("DirName",oline, &ret);
136                 break;
137
138                 case GEN_IPADD:
139                 p = gen->d.ip->data;
140                 /* BUG: doesn't support IPV6 */
141                 if(gen->d.ip->length != 4) {
142                         X509V3_add_value("IP Address","<invalid>", &ret);
143                         break;
144                 }
145                 sprintf(oline, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
146                 X509V3_add_value("IP Address",oline, &ret);
147                 break;
148
149                 case GEN_RID:
150                 i2t_ASN1_OBJECT(oline, 256, gen->d.rid);
151                 X509V3_add_value("Registered ID",oline, &ret);
152                 break;
153         }
154         return ret;
155 }
156
157 static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
158                                  X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
159 {
160         GENERAL_NAMES *gens = NULL;
161         CONF_VALUE *cnf;
162         int i;
163         if(!(gens = sk_GENERAL_NAME_new_null())) {
164                 X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE);
165                 return NULL;
166         }
167         for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
168                 cnf = sk_CONF_VALUE_value(nval, i);
169                 if(!name_cmp(cnf->name, "issuer") && cnf->value &&
170                                                 !strcmp(cnf->value, "copy")) {
171                         if(!copy_issuer(ctx, gens)) goto err;
172                 } else {
173                         GENERAL_NAME *gen;
174                         if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
175                                                                  goto err; 
176                         sk_GENERAL_NAME_push(gens, gen);
177                 }
178         }
179         return gens;
180         err:
181         sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
182         return NULL;
183 }
184
185 /* Append subject altname of issuer to issuer alt name of subject */
186
187 static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens)
188 {
189         GENERAL_NAMES *ialt;
190         GENERAL_NAME *gen;
191         X509_EXTENSION *ext;
192         int i;
193         if(ctx && (ctx->flags == CTX_TEST)) return 1;
194         if(!ctx || !ctx->issuer_cert) {
195                 X509V3err(X509V3_F_COPY_ISSUER,X509V3_R_NO_ISSUER_DETAILS);
196                 goto err;
197         }
198         i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
199         if(i < 0) return 1;
200         if(!(ext = X509_get_ext(ctx->issuer_cert, i)) ||
201                         !(ialt = X509V3_EXT_d2i(ext)) ) {
202                 X509V3err(X509V3_F_COPY_ISSUER,X509V3_R_ISSUER_DECODE_ERROR);
203                 goto err;
204         }
205
206         for(i = 0; i < sk_GENERAL_NAME_num(ialt); i++) {
207                 gen = sk_GENERAL_NAME_value(ialt, i);
208                 if(!sk_GENERAL_NAME_push(gens, gen)) {
209                         X509V3err(X509V3_F_COPY_ISSUER,ERR_R_MALLOC_FAILURE);
210                         goto err;
211                 }
212         }
213         sk_GENERAL_NAME_free(ialt);
214
215         return 1;
216                 
217         err:
218         return 0;
219         
220 }
221
222 static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
223                                  X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
224 {
225         GENERAL_NAMES *gens = NULL;
226         CONF_VALUE *cnf;
227         int i;
228         if(!(gens = sk_GENERAL_NAME_new_null())) {
229                 X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE);
230                 return NULL;
231         }
232         for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
233                 cnf = sk_CONF_VALUE_value(nval, i);
234                 if(!name_cmp(cnf->name, "email") && cnf->value &&
235                                                 !strcmp(cnf->value, "copy")) {
236                         if(!copy_email(ctx, gens)) goto err;
237                 } else {
238                         GENERAL_NAME *gen;
239                         if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
240                                                                  goto err; 
241                         sk_GENERAL_NAME_push(gens, gen);
242                 }
243         }
244         return gens;
245         err:
246         sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
247         return NULL;
248 }
249
250 /* Copy any email addresses in a certificate or request to 
251  * GENERAL_NAMES
252  */
253
254 static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens)
255 {
256         X509_NAME *nm;
257         ASN1_IA5STRING *email = NULL;
258         X509_NAME_ENTRY *ne;
259         GENERAL_NAME *gen = NULL;
260         int i;
261         if(ctx->flags == CTX_TEST) return 1;
262         if(!ctx || (!ctx->subject_cert && !ctx->subject_req)) {
263                 X509V3err(X509V3_F_COPY_EMAIL,X509V3_R_NO_SUBJECT_DETAILS);
264                 goto err;
265         }
266         /* Find the subject name */
267         if(ctx->subject_cert) nm = X509_get_subject_name(ctx->subject_cert);
268         else nm = X509_REQ_get_subject_name(ctx->subject_req);
269
270         /* Now add any email address(es) to STACK */
271         i = -1;
272         while((i = X509_NAME_get_index_by_NID(nm,
273                                          NID_pkcs9_emailAddress, i)) > 0) {
274                 ne = X509_NAME_get_entry(nm, i);
275                 email = M_ASN1_IA5STRING_dup(X509_NAME_ENTRY_get_data(ne));
276                 if(!email || !(gen = GENERAL_NAME_new())) {
277                         X509V3err(X509V3_F_COPY_EMAIL,ERR_R_MALLOC_FAILURE);
278                         goto err;
279                 }
280                 gen->d.ia5 = email;
281                 email = NULL;
282                 gen->type = GEN_EMAIL;
283                 if(!sk_GENERAL_NAME_push(gens, gen)) {
284                         X509V3err(X509V3_F_COPY_EMAIL,ERR_R_MALLOC_FAILURE);
285                         goto err;
286                 }
287                 gen = NULL;
288         }
289
290         
291         return 1;
292                 
293         err:
294         GENERAL_NAME_free(gen);
295         M_ASN1_IA5STRING_free(email);
296         return 0;
297         
298 }
299
300 GENERAL_NAMES *v2i_GENERAL_NAMES(X509V3_EXT_METHOD *method,
301                                 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
302 {
303         GENERAL_NAME *gen;
304         GENERAL_NAMES *gens = NULL;
305         CONF_VALUE *cnf;
306         int i;
307         if(!(gens = sk_GENERAL_NAME_new_null())) {
308                 X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE);
309                 return NULL;
310         }
311         for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
312                 cnf = sk_CONF_VALUE_value(nval, i);
313                 if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) goto err; 
314                 sk_GENERAL_NAME_push(gens, gen);
315         }
316         return gens;
317         err:
318         sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
319         return NULL;
320 }
321
322 GENERAL_NAME *v2i_GENERAL_NAME(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
323                                                          CONF_VALUE *cnf)
324 {
325 char is_string = 0;
326 int type;
327 GENERAL_NAME *gen = NULL;
328
329 char *name, *value;
330
331 name = cnf->name;
332 value = cnf->value;
333
334 if(!value) {
335         X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_MISSING_VALUE);
336         return NULL;
337 }
338
339 if(!(gen = GENERAL_NAME_new())) {
340         X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE);
341         return NULL;
342 }
343
344 if(!name_cmp(name, "email")) {
345         is_string = 1;
346         type = GEN_EMAIL;
347 } else if(!name_cmp(name, "URI")) {
348         is_string = 1;
349         type = GEN_URI;
350 } else if(!name_cmp(name, "DNS")) {
351         is_string = 1;
352         type = GEN_DNS;
353 } else if(!name_cmp(name, "RID")) {
354         ASN1_OBJECT *obj;
355         if(!(obj = OBJ_txt2obj(value,0))) {
356                 X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_BAD_OBJECT);
357                 ERR_add_error_data(2, "value=", value);
358                 goto err;
359         }
360         gen->d.rid = obj;
361         type = GEN_RID;
362 } else if(!name_cmp(name, "IP")) {
363         int i1,i2,i3,i4;
364         unsigned char ip[4];
365         if((sscanf(value, "%d.%d.%d.%d",&i1,&i2,&i3,&i4) != 4) ||
366             (i1 < 0) || (i1 > 255) || (i2 < 0) || (i2 > 255) ||
367             (i3 < 0) || (i3 > 255) || (i4 < 0) || (i4 > 255) ) {
368                 X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_BAD_IP_ADDRESS);
369                 ERR_add_error_data(2, "value=", value);
370                 goto err;
371         }
372         ip[0] = i1; ip[1] = i2 ; ip[2] = i3 ; ip[3] = i4;
373         if(!(gen->d.ip = M_ASN1_OCTET_STRING_new()) ||
374                 !ASN1_STRING_set(gen->d.ip, ip, 4)) {
375                         X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE);
376                         goto err;
377         }
378         type = GEN_IPADD;
379 } else {
380         X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_UNSUPPORTED_OPTION);
381         ERR_add_error_data(2, "name=", name);
382         goto err;
383 }
384
385 if(is_string) {
386         if(!(gen->d.ia5 = M_ASN1_IA5STRING_new()) ||
387                       !ASN1_STRING_set(gen->d.ia5, (unsigned char*)value,
388                                        strlen(value))) {
389                 X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE);
390                 goto err;
391         }
392 }
393
394 gen->type = type;
395
396 return gen;
397
398 err:
399 GENERAL_NAME_free(gen);
400 return NULL;
401 }