v3_conf.c 18 KB

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