2 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
5 /* ====================================================================
6 * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
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
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/)"
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.
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.
34 * 6. Redistributions of any form whatsoever must retain the following
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
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 * ====================================================================
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).
58 /* extension creation utilities */
70 static int v3_check_critical(char **value
);
71 static int v3_check_generic(char **value
);
72 static X509_EXTENSION
*do_ext_conf(LHASH
*conf
, X509V3_CTX
*ctx
, int ext_nid
, int crit
, char *value
);
73 static X509_EXTENSION
*v3_generic_extension(char *ext
, char *value
, int crit
, int type
);
75 static int v3_check_critical();
76 static int v3_check_generic();
77 static X509_EXTENSION
*do_ext_conf();
78 static X509V3_EXTENSION
*v3_generic_extension();
81 X509_EXTENSION
*X509V3_EXT_conf(conf
, ctx
, name
, value
)
82 LHASH
*conf
; /* Config file */
84 char *name
; /* Name */
85 char *value
; /* Value */
90 crit
= v3_check_critical(&value
);
91 if((ext_type
= v3_check_generic(&value
)))
92 return v3_generic_extension(name
, value
, crit
, ext_type
);
93 ret
= do_ext_conf(conf
, ctx
, OBJ_sn2nid(name
), crit
, value
);
95 X509V3err(X509V3_F_X509V3_EXT_CONF
,X509V3_R_ERROR_IN_EXTENSION
);
96 ERR_add_error_data(4,"name=", name
, ", value=", value
);
101 X509_EXTENSION
*X509V3_EXT_conf_nid(conf
, ctx
, ext_nid
, value
)
102 LHASH
*conf
; /* Config file */
105 char *value
; /* Value */
109 crit
= v3_check_critical(&value
);
110 if((ext_type
= v3_check_generic(&value
)))
111 return v3_generic_extension(OBJ_nid2sn(ext_nid
),
112 value
, crit
, ext_type
);
113 return do_ext_conf(conf
, ctx
, ext_nid
, crit
, value
);
116 static X509_EXTENSION
*do_ext_conf(conf
, ctx
, ext_nid
, crit
, value
)
117 LHASH
*conf
; /* Config file */
121 char *value
; /* Value */
123 X509_EXTENSION
*ext
= NULL
;
124 X509V3_EXT_METHOD
*method
;
129 ASN1_OCTET_STRING
*ext_oct
;
130 if(ext_nid
== NID_undef
) {
131 X509V3err(X509V3_F_DO_EXT_CONF
,X509V3_R_UNKNOWN_EXTENSION_NAME
);
134 if(!(method
= X509V3_EXT_get_nid(ext_nid
))) {
135 X509V3err(X509V3_F_DO_EXT_CONF
,X509V3_R_UNKNOWN_EXTENSION
);
138 /* Now get internal extension representation based on type */
140 if(*value
== '@') nval
= CONF_get_section(conf
, value
+ 1);
141 else nval
= X509V3_parse_list(value
);
143 X509V3err(X509V3_F_X509V3_EXT_CONF
,X509V3_R_INVALID_EXTENSION_STRING
);
144 ERR_add_error_data(4, "name=", OBJ_nid2sn(ext_nid
), ",section=", value
);
147 ext_struc
= method
->v2i(method
, ctx
, nval
);
148 if(*value
!= '@') sk_pop_free(nval
, X509V3_conf_free
);
149 if(!ext_struc
) return NULL
;
150 } else if(method
->s2i
) {
151 if(!(ext_struc
= method
->s2i(method
, ctx
, value
))) return NULL
;
153 X509V3err(X509V3_F_X509V3_EXT_CONF
,X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED
);
154 ERR_add_error_data(2, "name=", OBJ_nid2sn(ext_nid
));
158 /* We've now got the internal representation: convert to DER */
159 ext_len
= method
->i2d(ext_struc
, NULL
);
160 ext_der
= Malloc(ext_len
);
162 method
->i2d(ext_struc
, &p
);
163 method
->ext_free(ext_struc
);
164 ext_oct
= ASN1_OCTET_STRING_new();
165 ext_oct
->data
= ext_der
;
166 ext_oct
->length
= ext_len
;
168 ext
= X509_EXTENSION_create_by_NID(NULL
, ext_nid
, crit
, ext_oct
);
169 ASN1_OCTET_STRING_free(ext_oct
);
175 /* Check the extension string for critical flag */
176 static int v3_check_critical(value
)
180 if((strlen(p
) < 9) || strncmp(p
, "critical,", 9)) return 0;
182 while(isspace(*p
)) p
++;
187 /* Check extension string for generic extension and return the type */
188 static int v3_check_generic(value
)
192 if((strlen(p
) < 4) || strncmp(p
, "RAW:,", 4)) return 0;
194 while(isspace(*p
)) p
++;
199 /* Create a generic extension: for now just handle RAW type */
200 static X509_EXTENSION
*v3_generic_extension(ext
, value
, crit
, type
)
206 unsigned char *ext_der
=NULL
;
208 ASN1_OBJECT
*obj
=NULL
;
209 ASN1_OCTET_STRING
*oct
=NULL
;
210 X509_EXTENSION
*extension
=NULL
;
211 if(!(obj
= OBJ_txt2obj(ext
, 0))) {
212 X509V3err(X509V3_F_V3_GENERIC_EXTENSION
,X509V3_R_EXTENSION_NAME_ERROR
);
213 ERR_add_error_data(2, "name=", ext
);
217 if(!(ext_der
= string_to_hex(value
, &ext_len
))) {
218 X509V3err(X509V3_F_V3_GENERIC_EXTENSION
,X509V3_R_EXTENSION_VALUE_ERROR
);
219 ERR_add_error_data(2, "value=", value
);
223 if(!(oct
= ASN1_OCTET_STRING_new())) {
224 X509V3err(X509V3_F_V3_GENERIC_EXTENSION
,ERR_R_MALLOC_FAILURE
);
229 oct
->length
= ext_len
;
232 extension
= X509_EXTENSION_create_by_OBJ(NULL
, obj
, crit
, oct
);
235 ASN1_OBJECT_free(obj
);
236 ASN1_OCTET_STRING_free(oct
);
237 if(ext_der
) Free(ext_der
);
242 /* This is the main function: add a bunch of extensions based on a config file
246 int X509V3_EXT_add_conf(conf
, ctx
, section
, cert
)
256 if(!(nval
= CONF_get_section(conf
, section
))) return 0;
257 for(i
= 0; i
< sk_num(nval
); i
++) {
258 val
= (CONF_VALUE
*)sk_value(nval
, i
);
259 if(!(ext
= X509V3_EXT_conf(conf
, ctx
, val
->name
, val
->value
)))
261 if(cert
) X509_add_ext(cert
, ext
, -1);
262 X509_EXTENSION_free(ext
);
267 /* Same as above but for a CRL */
269 int X509V3_EXT_CRL_add_conf(conf
, ctx
, section
, crl
)
279 if(!(nval
= CONF_get_section(conf
, section
))) return 0;
280 for(i
= 0; i
< sk_num(nval
); i
++) {
281 val
= (CONF_VALUE
*)sk_value(nval
, i
);
282 if(!(ext
= X509V3_EXT_conf(conf
, ctx
, val
->name
, val
->value
)))
284 if(crl
) X509_CRL_add_ext(crl
, ext
, -1);
285 X509_EXTENSION_free(ext
);
290 /* Just check syntax of config file as far as possible */
291 int X509V3_EXT_check_conf(conf
, section
)
295 static X509V3_CTX ctx_tst
= { CTX_TEST
, NULL
, NULL
, NULL
, NULL
};
296 return X509V3_EXT_add_conf(conf
, &ctx_tst
, section
, NULL
);
299 /* Config database functions */
301 char * X509V3_get_string(ctx
, name
, section
)
306 if(ctx
->db_meth
->get_string
)
307 return ctx
->db_meth
->get_string(ctx
->db
, name
, section
);
311 STACK
* X509V3_get_section(ctx
, section
)
315 if(ctx
->db_meth
->get_section
)
316 return ctx
->db_meth
->get_section(ctx
->db
, section
);
320 void X509V3_free_string(ctx
, str
)
324 if(ctx
->db_meth
->free_string
)
325 return ctx
->db_meth
->free_string(ctx
->db
, str
);
328 void X509V3_free_section(ctx
, section
)
332 if(ctx
->db_meth
->free_section
)
333 return ctx
->db_meth
->free_section(ctx
->db
, section
);
336 static char *conf_lhash_get_string(db
, section
, value
)
341 return CONF_get_string(db
, section
, value
);
344 static STACK
*conf_lhash_get_section(db
, section
)
348 return CONF_get_section(db
, section
);
351 static X509V3_CONF_METHOD conf_lhash_method
= {
352 conf_lhash_get_string
,
353 conf_lhash_get_section
,
358 void X509V3_set_conf_lhash(ctx
, lhash
)
362 ctx
->db_meth
= &conf_lhash_method
;
366 void X509V3_set_ctx(ctx
, issuer
, subj
, req
, crl
, flags
)
374 ctx
->issuer_cert
= issuer
;
375 ctx
->subject_cert
= subj
;
377 ctx
->subject_req
= req
;