OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
v3_alt.c
Go to the documentation of this file.
1 /* v3_alt.c */
2 /* Written by Dr Stephen N Henson ([email protected]) for the OpenSSL
3  * project.
4  */
5 /* ====================================================================
6  * Copyright (c) 1999-2003 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
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  * ([email protected]). This product includes software written by Tim
55  * Hudson ([email protected]).
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, int move_p);
67 static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens);
68 static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx);
69 static int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx);
70 
72 { NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
73 0,0,0,0,
74 0,0,
75 (X509V3_EXT_I2V)i2v_GENERAL_NAMES,
76 (X509V3_EXT_V2I)v2i_subject_alt,
77 NULL, NULL, NULL},
78 
79 { NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
80 0,0,0,0,
81 0,0,
82 (X509V3_EXT_I2V)i2v_GENERAL_NAMES,
83 (X509V3_EXT_V2I)v2i_issuer_alt,
84 NULL, NULL, NULL},
85 
86 { NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES),
87 0,0,0,0,
88 0,0,
89 (X509V3_EXT_I2V)i2v_GENERAL_NAMES,
90 NULL, NULL, NULL, NULL},
91 };
92 
93 STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
94  GENERAL_NAMES *gens, STACK_OF(CONF_VALUE) *ret)
95 {
96  int i;
98  for(i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
99  gen = sk_GENERAL_NAME_value(gens, i);
100  ret = i2v_GENERAL_NAME(method, gen, ret);
101  }
102  if(!ret) return sk_CONF_VALUE_new_null();
103  return ret;
104 }
105 
106 STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
108 {
109  unsigned char *p;
110  char oline[256], htmp[5];
111  int i;
112  switch (gen->type)
113  {
114  case GEN_OTHERNAME:
115  X509V3_add_value("othername","<unsupported>", &ret);
116  break;
117 
118  case GEN_X400:
119  X509V3_add_value("X400Name","<unsupported>", &ret);
120  break;
121 
122  case GEN_EDIPARTY:
123  X509V3_add_value("EdiPartyName","<unsupported>", &ret);
124  break;
125 
126  case GEN_EMAIL:
127  X509V3_add_value_uchar("email",gen->d.ia5->data, &ret);
128  break;
129 
130  case GEN_DNS:
131  X509V3_add_value_uchar("DNS",gen->d.ia5->data, &ret);
132  break;
133 
134  case GEN_URI:
135  X509V3_add_value_uchar("URI",gen->d.ia5->data, &ret);
136  break;
137 
138  case GEN_DIRNAME:
139  X509_NAME_oneline(gen->d.dirn, oline, 256);
140  X509V3_add_value("DirName",oline, &ret);
141  break;
142 
143  case GEN_IPADD:
144  p = gen->d.ip->data;
145  if(gen->d.ip->length == 4)
146  BIO_snprintf(oline, sizeof oline,
147  "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
148  else if(gen->d.ip->length == 16)
149  {
150  oline[0] = 0;
151  for (i = 0; i < 8; i++)
152  {
153  BIO_snprintf(htmp, sizeof htmp,
154  "%X", p[0] << 8 | p[1]);
155  p += 2;
156  strcat(oline, htmp);
157  if (i != 7)
158  strcat(oline, ":");
159  }
160  }
161  else
162  {
163  X509V3_add_value("IP Address","<invalid>", &ret);
164  break;
165  }
166  X509V3_add_value("IP Address",oline, &ret);
167  break;
168 
169  case GEN_RID:
170  i2t_ASN1_OBJECT(oline, 256, gen->d.rid);
171  X509V3_add_value("Registered ID",oline, &ret);
172  break;
173  }
174  return ret;
175 }
176 
178 {
179  unsigned char *p;
180  int i;
181  switch (gen->type)
182  {
183  case GEN_OTHERNAME:
184  BIO_printf(out, "othername:<unsupported>");
185  break;
186 
187  case GEN_X400:
188  BIO_printf(out, "X400Name:<unsupported>");
189  break;
190 
191  case GEN_EDIPARTY:
192  /* Maybe fix this: it is supported now */
193  BIO_printf(out, "EdiPartyName:<unsupported>");
194  break;
195 
196  case GEN_EMAIL:
197  BIO_printf(out, "email:%s",gen->d.ia5->data);
198  break;
199 
200  case GEN_DNS:
201  BIO_printf(out, "DNS:%s",gen->d.ia5->data);
202  break;
203 
204  case GEN_URI:
205  BIO_printf(out, "URI:%s",gen->d.ia5->data);
206  break;
207 
208  case GEN_DIRNAME:
209  BIO_printf(out, "DirName: ");
210  X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE);
211  break;
212 
213  case GEN_IPADD:
214  p = gen->d.ip->data;
215  if(gen->d.ip->length == 4)
216  BIO_printf(out, "IP Address:%d.%d.%d.%d",
217  p[0], p[1], p[2], p[3]);
218  else if(gen->d.ip->length == 16)
219  {
220  BIO_printf(out, "IP Address");
221  for (i = 0; i < 8; i++)
222  {
223  BIO_printf(out, ":%X", p[0] << 8 | p[1]);
224  p += 2;
225  }
226  BIO_puts(out, "\n");
227  }
228  else
229  {
230  BIO_printf(out,"IP Address:<invalid>");
231  break;
232  }
233  break;
234 
235  case GEN_RID:
236  BIO_printf(out, "Registered ID");
237  i2a_ASN1_OBJECT(out, gen->d.rid);
238  break;
239  }
240  return 1;
241 }
242 
243 static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
244  X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
245 {
246  GENERAL_NAMES *gens = NULL;
247  CONF_VALUE *cnf;
248  int i;
249  if(!(gens = sk_GENERAL_NAME_new_null())) {
251  return NULL;
252  }
253  for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
254  cnf = sk_CONF_VALUE_value(nval, i);
255  if(!name_cmp(cnf->name, "issuer") && cnf->value &&
256  !strcmp(cnf->value, "copy")) {
257  if(!copy_issuer(ctx, gens)) goto err;
258  } else {
259  GENERAL_NAME *gen;
260  if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
261  goto err;
262  sk_GENERAL_NAME_push(gens, gen);
263  }
264  }
265  return gens;
266  err:
267  sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
268  return NULL;
269 }
270 
271 /* Append subject altname of issuer to issuer alt name of subject */
272 
273 static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens)
274 {
275  GENERAL_NAMES *ialt;
276  GENERAL_NAME *gen;
278  int i;
279  if(ctx && (ctx->flags == CTX_TEST)) return 1;
280  if(!ctx || !ctx->issuer_cert) {
282  goto err;
283  }
285  if(i < 0) return 1;
286  if(!(ext = X509_get_ext(ctx->issuer_cert, i)) ||
287  !(ialt = X509V3_EXT_d2i(ext)) ) {
289  goto err;
290  }
291 
292  for(i = 0; i < sk_GENERAL_NAME_num(ialt); i++) {
293  gen = sk_GENERAL_NAME_value(ialt, i);
294  if(!sk_GENERAL_NAME_push(gens, gen)) {
296  goto err;
297  }
298  }
299  sk_GENERAL_NAME_free(ialt);
300 
301  return 1;
302 
303  err:
304  return 0;
305 
306 }
307 
308 static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
309  X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
310 {
311  GENERAL_NAMES *gens = NULL;
312  CONF_VALUE *cnf;
313  int i;
314  if(!(gens = sk_GENERAL_NAME_new_null())) {
316  return NULL;
317  }
318  for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
319  cnf = sk_CONF_VALUE_value(nval, i);
320  if(!name_cmp(cnf->name, "email") && cnf->value &&
321  !strcmp(cnf->value, "copy")) {
322  if(!copy_email(ctx, gens, 0)) goto err;
323  } else if(!name_cmp(cnf->name, "email") && cnf->value &&
324  !strcmp(cnf->value, "move")) {
325  if(!copy_email(ctx, gens, 1)) goto err;
326  } else {
327  GENERAL_NAME *gen;
328  if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
329  goto err;
330  sk_GENERAL_NAME_push(gens, gen);
331  }
332  }
333  return gens;
334  err:
335  sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
336  return NULL;
337 }
338 
339 /* Copy any email addresses in a certificate or request to
340  * GENERAL_NAMES
341  */
342 
343 static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p)
344 {
345  X509_NAME *nm;
346  ASN1_IA5STRING *email = NULL;
347  X509_NAME_ENTRY *ne;
348  GENERAL_NAME *gen = NULL;
349  int i;
350  if(ctx != NULL && ctx->flags == CTX_TEST)
351  return 1;
352  if(!ctx || (!ctx->subject_cert && !ctx->subject_req)) {
354  goto err;
355  }
356  /* Find the subject name */
357  if(ctx->subject_cert) nm = X509_get_subject_name(ctx->subject_cert);
358  else nm = X509_REQ_get_subject_name(ctx->subject_req);
359 
360  /* Now add any email address(es) to STACK */
361  i = -1;
362  while((i = X509_NAME_get_index_by_NID(nm,
363  NID_pkcs9_emailAddress, i)) >= 0) {
364  ne = X509_NAME_get_entry(nm, i);
366  if (move_p)
367  {
368  X509_NAME_delete_entry(nm, i);
369  X509_NAME_ENTRY_free(ne);
370  i--;
371  }
372  if(!email || !(gen = GENERAL_NAME_new())) {
374  goto err;
375  }
376  gen->d.ia5 = email;
377  email = NULL;
378  gen->type = GEN_EMAIL;
379  if(!sk_GENERAL_NAME_push(gens, gen)) {
381  goto err;
382  }
383  gen = NULL;
384  }
385 
386 
387  return 1;
388 
389  err:
390  GENERAL_NAME_free(gen);
391  M_ASN1_IA5STRING_free(email);
392  return 0;
393 
394 }
395 
396 GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
397  X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
398 {
399  GENERAL_NAME *gen;
400  GENERAL_NAMES *gens = NULL;
401  CONF_VALUE *cnf;
402  int i;
403  if(!(gens = sk_GENERAL_NAME_new_null())) {
405  return NULL;
406  }
407  for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
408  cnf = sk_CONF_VALUE_value(nval, i);
409  if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) goto err;
410  sk_GENERAL_NAME_push(gens, gen);
411  }
412  return gens;
413  err:
414  sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
415  return NULL;
416 }
417 
419  CONF_VALUE *cnf)
420  {
421  return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
422  }
423 
425  const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
426  int gen_type, char *value, int is_nc)
427  {
428  char is_string = 0;
429  GENERAL_NAME *gen = NULL;
430 
431  if(!value)
432  {
434  return NULL;
435  }
436 
437  if (out)
438  gen = out;
439  else
440  {
441  gen = GENERAL_NAME_new();
442  if(gen == NULL)
443  {
445  return NULL;
446  }
447  }
448 
449  switch (gen_type)
450  {
451  case GEN_URI:
452  case GEN_EMAIL:
453  case GEN_DNS:
454  is_string = 1;
455  break;
456 
457  case GEN_RID:
458  {
459  ASN1_OBJECT *obj;
460  if(!(obj = OBJ_txt2obj(value,0)))
461  {
463  ERR_add_error_data(2, "value=", value);
464  goto err;
465  }
466  gen->d.rid = obj;
467  }
468  break;
469 
470  case GEN_IPADD:
471  if (is_nc)
472  gen->d.ip = a2i_IPADDRESS_NC(value);
473  else
474  gen->d.ip = a2i_IPADDRESS(value);
475  if(gen->d.ip == NULL)
476  {
478  ERR_add_error_data(2, "value=", value);
479  goto err;
480  }
481  break;
482 
483  case GEN_DIRNAME:
484  if (!do_dirname(gen, value, ctx))
485  {
487  goto err;
488  }
489  break;
490 
491  case GEN_OTHERNAME:
492  if (!do_othername(gen, value, ctx))
493  {
495  goto err;
496  }
497  break;
498  default:
500  goto err;
501  }
502 
503  if(is_string)
504  {
505  if(!(gen->d.ia5 = M_ASN1_IA5STRING_new()) ||
506  !ASN1_STRING_set(gen->d.ia5, (unsigned char*)value,
507  strlen(value)))
508  {
510  goto err;
511  }
512  }
513 
514  gen->type = gen_type;
515 
516  return gen;
517 
518  err:
519  if (!out)
520  GENERAL_NAME_free(gen);
521  return NULL;
522  }
523 
525  const X509V3_EXT_METHOD *method,
526  X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc)
527  {
528  int type;
529 
530  char *name, *value;
531 
532  name = cnf->name;
533  value = cnf->value;
534 
535  if(!value)
536  {
538  return NULL;
539  }
540 
541  if(!name_cmp(name, "email"))
542  type = GEN_EMAIL;
543  else if(!name_cmp(name, "URI"))
544  type = GEN_URI;
545  else if(!name_cmp(name, "DNS"))
546  type = GEN_DNS;
547  else if(!name_cmp(name, "RID"))
548  type = GEN_RID;
549  else if(!name_cmp(name, "IP"))
550  type = GEN_IPADD;
551  else if(!name_cmp(name, "dirName"))
552  type = GEN_DIRNAME;
553  else if(!name_cmp(name, "otherName"))
554  type = GEN_OTHERNAME;
555  else
556  {
558  ERR_add_error_data(2, "name=", name);
559  return NULL;
560  }
561 
562  return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc);
563 
564  }
565 
566 static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
567  {
568  char *objtmp = NULL, *p;
569  int objlen;
570  if (!(p = strchr(value, ';')))
571  return 0;
572  if (!(gen->d.otherName = OTHERNAME_new()))
573  return 0;
574  /* Free this up because we will overwrite it.
575  * no need to free type_id because it is static
576  */
577  ASN1_TYPE_free(gen->d.otherName->value);
578  if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)))
579  return 0;
580  objlen = p - value;
581  objtmp = OPENSSL_malloc(objlen + 1);
582  strncpy(objtmp, value, objlen);
583  objtmp[objlen] = 0;
584  gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
585  OPENSSL_free(objtmp);
586  if (!gen->d.otherName->type_id)
587  return 0;
588  return 1;
589  }
590 
591 static int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
592  {
593  int ret;
594  STACK_OF(CONF_VALUE) *sk;
595  X509_NAME *nm;
596  if (!(nm = X509_NAME_new()))
597  return 0;
598  sk = X509V3_get_section(ctx, value);
599  if (!sk)
600  {
602  ERR_add_error_data(2, "section=", value);
603  X509_NAME_free(nm);
604  return 0;
605  }
606  /* FIXME: should allow other character types... */
607  ret = X509V3_NAME_from_section(nm, sk, MBSTRING_ASC);
608  if (!ret)
609  X509_NAME_free(nm);
610  gen->d.dirn = nm;
611  X509V3_section_free(ctx, sk);
612 
613  return ret;
614  }