v3_alt.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. /* v3_alt.c */
  2. /* Written by Dr Stephen N Henson (shenson@bigfoot.com) 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
  28. * licensing@OpenSSL.org.
  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. * (eay@cryptsoft.com). This product includes software written by Tim
  55. * Hudson (tjh@cryptsoft.com).
  56. *
  57. */
  58. #include <stdio.h>
  59. #include "cryptlib.h"
  60. #include <openssl/conf.h>
  61. #include <openssl/x509v3.h>
  62. static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
  63. static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
  64. static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p);
  65. static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens);
  66. static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx);
  67. static int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx);
  68. X509V3_EXT_METHOD v3_alt[] = {
  69. { NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
  70. 0,0,0,0,
  71. 0,0,
  72. (X509V3_EXT_I2V)i2v_GENERAL_NAMES,
  73. (X509V3_EXT_V2I)v2i_subject_alt,
  74. NULL, NULL, NULL},
  75. { NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
  76. 0,0,0,0,
  77. 0,0,
  78. (X509V3_EXT_I2V)i2v_GENERAL_NAMES,
  79. (X509V3_EXT_V2I)v2i_issuer_alt,
  80. NULL, NULL, NULL},
  81. };
  82. STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
  83. GENERAL_NAMES *gens, STACK_OF(CONF_VALUE) *ret)
  84. {
  85. int i;
  86. GENERAL_NAME *gen;
  87. for(i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
  88. gen = sk_GENERAL_NAME_value(gens, i);
  89. ret = i2v_GENERAL_NAME(method, gen, ret);
  90. }
  91. if(!ret) return sk_CONF_VALUE_new_null();
  92. return ret;
  93. }
  94. STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
  95. GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret)
  96. {
  97. unsigned char *p;
  98. char oline[256], htmp[5];
  99. int i;
  100. switch (gen->type)
  101. {
  102. case GEN_OTHERNAME:
  103. X509V3_add_value("othername","<unsupported>", &ret);
  104. break;
  105. case GEN_X400:
  106. X509V3_add_value("X400Name","<unsupported>", &ret);
  107. break;
  108. case GEN_EDIPARTY:
  109. X509V3_add_value("EdiPartyName","<unsupported>", &ret);
  110. break;
  111. case GEN_EMAIL:
  112. X509V3_add_value_uchar("email",gen->d.ia5->data, &ret);
  113. break;
  114. case GEN_DNS:
  115. X509V3_add_value_uchar("DNS",gen->d.ia5->data, &ret);
  116. break;
  117. case GEN_URI:
  118. X509V3_add_value_uchar("URI",gen->d.ia5->data, &ret);
  119. break;
  120. case GEN_DIRNAME:
  121. X509_NAME_oneline(gen->d.dirn, oline, 256);
  122. X509V3_add_value("DirName",oline, &ret);
  123. break;
  124. case GEN_IPADD:
  125. p = gen->d.ip->data;
  126. if(gen->d.ip->length == 4)
  127. BIO_snprintf(oline, sizeof oline,
  128. "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
  129. else if(gen->d.ip->length == 16)
  130. {
  131. oline[0] = 0;
  132. for (i = 0; i < 8; i++)
  133. {
  134. BIO_snprintf(htmp, sizeof htmp,
  135. "%X", p[0] << 8 | p[1]);
  136. p += 2;
  137. strcat(oline, htmp);
  138. if (i != 7)
  139. strcat(oline, ":");
  140. }
  141. }
  142. else
  143. {
  144. X509V3_add_value("IP Address","<invalid>", &ret);
  145. break;
  146. }
  147. X509V3_add_value("IP Address",oline, &ret);
  148. break;
  149. case GEN_RID:
  150. i2t_ASN1_OBJECT(oline, 256, gen->d.rid);
  151. X509V3_add_value("Registered ID",oline, &ret);
  152. break;
  153. }
  154. return ret;
  155. }
  156. int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
  157. {
  158. unsigned char *p;
  159. int i;
  160. switch (gen->type)
  161. {
  162. case GEN_OTHERNAME:
  163. BIO_printf(out, "othername:<unsupported>");
  164. break;
  165. case GEN_X400:
  166. BIO_printf(out, "X400Name:<unsupported>");
  167. break;
  168. case GEN_EDIPARTY:
  169. /* Maybe fix this: it is supported now */
  170. BIO_printf(out, "EdiPartyName:<unsupported>");
  171. break;
  172. case GEN_EMAIL:
  173. BIO_printf(out, "email:%s",gen->d.ia5->data);
  174. break;
  175. case GEN_DNS:
  176. BIO_printf(out, "DNS:%s",gen->d.ia5->data);
  177. break;
  178. case GEN_URI:
  179. BIO_printf(out, "URI:%s",gen->d.ia5->data);
  180. break;
  181. case GEN_DIRNAME:
  182. BIO_printf(out, "DirName: ");
  183. X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE);
  184. break;
  185. case GEN_IPADD:
  186. p = gen->d.ip->data;
  187. if(gen->d.ip->length == 4)
  188. BIO_printf(out, "IP Address:%d.%d.%d.%d",
  189. p[0], p[1], p[2], p[3]);
  190. else if(gen->d.ip->length == 16)
  191. {
  192. BIO_printf(out, "IP Address");
  193. for (i = 0; i < 8; i++)
  194. {
  195. BIO_printf(out, ":%X", p[0] << 8 | p[1]);
  196. p += 2;
  197. }
  198. BIO_puts(out, "\n");
  199. }
  200. else
  201. {
  202. BIO_printf(out,"IP Address:<invalid>");
  203. break;
  204. }
  205. break;
  206. case GEN_RID:
  207. BIO_printf(out, "Registered ID");
  208. i2a_ASN1_OBJECT(out, gen->d.rid);
  209. break;
  210. }
  211. return 1;
  212. }
  213. static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
  214. X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
  215. {
  216. GENERAL_NAMES *gens = NULL;
  217. CONF_VALUE *cnf;
  218. int i;
  219. if(!(gens = sk_GENERAL_NAME_new_null())) {
  220. X509V3err(X509V3_F_V2I_ISSUER_ALT,ERR_R_MALLOC_FAILURE);
  221. return NULL;
  222. }
  223. for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
  224. cnf = sk_CONF_VALUE_value(nval, i);
  225. if(!name_cmp(cnf->name, "issuer") && cnf->value &&
  226. !strcmp(cnf->value, "copy")) {
  227. if(!copy_issuer(ctx, gens)) goto err;
  228. } else {
  229. GENERAL_NAME *gen;
  230. if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
  231. goto err;
  232. sk_GENERAL_NAME_push(gens, gen);
  233. }
  234. }
  235. return gens;
  236. err:
  237. sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
  238. return NULL;
  239. }
  240. /* Append subject altname of issuer to issuer alt name of subject */
  241. static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens)
  242. {
  243. GENERAL_NAMES *ialt;
  244. GENERAL_NAME *gen;
  245. X509_EXTENSION *ext;
  246. int i;
  247. if(ctx && (ctx->flags == CTX_TEST)) return 1;
  248. if(!ctx || !ctx->issuer_cert) {
  249. X509V3err(X509V3_F_COPY_ISSUER,X509V3_R_NO_ISSUER_DETAILS);
  250. goto err;
  251. }
  252. i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
  253. if(i < 0) return 1;
  254. if(!(ext = X509_get_ext(ctx->issuer_cert, i)) ||
  255. !(ialt = X509V3_EXT_d2i(ext)) ) {
  256. X509V3err(X509V3_F_COPY_ISSUER,X509V3_R_ISSUER_DECODE_ERROR);
  257. goto err;
  258. }
  259. for(i = 0; i < sk_GENERAL_NAME_num(ialt); i++) {
  260. gen = sk_GENERAL_NAME_value(ialt, i);
  261. if(!sk_GENERAL_NAME_push(gens, gen)) {
  262. X509V3err(X509V3_F_COPY_ISSUER,ERR_R_MALLOC_FAILURE);
  263. goto err;
  264. }
  265. }
  266. sk_GENERAL_NAME_free(ialt);
  267. return 1;
  268. err:
  269. return 0;
  270. }
  271. static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
  272. X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
  273. {
  274. GENERAL_NAMES *gens = NULL;
  275. CONF_VALUE *cnf;
  276. int i;
  277. if(!(gens = sk_GENERAL_NAME_new_null())) {
  278. X509V3err(X509V3_F_V2I_SUBJECT_ALT,ERR_R_MALLOC_FAILURE);
  279. return NULL;
  280. }
  281. for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
  282. cnf = sk_CONF_VALUE_value(nval, i);
  283. if(!name_cmp(cnf->name, "email") && cnf->value &&
  284. !strcmp(cnf->value, "copy")) {
  285. if(!copy_email(ctx, gens, 0)) goto err;
  286. } else if(!name_cmp(cnf->name, "email") && cnf->value &&
  287. !strcmp(cnf->value, "move")) {
  288. if(!copy_email(ctx, gens, 1)) goto err;
  289. } else {
  290. GENERAL_NAME *gen;
  291. if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
  292. goto err;
  293. sk_GENERAL_NAME_push(gens, gen);
  294. }
  295. }
  296. return gens;
  297. err:
  298. sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
  299. return NULL;
  300. }
  301. /* Copy any email addresses in a certificate or request to
  302. * GENERAL_NAMES
  303. */
  304. static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p)
  305. {
  306. X509_NAME *nm;
  307. ASN1_IA5STRING *email = NULL;
  308. X509_NAME_ENTRY *ne;
  309. GENERAL_NAME *gen = NULL;
  310. int i;
  311. if(ctx != NULL && ctx->flags == CTX_TEST)
  312. return 1;
  313. if(!ctx || (!ctx->subject_cert && !ctx->subject_req)) {
  314. X509V3err(X509V3_F_COPY_EMAIL,X509V3_R_NO_SUBJECT_DETAILS);
  315. goto err;
  316. }
  317. /* Find the subject name */
  318. if(ctx->subject_cert) nm = X509_get_subject_name(ctx->subject_cert);
  319. else nm = X509_REQ_get_subject_name(ctx->subject_req);
  320. /* Now add any email address(es) to STACK */
  321. i = -1;
  322. while((i = X509_NAME_get_index_by_NID(nm,
  323. NID_pkcs9_emailAddress, i)) >= 0) {
  324. ne = X509_NAME_get_entry(nm, i);
  325. email = M_ASN1_IA5STRING_dup(X509_NAME_ENTRY_get_data(ne));
  326. if (move_p)
  327. {
  328. X509_NAME_delete_entry(nm, i);
  329. i--;
  330. }
  331. if(!email || !(gen = GENERAL_NAME_new())) {
  332. X509V3err(X509V3_F_COPY_EMAIL,ERR_R_MALLOC_FAILURE);
  333. goto err;
  334. }
  335. gen->d.ia5 = email;
  336. email = NULL;
  337. gen->type = GEN_EMAIL;
  338. if(!sk_GENERAL_NAME_push(gens, gen)) {
  339. X509V3err(X509V3_F_COPY_EMAIL,ERR_R_MALLOC_FAILURE);
  340. goto err;
  341. }
  342. gen = NULL;
  343. }
  344. return 1;
  345. err:
  346. GENERAL_NAME_free(gen);
  347. M_ASN1_IA5STRING_free(email);
  348. return 0;
  349. }
  350. GENERAL_NAMES *v2i_GENERAL_NAMES(X509V3_EXT_METHOD *method,
  351. X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
  352. {
  353. GENERAL_NAME *gen;
  354. GENERAL_NAMES *gens = NULL;
  355. CONF_VALUE *cnf;
  356. int i;
  357. if(!(gens = sk_GENERAL_NAME_new_null())) {
  358. X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE);
  359. return NULL;
  360. }
  361. for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
  362. cnf = sk_CONF_VALUE_value(nval, i);
  363. if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) goto err;
  364. sk_GENERAL_NAME_push(gens, gen);
  365. }
  366. return gens;
  367. err:
  368. sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
  369. return NULL;
  370. }
  371. GENERAL_NAME *v2i_GENERAL_NAME(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
  372. CONF_VALUE *cnf)
  373. {
  374. return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
  375. }
  376. GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
  377. X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
  378. CONF_VALUE *cnf, int is_nc)
  379. {
  380. char is_string = 0;
  381. int type;
  382. GENERAL_NAME *gen = NULL;
  383. char *name, *value;
  384. name = cnf->name;
  385. value = cnf->value;
  386. if(!value)
  387. {
  388. X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_MISSING_VALUE);
  389. return NULL;
  390. }
  391. if (out)
  392. gen = out;
  393. else
  394. {
  395. gen = GENERAL_NAME_new();
  396. if(gen == NULL)
  397. {
  398. X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,ERR_R_MALLOC_FAILURE);
  399. return NULL;
  400. }
  401. }
  402. if(!name_cmp(name, "email"))
  403. {
  404. is_string = 1;
  405. type = GEN_EMAIL;
  406. }
  407. else if(!name_cmp(name, "URI"))
  408. {
  409. is_string = 1;
  410. type = GEN_URI;
  411. }
  412. else if(!name_cmp(name, "DNS"))
  413. {
  414. is_string = 1;
  415. type = GEN_DNS;
  416. }
  417. else if(!name_cmp(name, "RID"))
  418. {
  419. ASN1_OBJECT *obj;
  420. if(!(obj = OBJ_txt2obj(value,0)))
  421. {
  422. X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_BAD_OBJECT);
  423. ERR_add_error_data(2, "value=", value);
  424. goto err;
  425. }
  426. gen->d.rid = obj;
  427. type = GEN_RID;
  428. }
  429. else if(!name_cmp(name, "IP"))
  430. {
  431. if (is_nc)
  432. gen->d.ip = a2i_IPADDRESS_NC(value);
  433. else
  434. gen->d.ip = a2i_IPADDRESS(value);
  435. if(gen->d.ip == NULL)
  436. {
  437. X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_BAD_IP_ADDRESS);
  438. ERR_add_error_data(2, "value=", value);
  439. goto err;
  440. }
  441. type = GEN_IPADD;
  442. }
  443. else if(!name_cmp(name, "dirName"))
  444. {
  445. type = GEN_DIRNAME;
  446. if (!do_dirname(gen, value, ctx))
  447. {
  448. X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_DIRNAME_ERROR);
  449. goto err;
  450. }
  451. }
  452. else if(!name_cmp(name, "otherName"))
  453. {
  454. if (!do_othername(gen, value, ctx))
  455. {
  456. X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_OTHERNAME_ERROR);
  457. goto err;
  458. }
  459. type = GEN_OTHERNAME;
  460. }
  461. else
  462. {
  463. X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_UNSUPPORTED_OPTION);
  464. ERR_add_error_data(2, "name=", name);
  465. goto err;
  466. }
  467. if(is_string)
  468. {
  469. if(!(gen->d.ia5 = M_ASN1_IA5STRING_new()) ||
  470. !ASN1_STRING_set(gen->d.ia5, (unsigned char*)value,
  471. strlen(value)))
  472. {
  473. X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,ERR_R_MALLOC_FAILURE);
  474. goto err;
  475. }
  476. }
  477. gen->type = type;
  478. return gen;
  479. err:
  480. GENERAL_NAME_free(gen);
  481. return NULL;
  482. }
  483. static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
  484. {
  485. char *objtmp = NULL, *p;
  486. int objlen;
  487. if (!(p = strchr(value, ';')))
  488. return 0;
  489. if (!(gen->d.otherName = OTHERNAME_new()))
  490. return 0;
  491. /* Free this up because we will overwrite it.
  492. * no need to free type_id because it is static
  493. */
  494. ASN1_TYPE_free(gen->d.otherName->value);
  495. if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)))
  496. return 0;
  497. objlen = p - value;
  498. objtmp = OPENSSL_malloc(objlen + 1);
  499. strncpy(objtmp, value, objlen);
  500. objtmp[objlen] = 0;
  501. gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
  502. OPENSSL_free(objtmp);
  503. if (!gen->d.otherName->type_id)
  504. return 0;
  505. return 1;
  506. }
  507. static int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
  508. {
  509. int ret;
  510. STACK_OF(CONF_VALUE) *sk;
  511. X509_NAME *nm;
  512. if (!(nm = X509_NAME_new()))
  513. return 0;
  514. sk = X509V3_get_section(ctx, value);
  515. if (!sk)
  516. {
  517. X509V3err(X509V3_F_DO_DIRNAME,X509V3_R_SECTION_NOT_FOUND);
  518. ERR_add_error_data(2, "section=", value);
  519. X509_NAME_free(nm);
  520. return 0;
  521. }
  522. /* FIXME: should allow other character types... */
  523. ret = X509V3_NAME_from_section(nm, sk, MBSTRING_ASC);
  524. if (!ret)
  525. X509_NAME_free(nm);
  526. gen->d.dirn = nm;
  527. return ret;
  528. }