sl@0: /* v3_conf.c */ sl@0: /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL sl@0: * project 1999. sl@0: */ sl@0: /* ==================================================================== sl@0: * Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved. sl@0: * sl@0: * Redistribution and use in source and binary forms, with or without sl@0: * modification, are permitted provided that the following conditions sl@0: * are met: sl@0: * sl@0: * 1. Redistributions of source code must retain the above copyright sl@0: * notice, this list of conditions and the following disclaimer. sl@0: * sl@0: * 2. Redistributions in binary form must reproduce the above copyright sl@0: * notice, this list of conditions and the following disclaimer in sl@0: * the documentation and/or other materials provided with the sl@0: * distribution. sl@0: * sl@0: * 3. All advertising materials mentioning features or use of this sl@0: * software must display the following acknowledgment: sl@0: * "This product includes software developed by the OpenSSL Project sl@0: * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" sl@0: * sl@0: * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to sl@0: * endorse or promote products derived from this software without sl@0: * prior written permission. For written permission, please contact sl@0: * licensing@OpenSSL.org. sl@0: * sl@0: * 5. Products derived from this software may not be called "OpenSSL" sl@0: * nor may "OpenSSL" appear in their names without prior written sl@0: * permission of the OpenSSL Project. sl@0: * sl@0: * 6. Redistributions of any form whatsoever must retain the following sl@0: * acknowledgment: sl@0: * "This product includes software developed by the OpenSSL Project sl@0: * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" sl@0: * sl@0: * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY sl@0: * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE sl@0: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR sl@0: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR sl@0: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, sl@0: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT sl@0: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; sl@0: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) sl@0: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, sl@0: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) sl@0: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED sl@0: * OF THE POSSIBILITY OF SUCH DAMAGE. sl@0: * ==================================================================== sl@0: * sl@0: * This product includes cryptographic software written by Eric Young sl@0: * (eay@cryptsoft.com). This product includes software written by Tim sl@0: * Hudson (tjh@cryptsoft.com). sl@0: * sl@0: */ sl@0: /* sl@0: © Portions copyright (c) 2006 Nokia Corporation. All rights reserved. sl@0: */ sl@0: /* extension creation utilities */ sl@0: sl@0: sl@0: sl@0: #include sl@0: #include sl@0: #include "cryptlib.h" sl@0: #include sl@0: #include sl@0: #include sl@0: #if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__))) sl@0: #include "libcrypto_wsd_macros.h" sl@0: #include "libcrypto_wsd.h" sl@0: #endif sl@0: sl@0: static int v3_check_critical(char **value); sl@0: static int v3_check_generic(char **value); sl@0: static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid, int crit, char *value); sl@0: static X509_EXTENSION *v3_generic_extension(const char *ext, char *value, int crit, int type, X509V3_CTX *ctx); sl@0: static char *conf_lhash_get_string(void *db, char *section, char *value); sl@0: static STACK_OF(CONF_VALUE) *conf_lhash_get_section(void *db, char *section); sl@0: static X509_EXTENSION *do_ext_i2d(X509V3_EXT_METHOD *method, int ext_nid, sl@0: int crit, void *ext_struc); sl@0: static unsigned char *generic_asn1(char *value, X509V3_CTX *ctx, long *ext_len); sl@0: /* CONF *conf: Config file */ sl@0: /* char *name: Name */ sl@0: /* char *value: Value */ sl@0: EXPORT_C X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, char *name, sl@0: char *value) sl@0: { sl@0: int crit; sl@0: int ext_type; sl@0: X509_EXTENSION *ret; sl@0: crit = v3_check_critical(&value); sl@0: if ((ext_type = v3_check_generic(&value))) sl@0: return v3_generic_extension(name, value, crit, ext_type, ctx); sl@0: ret = do_ext_nconf(conf, ctx, OBJ_sn2nid(name), crit, value); sl@0: if (!ret) sl@0: { sl@0: X509V3err(X509V3_F_X509V3_EXT_NCONF,X509V3_R_ERROR_IN_EXTENSION); sl@0: ERR_add_error_data(4,"name=", name, ", value=", value); sl@0: } sl@0: return ret; sl@0: } sl@0: sl@0: /* CONF *conf: Config file */ sl@0: /* char *value: Value */ sl@0: EXPORT_C X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid, sl@0: char *value) sl@0: { sl@0: int crit; sl@0: int ext_type; sl@0: crit = v3_check_critical(&value); sl@0: if ((ext_type = v3_check_generic(&value))) sl@0: return v3_generic_extension(OBJ_nid2sn(ext_nid), sl@0: value, crit, ext_type, ctx); sl@0: return do_ext_nconf(conf, ctx, ext_nid, crit, value); sl@0: } sl@0: sl@0: /* CONF *conf: Config file */ sl@0: /* char *value: Value */ sl@0: static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid, sl@0: int crit, char *value) sl@0: { sl@0: X509V3_EXT_METHOD *method; sl@0: X509_EXTENSION *ext; sl@0: STACK_OF(CONF_VALUE) *nval; sl@0: void *ext_struc; sl@0: if (ext_nid == NID_undef) sl@0: { sl@0: X509V3err(X509V3_F_DO_EXT_NCONF,X509V3_R_UNKNOWN_EXTENSION_NAME); sl@0: return NULL; sl@0: } sl@0: if (!(method = X509V3_EXT_get_nid(ext_nid))) sl@0: { sl@0: X509V3err(X509V3_F_DO_EXT_NCONF,X509V3_R_UNKNOWN_EXTENSION); sl@0: return NULL; sl@0: } sl@0: /* Now get internal extension representation based on type */ sl@0: if (method->v2i) sl@0: { sl@0: if(*value == '@') nval = NCONF_get_section(conf, value + 1); sl@0: else nval = X509V3_parse_list(value); sl@0: if(sk_CONF_VALUE_num(nval) <= 0) sl@0: { sl@0: X509V3err(X509V3_F_DO_EXT_NCONF,X509V3_R_INVALID_EXTENSION_STRING); sl@0: ERR_add_error_data(4, "name=", OBJ_nid2sn(ext_nid), ",section=", value); sl@0: return NULL; sl@0: } sl@0: ext_struc = method->v2i(method, ctx, nval); sl@0: if(*value != '@') sk_CONF_VALUE_pop_free(nval, sl@0: X509V3_conf_free); sl@0: if(!ext_struc) return NULL; sl@0: } sl@0: else if(method->s2i) sl@0: { sl@0: if(!(ext_struc = method->s2i(method, ctx, value))) return NULL; sl@0: } sl@0: else if(method->r2i) sl@0: { sl@0: if(!ctx->db || !ctx->db_meth) sl@0: { sl@0: X509V3err(X509V3_F_DO_EXT_NCONF,X509V3_R_NO_CONFIG_DATABASE); sl@0: return NULL; sl@0: } sl@0: if(!(ext_struc = method->r2i(method, ctx, value))) return NULL; sl@0: } sl@0: else sl@0: { sl@0: X509V3err(X509V3_F_DO_EXT_NCONF,X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED); sl@0: ERR_add_error_data(2, "name=", OBJ_nid2sn(ext_nid)); sl@0: return NULL; sl@0: } sl@0: sl@0: ext = do_ext_i2d(method, ext_nid, crit, ext_struc); sl@0: if(method->it) ASN1_item_free(ext_struc, ASN1_ITEM_ptr(method->it)); sl@0: else method->ext_free(ext_struc); sl@0: return ext; sl@0: sl@0: } sl@0: sl@0: static X509_EXTENSION *do_ext_i2d(X509V3_EXT_METHOD *method, int ext_nid, sl@0: int crit, void *ext_struc) sl@0: { sl@0: unsigned char *ext_der; sl@0: int ext_len; sl@0: ASN1_OCTET_STRING *ext_oct; sl@0: X509_EXTENSION *ext; sl@0: /* Convert internal representation to DER */ sl@0: if (method->it) sl@0: { sl@0: ext_der = NULL; sl@0: ext_len = ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it)); sl@0: if (ext_len < 0) goto merr; sl@0: } sl@0: else sl@0: { sl@0: unsigned char *p; sl@0: ext_len = method->i2d(ext_struc, NULL); sl@0: if(!(ext_der = OPENSSL_malloc(ext_len))) goto merr; sl@0: p = ext_der; sl@0: method->i2d(ext_struc, &p); sl@0: } sl@0: if (!(ext_oct = M_ASN1_OCTET_STRING_new())) goto merr; sl@0: ext_oct->data = ext_der; sl@0: ext_oct->length = ext_len; sl@0: sl@0: ext = X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct); sl@0: if (!ext) goto merr; sl@0: M_ASN1_OCTET_STRING_free(ext_oct); sl@0: sl@0: return ext; sl@0: sl@0: merr: sl@0: X509V3err(X509V3_F_DO_EXT_I2D,ERR_R_MALLOC_FAILURE); sl@0: return NULL; sl@0: sl@0: } sl@0: sl@0: /* Given an internal structure, nid and critical flag create an extension */ sl@0: sl@0: EXPORT_C X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc) sl@0: { sl@0: X509V3_EXT_METHOD *method; sl@0: if (!(method = X509V3_EXT_get_nid(ext_nid))) { sl@0: X509V3err(X509V3_F_X509V3_EXT_I2D,X509V3_R_UNKNOWN_EXTENSION); sl@0: return NULL; sl@0: } sl@0: return do_ext_i2d(method, ext_nid, crit, ext_struc); sl@0: } sl@0: sl@0: /* Check the extension string for critical flag */ sl@0: static int v3_check_critical(char **value) sl@0: { sl@0: char *p = *value; sl@0: if ((strlen(p) < 9) || strncmp(p, "critical,", 9)) return 0; sl@0: p+=9; sl@0: while(isspace((unsigned char)*p)) p++; sl@0: *value = p; sl@0: return 1; sl@0: } sl@0: sl@0: /* Check extension string for generic extension and return the type */ sl@0: static int v3_check_generic(char **value) sl@0: { sl@0: int gen_type = 0; sl@0: char *p = *value; sl@0: if ((strlen(p) >= 4) && !strncmp(p, "DER:", 4)) sl@0: { sl@0: p+=4; sl@0: gen_type = 1; sl@0: } sl@0: else if ((strlen(p) >= 5) && !strncmp(p, "ASN1:", 5)) sl@0: { sl@0: p+=5; sl@0: gen_type = 2; sl@0: } sl@0: else sl@0: return 0; sl@0: sl@0: while (isspace((unsigned char)*p)) p++; sl@0: *value = p; sl@0: return gen_type; sl@0: } sl@0: sl@0: /* Create a generic extension: for now just handle DER type */ sl@0: static X509_EXTENSION *v3_generic_extension(const char *ext, char *value, sl@0: int crit, int gen_type, X509V3_CTX *ctx) sl@0: { sl@0: unsigned char *ext_der=NULL; sl@0: long ext_len; sl@0: ASN1_OBJECT *obj=NULL; sl@0: ASN1_OCTET_STRING *oct=NULL; sl@0: X509_EXTENSION *extension=NULL; sl@0: if (!(obj = OBJ_txt2obj(ext, 0))) sl@0: { sl@0: X509V3err(X509V3_F_V3_GENERIC_EXTENSION,X509V3_R_EXTENSION_NAME_ERROR); sl@0: ERR_add_error_data(2, "name=", ext); sl@0: goto err; sl@0: } sl@0: sl@0: if (gen_type == 1) sl@0: ext_der = string_to_hex(value, &ext_len); sl@0: else if (gen_type == 2) sl@0: ext_der = generic_asn1(value, ctx, &ext_len); sl@0: sl@0: if (ext_der == NULL) sl@0: { sl@0: X509V3err(X509V3_F_V3_GENERIC_EXTENSION,X509V3_R_EXTENSION_VALUE_ERROR); sl@0: ERR_add_error_data(2, "value=", value); sl@0: goto err; sl@0: } sl@0: sl@0: if (!(oct = M_ASN1_OCTET_STRING_new())) sl@0: { sl@0: X509V3err(X509V3_F_V3_GENERIC_EXTENSION,ERR_R_MALLOC_FAILURE); sl@0: goto err; sl@0: } sl@0: sl@0: oct->data = ext_der; sl@0: oct->length = ext_len; sl@0: ext_der = NULL; sl@0: sl@0: extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct); sl@0: sl@0: err: sl@0: ASN1_OBJECT_free(obj); sl@0: M_ASN1_OCTET_STRING_free(oct); sl@0: if(ext_der) OPENSSL_free(ext_der); sl@0: return extension; sl@0: sl@0: } sl@0: sl@0: static unsigned char *generic_asn1(char *value, X509V3_CTX *ctx, long *ext_len) sl@0: { sl@0: ASN1_TYPE *typ; sl@0: unsigned char *ext_der = NULL; sl@0: typ = ASN1_generate_v3(value, ctx); sl@0: if (typ == NULL) sl@0: return NULL; sl@0: *ext_len = i2d_ASN1_TYPE(typ, &ext_der); sl@0: ASN1_TYPE_free(typ); sl@0: return ext_der; sl@0: } sl@0: sl@0: /* This is the main function: add a bunch of extensions based on a config file sl@0: * section to an extension STACK. sl@0: */ sl@0: sl@0: sl@0: EXPORT_C int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, char *section, sl@0: STACK_OF(X509_EXTENSION) **sk) sl@0: { sl@0: X509_EXTENSION *ext; sl@0: STACK_OF(CONF_VALUE) *nval; sl@0: CONF_VALUE *val; sl@0: int i; sl@0: if (!(nval = NCONF_get_section(conf, section))) return 0; sl@0: for (i = 0; i < sk_CONF_VALUE_num(nval); i++) sl@0: { sl@0: val = sk_CONF_VALUE_value(nval, i); sl@0: if (!(ext = X509V3_EXT_nconf(conf, ctx, val->name, val->value))) sl@0: return 0; sl@0: if (sk) X509v3_add_ext(sk, ext, -1); sl@0: X509_EXTENSION_free(ext); sl@0: } sl@0: return 1; sl@0: } sl@0: sl@0: /* Convenience functions to add extensions to a certificate, CRL and request */ sl@0: sl@0: EXPORT_C int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, sl@0: X509 *cert) sl@0: { sl@0: STACK_OF(X509_EXTENSION) **sk = NULL; sl@0: if (cert) sl@0: sk = &cert->cert_info->extensions; sl@0: return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); sl@0: } sl@0: sl@0: /* Same as above but for a CRL */ sl@0: sl@0: EXPORT_C int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, sl@0: X509_CRL *crl) sl@0: { sl@0: STACK_OF(X509_EXTENSION) **sk = NULL; sl@0: if (crl) sl@0: sk = &crl->crl->extensions; sl@0: return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); sl@0: } sl@0: sl@0: /* Add extensions to certificate request */ sl@0: sl@0: EXPORT_C int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, sl@0: X509_REQ *req) sl@0: { sl@0: STACK_OF(X509_EXTENSION) *extlist = NULL, **sk = NULL; sl@0: int i; sl@0: if (req) sl@0: sk = &extlist; sl@0: i = X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); sl@0: if (!i || !sk) sl@0: return i; sl@0: i = X509_REQ_add_extensions(req, extlist); sl@0: sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free); sl@0: return i; sl@0: } sl@0: sl@0: /* Config database functions */ sl@0: sl@0: EXPORT_C char * X509V3_get_string(X509V3_CTX *ctx, char *name, char *section) sl@0: { sl@0: if(!ctx->db || !ctx->db_meth || !ctx->db_meth->get_string) sl@0: { sl@0: X509V3err(X509V3_F_X509V3_GET_STRING,X509V3_R_OPERATION_NOT_DEFINED); sl@0: return NULL; sl@0: } sl@0: if (ctx->db_meth->get_string) sl@0: return ctx->db_meth->get_string(ctx->db, name, section); sl@0: return NULL; sl@0: } sl@0: sl@0: EXPORT_C STACK_OF(CONF_VALUE) * X509V3_get_section(X509V3_CTX *ctx, char *section) sl@0: { sl@0: if(!ctx->db || !ctx->db_meth || !ctx->db_meth->get_section) sl@0: { sl@0: X509V3err(X509V3_F_X509V3_GET_SECTION,X509V3_R_OPERATION_NOT_DEFINED); sl@0: return NULL; sl@0: } sl@0: if (ctx->db_meth->get_section) sl@0: return ctx->db_meth->get_section(ctx->db, section); sl@0: return NULL; sl@0: } sl@0: sl@0: EXPORT_C void X509V3_string_free(X509V3_CTX *ctx, char *str) sl@0: { sl@0: if (!str) return; sl@0: if (ctx->db_meth->free_string) sl@0: ctx->db_meth->free_string(ctx->db, str); sl@0: } sl@0: sl@0: EXPORT_C void X509V3_section_free(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section) sl@0: { sl@0: if (!section) return; sl@0: if (ctx->db_meth->free_section) sl@0: ctx->db_meth->free_section(ctx->db, section); sl@0: } sl@0: sl@0: static char *nconf_get_string(void *db, char *section, char *value) sl@0: { sl@0: return NCONF_get_string(db, section, value); sl@0: } sl@0: sl@0: static STACK_OF(CONF_VALUE) *nconf_get_section(void *db, char *section) sl@0: { sl@0: return NCONF_get_section(db, section); sl@0: } sl@0: sl@0: #ifndef EMULATOR sl@0: static X509V3_CONF_METHOD nconf_method = { sl@0: nconf_get_string, sl@0: nconf_get_section, sl@0: NULL, sl@0: NULL sl@0: }; sl@0: #else sl@0: GET_STATIC_VAR_FROM_TLS(nconf_method,v3_conf,X509V3_CONF_METHOD) sl@0: #define nconf_method (*GET_WSD_VAR_NAME(nconf_method,v3_conf, s)()) sl@0: const X509V3_CONF_METHOD temp_s_nconf_method = { sl@0: nconf_get_string, sl@0: nconf_get_section, sl@0: NULL, sl@0: NULL sl@0: }; sl@0: #endif sl@0: sl@0: EXPORT_C void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf) sl@0: { sl@0: ctx->db_meth = &nconf_method; sl@0: ctx->db = conf; sl@0: } sl@0: sl@0: EXPORT_C void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subj, X509_REQ *req, sl@0: X509_CRL *crl, int flags) sl@0: { sl@0: ctx->issuer_cert = issuer; sl@0: ctx->subject_cert = subj; sl@0: ctx->crl = crl; sl@0: ctx->subject_req = req; sl@0: ctx->flags = flags; sl@0: } sl@0: sl@0: /* Old conf compatibility functions */ sl@0: sl@0: EXPORT_C X509_EXTENSION *X509V3_EXT_conf(LHASH *conf, X509V3_CTX *ctx, char *name, sl@0: char *value) sl@0: { sl@0: CONF ctmp; sl@0: CONF_set_nconf(&ctmp, conf); sl@0: return X509V3_EXT_nconf(&ctmp, ctx, name, value); sl@0: } sl@0: sl@0: /* LHASH *conf: Config file */ sl@0: /* char *value: Value */ sl@0: EXPORT_C X509_EXTENSION *X509V3_EXT_conf_nid(LHASH *conf, X509V3_CTX *ctx, int ext_nid, sl@0: char *value) sl@0: { sl@0: CONF ctmp; sl@0: CONF_set_nconf(&ctmp, conf); sl@0: return X509V3_EXT_nconf_nid(&ctmp, ctx, ext_nid, value); sl@0: } sl@0: sl@0: static char *conf_lhash_get_string(void *db, char *section, char *value) sl@0: { sl@0: return CONF_get_string(db, section, value); sl@0: } sl@0: sl@0: static STACK_OF(CONF_VALUE) *conf_lhash_get_section(void *db, char *section) sl@0: { sl@0: return CONF_get_section(db, section); sl@0: } sl@0: sl@0: #ifndef EMULATOR sl@0: static X509V3_CONF_METHOD conf_lhash_method = { sl@0: conf_lhash_get_string, sl@0: conf_lhash_get_section, sl@0: NULL, sl@0: NULL sl@0: }; sl@0: #else sl@0: GET_STATIC_VAR_FROM_TLS(conf_lhash_method,v3_conf,X509V3_CONF_METHOD) sl@0: #define conf_lhash_method (*GET_WSD_VAR_NAME(conf_lhash_method,v3_conf, s)()) sl@0: const X509V3_CONF_METHOD temp_s_conf_lhash_method = { sl@0: conf_lhash_get_string, sl@0: conf_lhash_get_section, sl@0: NULL, sl@0: NULL sl@0: }; sl@0: #endif sl@0: sl@0: EXPORT_C void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH *lhash) sl@0: { sl@0: ctx->db_meth = &conf_lhash_method; sl@0: ctx->db = lhash; sl@0: } sl@0: sl@0: EXPORT_C int X509V3_EXT_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, sl@0: X509 *cert) sl@0: { sl@0: CONF ctmp; sl@0: CONF_set_nconf(&ctmp, conf); sl@0: return X509V3_EXT_add_nconf(&ctmp, ctx, section, cert); sl@0: } sl@0: sl@0: /* Same as above but for a CRL */ sl@0: sl@0: EXPORT_C int X509V3_EXT_CRL_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, sl@0: X509_CRL *crl) sl@0: { sl@0: CONF ctmp; sl@0: CONF_set_nconf(&ctmp, conf); sl@0: return X509V3_EXT_CRL_add_nconf(&ctmp, ctx, section, crl); sl@0: } sl@0: sl@0: /* Add extensions to certificate request */ sl@0: sl@0: EXPORT_C int X509V3_EXT_REQ_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, sl@0: X509_REQ *req) sl@0: { sl@0: CONF ctmp; sl@0: CONF_set_nconf(&ctmp, conf); sl@0: return X509V3_EXT_REQ_add_nconf(&ctmp, ctx, section, req); sl@0: }