]>
Commit | Line | Data |
---|---|---|
0f113f3e | 1 | /* |
454afd98 | 2 | * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved. |
9aeaf1b4 | 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 | |
9aeaf1b4 | 8 | */ |
d2e9e320 | 9 | |
388ff0b0 | 10 | /* extension creation utilities */ |
9aeaf1b4 | 11 | |
e527ba09 | 12 | #include <stdio.h> |
25f2138b | 13 | #include "crypto/ctype.h" |
b39fc560 | 14 | #include "internal/cryptlib.h" |
ec577822 BM |
15 | #include <openssl/conf.h> |
16 | #include <openssl/x509.h> | |
25f2138b | 17 | #include "crypto/x509.h" |
ec577822 | 18 | #include <openssl/x509v3.h> |
9aeaf1b4 | 19 | |
852c2ed2 RS |
20 | DEFINE_STACK_OF(CONF_VALUE) |
21 | DEFINE_STACK_OF(X509_EXTENSION) | |
22 | ||
34707951 F |
23 | static int v3_check_critical(const char **value); |
24 | static int v3_check_generic(const char **value); | |
0f113f3e | 25 | static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid, |
34707951 F |
26 | int crit, const char *value); |
27 | static X509_EXTENSION *v3_generic_extension(const char *ext, const char *value, | |
0f113f3e MC |
28 | int crit, int type, |
29 | X509V3_CTX *ctx); | |
34707951 F |
30 | static char *conf_lhash_get_string(void *db, const char *section, const char *value); |
31 | static STACK_OF(CONF_VALUE) *conf_lhash_get_section(void *db, const char *section); | |
0f113f3e MC |
32 | static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, |
33 | int ext_nid, int crit, void *ext_struc); | |
34707951 | 34 | static unsigned char *generic_asn1(const char *value, X509V3_CTX *ctx, |
0f113f3e | 35 | long *ext_len); |
b7a26e6d | 36 | /* CONF *conf: Config file */ |
6b691a5c UM |
37 | /* char *name: Name */ |
38 | /* char *value: Value */ | |
34707951 F |
39 | X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, const char *name, |
40 | const char *value) | |
0f113f3e MC |
41 | { |
42 | int crit; | |
43 | int ext_type; | |
44 | X509_EXTENSION *ret; | |
45 | crit = v3_check_critical(&value); | |
46 | if ((ext_type = v3_check_generic(&value))) | |
47 | return v3_generic_extension(name, value, crit, ext_type, ctx); | |
48 | ret = do_ext_nconf(conf, ctx, OBJ_sn2nid(name), crit, value); | |
49 | if (!ret) { | |
50 | X509V3err(X509V3_F_X509V3_EXT_NCONF, X509V3_R_ERROR_IN_EXTENSION); | |
51 | ERR_add_error_data(4, "name=", name, ", value=", value); | |
52 | } | |
53 | return ret; | |
54 | } | |
9aeaf1b4 | 55 | |
b7a26e6d | 56 | /* CONF *conf: Config file */ |
6b691a5c | 57 | /* char *value: Value */ |
b7a26e6d | 58 | X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid, |
34707951 | 59 | const char *value) |
0f113f3e MC |
60 | { |
61 | int crit; | |
62 | int ext_type; | |
63 | crit = v3_check_critical(&value); | |
64 | if ((ext_type = v3_check_generic(&value))) | |
65 | return v3_generic_extension(OBJ_nid2sn(ext_nid), | |
66 | value, crit, ext_type, ctx); | |
67 | return do_ext_nconf(conf, ctx, ext_nid, crit, value); | |
68 | } | |
388ff0b0 | 69 | |
b7a26e6d | 70 | /* CONF *conf: Config file */ |
6b691a5c | 71 | /* char *value: Value */ |
b7a26e6d | 72 | static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid, |
34707951 | 73 | int crit, const char *value) |
0f113f3e MC |
74 | { |
75 | const X509V3_EXT_METHOD *method; | |
76 | X509_EXTENSION *ext; | |
77 | STACK_OF(CONF_VALUE) *nval; | |
78 | void *ext_struc; | |
75ebbd9a | 79 | |
0f113f3e MC |
80 | if (ext_nid == NID_undef) { |
81 | X509V3err(X509V3_F_DO_EXT_NCONF, X509V3_R_UNKNOWN_EXTENSION_NAME); | |
82 | return NULL; | |
83 | } | |
75ebbd9a | 84 | if ((method = X509V3_EXT_get_nid(ext_nid)) == NULL) { |
0f113f3e MC |
85 | X509V3err(X509V3_F_DO_EXT_NCONF, X509V3_R_UNKNOWN_EXTENSION); |
86 | return NULL; | |
87 | } | |
88 | /* Now get internal extension representation based on type */ | |
89 | if (method->v2i) { | |
90 | if (*value == '@') | |
91 | nval = NCONF_get_section(conf, value + 1); | |
92 | else | |
93 | nval = X509V3_parse_list(value); | |
8605abf1 | 94 | if (nval == NULL || sk_CONF_VALUE_num(nval) <= 0) { |
0f113f3e MC |
95 | X509V3err(X509V3_F_DO_EXT_NCONF, |
96 | X509V3_R_INVALID_EXTENSION_STRING); | |
97 | ERR_add_error_data(4, "name=", OBJ_nid2sn(ext_nid), ",section=", | |
98 | value); | |
8605abf1 | 99 | if (*value != '@') |
e125c12f | 100 | sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); |
0f113f3e MC |
101 | return NULL; |
102 | } | |
103 | ext_struc = method->v2i(method, ctx, nval); | |
104 | if (*value != '@') | |
105 | sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); | |
106 | if (!ext_struc) | |
107 | return NULL; | |
108 | } else if (method->s2i) { | |
75ebbd9a | 109 | if ((ext_struc = method->s2i(method, ctx, value)) == NULL) |
0f113f3e MC |
110 | return NULL; |
111 | } else if (method->r2i) { | |
112 | if (!ctx->db || !ctx->db_meth) { | |
113 | X509V3err(X509V3_F_DO_EXT_NCONF, X509V3_R_NO_CONFIG_DATABASE); | |
114 | return NULL; | |
115 | } | |
75ebbd9a | 116 | if ((ext_struc = method->r2i(method, ctx, value)) == NULL) |
0f113f3e MC |
117 | return NULL; |
118 | } else { | |
119 | X509V3err(X509V3_F_DO_EXT_NCONF, | |
120 | X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED); | |
121 | ERR_add_error_data(2, "name=", OBJ_nid2sn(ext_nid)); | |
122 | return NULL; | |
123 | } | |
124 | ||
125 | ext = do_ext_i2d(method, ext_nid, crit, ext_struc); | |
126 | if (method->it) | |
127 | ASN1_item_free(ext_struc, ASN1_ITEM_ptr(method->it)); | |
128 | else | |
129 | method->ext_free(ext_struc); | |
130 | return ext; | |
131 | ||
132 | } | |
133 | ||
134 | static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, | |
135 | int ext_nid, int crit, void *ext_struc) | |
136 | { | |
137 | unsigned char *ext_der = NULL; | |
138 | int ext_len; | |
139 | ASN1_OCTET_STRING *ext_oct = NULL; | |
140 | X509_EXTENSION *ext; | |
141 | /* Convert internal representation to DER */ | |
142 | if (method->it) { | |
143 | ext_der = NULL; | |
144 | ext_len = | |
145 | ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it)); | |
146 | if (ext_len < 0) | |
147 | goto merr; | |
148 | } else { | |
149 | unsigned char *p; | |
75ebbd9a | 150 | |
0f113f3e | 151 | ext_len = method->i2d(ext_struc, NULL); |
75ebbd9a | 152 | if ((ext_der = OPENSSL_malloc(ext_len)) == NULL) |
0f113f3e MC |
153 | goto merr; |
154 | p = ext_der; | |
155 | method->i2d(ext_struc, &p); | |
156 | } | |
75ebbd9a | 157 | if ((ext_oct = ASN1_OCTET_STRING_new()) == NULL) |
0f113f3e MC |
158 | goto merr; |
159 | ext_oct->data = ext_der; | |
160 | ext_der = NULL; | |
161 | ext_oct->length = ext_len; | |
162 | ||
163 | ext = X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct); | |
164 | if (!ext) | |
165 | goto merr; | |
f422a514 | 166 | ASN1_OCTET_STRING_free(ext_oct); |
0f113f3e MC |
167 | |
168 | return ext; | |
169 | ||
170 | merr: | |
171 | X509V3err(X509V3_F_DO_EXT_I2D, ERR_R_MALLOC_FAILURE); | |
b548a1f1 | 172 | OPENSSL_free(ext_der); |
0dfb9398 | 173 | ASN1_OCTET_STRING_free(ext_oct); |
0f113f3e MC |
174 | return NULL; |
175 | ||
176 | } | |
c8b41850 DSH |
177 | |
178 | /* Given an internal structure, nid and critical flag create an extension */ | |
179 | ||
180 | X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc) | |
0f113f3e MC |
181 | { |
182 | const X509V3_EXT_METHOD *method; | |
75ebbd9a RS |
183 | |
184 | if ((method = X509V3_EXT_get_nid(ext_nid)) == NULL) { | |
0f113f3e MC |
185 | X509V3err(X509V3_F_X509V3_EXT_I2D, X509V3_R_UNKNOWN_EXTENSION); |
186 | return NULL; | |
187 | } | |
188 | return do_ext_i2d(method, ext_nid, crit, ext_struc); | |
9aeaf1b4 DSH |
189 | } |
190 | ||
388ff0b0 | 191 | /* Check the extension string for critical flag */ |
34707951 | 192 | static int v3_check_critical(const char **value) |
388ff0b0 | 193 | { |
34707951 | 194 | const char *p = *value; |
0f113f3e MC |
195 | if ((strlen(p) < 9) || strncmp(p, "critical,", 9)) |
196 | return 0; | |
197 | p += 9; | |
a1df06b3 | 198 | while (ossl_isspace(*p)) |
0f113f3e MC |
199 | p++; |
200 | *value = p; | |
201 | return 1; | |
388ff0b0 DSH |
202 | } |
203 | ||
204 | /* Check extension string for generic extension and return the type */ | |
34707951 | 205 | static int v3_check_generic(const char **value) |
388ff0b0 | 206 | { |
0f113f3e | 207 | int gen_type = 0; |
34707951 | 208 | const char *p = *value; |
86885c28 | 209 | if ((strlen(p) >= 4) && strncmp(p, "DER:", 4) == 0) { |
0f113f3e MC |
210 | p += 4; |
211 | gen_type = 1; | |
86885c28 | 212 | } else if ((strlen(p) >= 5) && strncmp(p, "ASN1:", 5) == 0) { |
0f113f3e MC |
213 | p += 5; |
214 | gen_type = 2; | |
215 | } else | |
216 | return 0; | |
217 | ||
a1df06b3 | 218 | while (ossl_isspace(*p)) |
0f113f3e MC |
219 | p++; |
220 | *value = p; | |
221 | return gen_type; | |
388ff0b0 DSH |
222 | } |
223 | ||
c79b16e1 | 224 | /* Create a generic extension: for now just handle DER type */ |
34707951 | 225 | static X509_EXTENSION *v3_generic_extension(const char *ext, const char *value, |
0f113f3e MC |
226 | int crit, int gen_type, |
227 | X509V3_CTX *ctx) | |
228 | { | |
229 | unsigned char *ext_der = NULL; | |
4c9b0a03 | 230 | long ext_len = 0; |
0f113f3e MC |
231 | ASN1_OBJECT *obj = NULL; |
232 | ASN1_OCTET_STRING *oct = NULL; | |
233 | X509_EXTENSION *extension = NULL; | |
75ebbd9a RS |
234 | |
235 | if ((obj = OBJ_txt2obj(ext, 0)) == NULL) { | |
0f113f3e MC |
236 | X509V3err(X509V3_F_V3_GENERIC_EXTENSION, |
237 | X509V3_R_EXTENSION_NAME_ERROR); | |
238 | ERR_add_error_data(2, "name=", ext); | |
239 | goto err; | |
240 | } | |
241 | ||
242 | if (gen_type == 1) | |
14f051a0 | 243 | ext_der = OPENSSL_hexstr2buf(value, &ext_len); |
0f113f3e MC |
244 | else if (gen_type == 2) |
245 | ext_der = generic_asn1(value, ctx, &ext_len); | |
246 | ||
247 | if (ext_der == NULL) { | |
248 | X509V3err(X509V3_F_V3_GENERIC_EXTENSION, | |
249 | X509V3_R_EXTENSION_VALUE_ERROR); | |
250 | ERR_add_error_data(2, "value=", value); | |
251 | goto err; | |
252 | } | |
253 | ||
75ebbd9a | 254 | if ((oct = ASN1_OCTET_STRING_new()) == NULL) { |
0f113f3e MC |
255 | X509V3err(X509V3_F_V3_GENERIC_EXTENSION, ERR_R_MALLOC_FAILURE); |
256 | goto err; | |
257 | } | |
258 | ||
259 | oct->data = ext_der; | |
260 | oct->length = ext_len; | |
261 | ext_der = NULL; | |
262 | ||
263 | extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct); | |
264 | ||
265 | err: | |
266 | ASN1_OBJECT_free(obj); | |
f422a514 | 267 | ASN1_OCTET_STRING_free(oct); |
b548a1f1 | 268 | OPENSSL_free(ext_der); |
0f113f3e MC |
269 | return extension; |
270 | ||
271 | } | |
272 | ||
34707951 | 273 | static unsigned char *generic_asn1(const char *value, X509V3_CTX *ctx, |
0f113f3e MC |
274 | long *ext_len) |
275 | { | |
276 | ASN1_TYPE *typ; | |
277 | unsigned char *ext_der = NULL; | |
278 | typ = ASN1_generate_v3(value, ctx); | |
279 | if (typ == NULL) | |
280 | return NULL; | |
281 | *ext_len = i2d_ASN1_TYPE(typ, &ext_der); | |
282 | ASN1_TYPE_free(typ); | |
283 | return ext_der; | |
284 | } | |
388ff0b0 | 285 | |
ebaa2cf5 | 286 | static void delete_ext(STACK_OF(X509_EXTENSION) *sk, X509_EXTENSION *dext) |
0f113f3e MC |
287 | { |
288 | int idx; | |
289 | ASN1_OBJECT *obj; | |
290 | obj = X509_EXTENSION_get_object(dext); | |
291 | while ((idx = X509v3_get_ext_by_OBJ(sk, obj, -1)) >= 0) { | |
292 | X509_EXTENSION *tmpext = X509v3_get_ext(sk, idx); | |
293 | X509v3_delete_ext(sk, idx); | |
294 | X509_EXTENSION_free(tmpext); | |
295 | } | |
296 | } | |
9aeaf1b4 | 297 | |
0f113f3e MC |
298 | /* |
299 | * This is the main function: add a bunch of extensions based on a config | |
300 | * file section to an extension STACK. | |
301 | */ | |
b7a26e6d | 302 | |
34707951 | 303 | int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, const char *section, |
0f113f3e MC |
304 | STACK_OF(X509_EXTENSION) **sk) |
305 | { | |
306 | X509_EXTENSION *ext; | |
307 | STACK_OF(CONF_VALUE) *nval; | |
308 | CONF_VALUE *val; | |
309 | int i; | |
75ebbd9a RS |
310 | |
311 | if ((nval = NCONF_get_section(conf, section)) == NULL) | |
0f113f3e MC |
312 | return 0; |
313 | for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { | |
314 | val = sk_CONF_VALUE_value(nval, i); | |
75ebbd9a | 315 | if ((ext = X509V3_EXT_nconf(conf, ctx, val->name, val->value)) == NULL) |
0f113f3e MC |
316 | return 0; |
317 | if (ctx->flags == X509V3_CTX_REPLACE) | |
318 | delete_ext(*sk, ext); | |
abcf2411 PK |
319 | if (sk != NULL) { |
320 | if (X509v3_add_ext(sk, ext, -1) == NULL) { | |
321 | X509_EXTENSION_free(ext); | |
322 | return 0; | |
323 | } | |
324 | } | |
0f113f3e MC |
325 | X509_EXTENSION_free(ext); |
326 | } | |
327 | return 1; | |
328 | } | |
329 | ||
330 | /* | |
331 | * Convenience functions to add extensions to a certificate, CRL and request | |
332 | */ | |
b7a26e6d | 333 | |
34707951 | 334 | int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section, |
0f113f3e MC |
335 | X509 *cert) |
336 | { | |
337 | STACK_OF(X509_EXTENSION) **sk = NULL; | |
338 | if (cert) | |
5cf6abd8 | 339 | sk = &cert->cert_info.extensions; |
0f113f3e MC |
340 | return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); |
341 | } | |
9aeaf1b4 | 342 | |
1756d405 DSH |
343 | /* Same as above but for a CRL */ |
344 | ||
34707951 | 345 | int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section, |
0f113f3e MC |
346 | X509_CRL *crl) |
347 | { | |
348 | STACK_OF(X509_EXTENSION) **sk = NULL; | |
349 | if (crl) | |
7aef39a7 | 350 | sk = &crl->crl.extensions; |
0f113f3e MC |
351 | return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); |
352 | } | |
1756d405 | 353 | |
c79b16e1 DSH |
354 | /* Add extensions to certificate request */ |
355 | ||
34707951 | 356 | int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section, |
0f113f3e MC |
357 | X509_REQ *req) |
358 | { | |
359 | STACK_OF(X509_EXTENSION) *extlist = NULL, **sk = NULL; | |
360 | int i; | |
361 | if (req) | |
362 | sk = &extlist; | |
363 | i = X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); | |
364 | if (!i || !sk) | |
365 | return i; | |
366 | i = X509_REQ_add_extensions(req, extlist); | |
367 | sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free); | |
368 | return i; | |
369 | } | |
c79b16e1 | 370 | |
1d48dd00 DSH |
371 | /* Config database functions */ |
372 | ||
c8f717fe | 373 | char *X509V3_get_string(X509V3_CTX *ctx, const char *name, const char *section) |
0f113f3e MC |
374 | { |
375 | if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_string) { | |
376 | X509V3err(X509V3_F_X509V3_GET_STRING, X509V3_R_OPERATION_NOT_DEFINED); | |
377 | return NULL; | |
378 | } | |
379 | if (ctx->db_meth->get_string) | |
380 | return ctx->db_meth->get_string(ctx->db, name, section); | |
381 | return NULL; | |
382 | } | |
383 | ||
c8f717fe | 384 | STACK_OF(CONF_VALUE) *X509V3_get_section(X509V3_CTX *ctx, const char *section) |
0f113f3e MC |
385 | { |
386 | if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_section) { | |
387 | X509V3err(X509V3_F_X509V3_GET_SECTION, | |
388 | X509V3_R_OPERATION_NOT_DEFINED); | |
389 | return NULL; | |
390 | } | |
391 | if (ctx->db_meth->get_section) | |
392 | return ctx->db_meth->get_section(ctx->db, section); | |
393 | return NULL; | |
394 | } | |
1d48dd00 | 395 | |
6b691a5c | 396 | void X509V3_string_free(X509V3_CTX *ctx, char *str) |
0f113f3e MC |
397 | { |
398 | if (!str) | |
399 | return; | |
400 | if (ctx->db_meth->free_string) | |
401 | ctx->db_meth->free_string(ctx->db, str); | |
402 | } | |
1d48dd00 | 403 | |
ba404b5e | 404 | void X509V3_section_free(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section) |
0f113f3e MC |
405 | { |
406 | if (!section) | |
407 | return; | |
408 | if (ctx->db_meth->free_section) | |
409 | ctx->db_meth->free_section(ctx->db, section); | |
410 | } | |
b7a26e6d | 411 | |
34707951 | 412 | static char *nconf_get_string(void *db, const char *section, const char *value) |
0f113f3e MC |
413 | { |
414 | return NCONF_get_string(db, section, value); | |
415 | } | |
b7a26e6d | 416 | |
34707951 | 417 | static STACK_OF(CONF_VALUE) *nconf_get_section(void *db, const char *section) |
0f113f3e MC |
418 | { |
419 | return NCONF_get_section(db, section); | |
420 | } | |
b7a26e6d DSH |
421 | |
422 | static X509V3_CONF_METHOD nconf_method = { | |
0f113f3e MC |
423 | nconf_get_string, |
424 | nconf_get_section, | |
425 | NULL, | |
426 | NULL | |
b7a26e6d DSH |
427 | }; |
428 | ||
429 | void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf) | |
0f113f3e MC |
430 | { |
431 | ctx->db_meth = &nconf_method; | |
432 | ctx->db = conf; | |
433 | } | |
b7a26e6d DSH |
434 | |
435 | void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subj, X509_REQ *req, | |
0f113f3e MC |
436 | X509_CRL *crl, int flags) |
437 | { | |
438 | ctx->issuer_cert = issuer; | |
439 | ctx->subject_cert = subj; | |
440 | ctx->crl = crl; | |
441 | ctx->subject_req = req; | |
442 | ctx->flags = flags; | |
443 | } | |
b7a26e6d DSH |
444 | |
445 | /* Old conf compatibility functions */ | |
446 | ||
3c1d6bbc | 447 | X509_EXTENSION *X509V3_EXT_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, |
34707951 | 448 | const char *name, const char *value) |
0f113f3e MC |
449 | { |
450 | CONF ctmp; | |
451 | CONF_set_nconf(&ctmp, conf); | |
452 | return X509V3_EXT_nconf(&ctmp, ctx, name, value); | |
453 | } | |
b7a26e6d DSH |
454 | |
455 | /* LHASH *conf: Config file */ | |
456 | /* char *value: Value */ | |
0f113f3e | 457 | X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf, |
34707951 | 458 | X509V3_CTX *ctx, int ext_nid, const char *value) |
0f113f3e MC |
459 | { |
460 | CONF ctmp; | |
461 | CONF_set_nconf(&ctmp, conf); | |
462 | return X509V3_EXT_nconf_nid(&ctmp, ctx, ext_nid, value); | |
463 | } | |
1d48dd00 | 464 | |
34707951 | 465 | static char *conf_lhash_get_string(void *db, const char *section, const char *value) |
0f113f3e MC |
466 | { |
467 | return CONF_get_string(db, section, value); | |
468 | } | |
1d48dd00 | 469 | |
34707951 | 470 | static STACK_OF(CONF_VALUE) *conf_lhash_get_section(void *db, const char *section) |
0f113f3e MC |
471 | { |
472 | return CONF_get_section(db, section); | |
473 | } | |
1d48dd00 DSH |
474 | |
475 | static X509V3_CONF_METHOD conf_lhash_method = { | |
0f113f3e MC |
476 | conf_lhash_get_string, |
477 | conf_lhash_get_section, | |
478 | NULL, | |
479 | NULL | |
1d48dd00 DSH |
480 | }; |
481 | ||
3c1d6bbc | 482 | void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH_OF(CONF_VALUE) *lhash) |
0f113f3e MC |
483 | { |
484 | ctx->db_meth = &conf_lhash_method; | |
485 | ctx->db = lhash; | |
486 | } | |
1d48dd00 | 487 | |
3c1d6bbc | 488 | int X509V3_EXT_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, |
34707951 | 489 | const char *section, X509 *cert) |
0f113f3e MC |
490 | { |
491 | CONF ctmp; | |
492 | CONF_set_nconf(&ctmp, conf); | |
493 | return X509V3_EXT_add_nconf(&ctmp, ctx, section, cert); | |
494 | } | |
b7a26e6d DSH |
495 | |
496 | /* Same as above but for a CRL */ | |
497 | ||
3c1d6bbc | 498 | int X509V3_EXT_CRL_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, |
34707951 | 499 | const char *section, X509_CRL *crl) |
0f113f3e MC |
500 | { |
501 | CONF ctmp; | |
502 | CONF_set_nconf(&ctmp, conf); | |
503 | return X509V3_EXT_CRL_add_nconf(&ctmp, ctx, section, crl); | |
504 | } | |
b7a26e6d DSH |
505 | |
506 | /* Add extensions to certificate request */ | |
507 | ||
3c1d6bbc | 508 | int X509V3_EXT_REQ_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, |
34707951 | 509 | const char *section, X509_REQ *req) |
0f113f3e MC |
510 | { |
511 | CONF ctmp; | |
512 | CONF_set_nconf(&ctmp, conf); | |
513 | return X509V3_EXT_REQ_add_nconf(&ctmp, ctx, section, req); | |
514 | } |