Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 
 
 

562 рядки
17 KiB

  1. /* v3_crld.c */
  2. /*
  3. * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
  4. * 1999.
  5. */
  6. /* ====================================================================
  7. * Copyright (c) 1999-2008 The OpenSSL Project. All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. *
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. *
  16. * 2. Redistributions in binary form must reproduce the above copyright
  17. * notice, this list of conditions and the following disclaimer in
  18. * the documentation and/or other materials provided with the
  19. * distribution.
  20. *
  21. * 3. All advertising materials mentioning features or use of this
  22. * software must display the following acknowledgment:
  23. * "This product includes software developed by the OpenSSL Project
  24. * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  25. *
  26. * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  27. * endorse or promote products derived from this software without
  28. * prior written permission. For written permission, please contact
  29. * licensing@OpenSSL.org.
  30. *
  31. * 5. Products derived from this software may not be called "OpenSSL"
  32. * nor may "OpenSSL" appear in their names without prior written
  33. * permission of the OpenSSL Project.
  34. *
  35. * 6. Redistributions of any form whatsoever must retain the following
  36. * acknowledgment:
  37. * "This product includes software developed by the OpenSSL Project
  38. * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  39. *
  40. * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  41. * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  42. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  43. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
  44. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  45. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  46. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  47. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  48. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  49. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  50. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  51. * OF THE POSSIBILITY OF SUCH DAMAGE.
  52. * ====================================================================
  53. *
  54. * This product includes cryptographic software written by Eric Young
  55. * (eay@cryptsoft.com). This product includes software written by Tim
  56. * Hudson (tjh@cryptsoft.com). */
  57. #include <stdio.h>
  58. #include <string.h>
  59. #include <openssl/asn1.h>
  60. #include <openssl/asn1t.h>
  61. #include <openssl/conf.h>
  62. #include <openssl/err.h>
  63. #include <openssl/mem.h>
  64. #include <openssl/obj.h>
  65. #include <openssl/x509v3.h>
  66. static void *v2i_crld(const X509V3_EXT_METHOD *method,
  67. X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
  68. static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
  69. int indent);
  70. const X509V3_EXT_METHOD v3_crld = {
  71. NID_crl_distribution_points, 0, ASN1_ITEM_ref(CRL_DIST_POINTS),
  72. 0, 0, 0, 0,
  73. 0, 0,
  74. 0,
  75. v2i_crld,
  76. i2r_crldp, 0,
  77. NULL
  78. };
  79. const X509V3_EXT_METHOD v3_freshest_crl = {
  80. NID_freshest_crl, 0, ASN1_ITEM_ref(CRL_DIST_POINTS),
  81. 0, 0, 0, 0,
  82. 0, 0,
  83. 0,
  84. v2i_crld,
  85. i2r_crldp, 0,
  86. NULL
  87. };
  88. static STACK_OF(GENERAL_NAME) *gnames_from_sectname(X509V3_CTX *ctx,
  89. char *sect)
  90. {
  91. STACK_OF(CONF_VALUE) *gnsect;
  92. STACK_OF(GENERAL_NAME) *gens;
  93. if (*sect == '@')
  94. gnsect = X509V3_get_section(ctx, sect + 1);
  95. else
  96. gnsect = X509V3_parse_list(sect);
  97. if (!gnsect) {
  98. OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND);
  99. return NULL;
  100. }
  101. gens = v2i_GENERAL_NAMES(NULL, ctx, gnsect);
  102. if (*sect == '@')
  103. X509V3_section_free(ctx, gnsect);
  104. else
  105. sk_CONF_VALUE_pop_free(gnsect, X509V3_conf_free);
  106. return gens;
  107. }
  108. static int set_dist_point_name(DIST_POINT_NAME **pdp, X509V3_CTX *ctx,
  109. CONF_VALUE *cnf)
  110. {
  111. STACK_OF(GENERAL_NAME) *fnm = NULL;
  112. STACK_OF(X509_NAME_ENTRY) *rnm = NULL;
  113. if (!strncmp(cnf->name, "fullname", 9)) {
  114. fnm = gnames_from_sectname(ctx, cnf->value);
  115. if (!fnm)
  116. goto err;
  117. } else if (!strcmp(cnf->name, "relativename")) {
  118. int ret;
  119. STACK_OF(CONF_VALUE) *dnsect;
  120. X509_NAME *nm;
  121. nm = X509_NAME_new();
  122. if (!nm)
  123. return -1;
  124. dnsect = X509V3_get_section(ctx, cnf->value);
  125. if (!dnsect) {
  126. OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND);
  127. return -1;
  128. }
  129. ret = X509V3_NAME_from_section(nm, dnsect, MBSTRING_ASC);
  130. X509V3_section_free(ctx, dnsect);
  131. rnm = nm->entries;
  132. nm->entries = NULL;
  133. X509_NAME_free(nm);
  134. if (!ret || sk_X509_NAME_ENTRY_num(rnm) <= 0)
  135. goto err;
  136. /*
  137. * Since its a name fragment can't have more than one RDNSequence
  138. */
  139. if (sk_X509_NAME_ENTRY_value(rnm,
  140. sk_X509_NAME_ENTRY_num(rnm) - 1)->set) {
  141. OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_MULTIPLE_RDNS);
  142. goto err;
  143. }
  144. } else
  145. return 0;
  146. if (*pdp) {
  147. OPENSSL_PUT_ERROR(X509V3, X509V3_R_DISTPOINT_ALREADY_SET);
  148. goto err;
  149. }
  150. *pdp = DIST_POINT_NAME_new();
  151. if (!*pdp)
  152. goto err;
  153. if (fnm) {
  154. (*pdp)->type = 0;
  155. (*pdp)->name.fullname = fnm;
  156. } else {
  157. (*pdp)->type = 1;
  158. (*pdp)->name.relativename = rnm;
  159. }
  160. return 1;
  161. err:
  162. if (fnm)
  163. sk_GENERAL_NAME_pop_free(fnm, GENERAL_NAME_free);
  164. if (rnm)
  165. sk_X509_NAME_ENTRY_pop_free(rnm, X509_NAME_ENTRY_free);
  166. return -1;
  167. }
  168. static const BIT_STRING_BITNAME reason_flags[] = {
  169. {0, "Unused", "unused"},
  170. {1, "Key Compromise", "keyCompromise"},
  171. {2, "CA Compromise", "CACompromise"},
  172. {3, "Affiliation Changed", "affiliationChanged"},
  173. {4, "Superseded", "superseded"},
  174. {5, "Cessation Of Operation", "cessationOfOperation"},
  175. {6, "Certificate Hold", "certificateHold"},
  176. {7, "Privilege Withdrawn", "privilegeWithdrawn"},
  177. {8, "AA Compromise", "AACompromise"},
  178. {-1, NULL, NULL}
  179. };
  180. static int set_reasons(ASN1_BIT_STRING **preas, char *value)
  181. {
  182. STACK_OF(CONF_VALUE) *rsk = NULL;
  183. const BIT_STRING_BITNAME *pbn;
  184. const char *bnam;
  185. size_t i;
  186. int ret = 0;
  187. rsk = X509V3_parse_list(value);
  188. if (!rsk)
  189. return 0;
  190. if (*preas)
  191. return 0;
  192. for (i = 0; i < sk_CONF_VALUE_num(rsk); i++) {
  193. bnam = sk_CONF_VALUE_value(rsk, i)->name;
  194. if (!*preas) {
  195. *preas = ASN1_BIT_STRING_new();
  196. if (!*preas)
  197. goto err;
  198. }
  199. for (pbn = reason_flags; pbn->lname; pbn++) {
  200. if (!strcmp(pbn->sname, bnam)) {
  201. if (!ASN1_BIT_STRING_set_bit(*preas, pbn->bitnum, 1))
  202. goto err;
  203. break;
  204. }
  205. }
  206. if (!pbn->lname)
  207. goto err;
  208. }
  209. ret = 1;
  210. err:
  211. sk_CONF_VALUE_pop_free(rsk, X509V3_conf_free);
  212. return ret;
  213. }
  214. static int print_reasons(BIO *out, const char *rname,
  215. ASN1_BIT_STRING *rflags, int indent)
  216. {
  217. int first = 1;
  218. const BIT_STRING_BITNAME *pbn;
  219. BIO_printf(out, "%*s%s:\n%*s", indent, "", rname, indent + 2, "");
  220. for (pbn = reason_flags; pbn->lname; pbn++) {
  221. if (ASN1_BIT_STRING_get_bit(rflags, pbn->bitnum)) {
  222. if (first)
  223. first = 0;
  224. else
  225. BIO_puts(out, ", ");
  226. BIO_puts(out, pbn->lname);
  227. }
  228. }
  229. if (first)
  230. BIO_puts(out, "<EMPTY>\n");
  231. else
  232. BIO_puts(out, "\n");
  233. return 1;
  234. }
  235. static DIST_POINT *crldp_from_section(X509V3_CTX *ctx,
  236. STACK_OF(CONF_VALUE) *nval)
  237. {
  238. size_t i;
  239. CONF_VALUE *cnf;
  240. DIST_POINT *point = NULL;
  241. point = DIST_POINT_new();
  242. if (!point)
  243. goto err;
  244. for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
  245. int ret;
  246. cnf = sk_CONF_VALUE_value(nval, i);
  247. ret = set_dist_point_name(&point->distpoint, ctx, cnf);
  248. if (ret > 0)
  249. continue;
  250. if (ret < 0)
  251. goto err;
  252. if (!strcmp(cnf->name, "reasons")) {
  253. if (!set_reasons(&point->reasons, cnf->value))
  254. goto err;
  255. } else if (!strcmp(cnf->name, "CRLissuer")) {
  256. point->CRLissuer = gnames_from_sectname(ctx, cnf->value);
  257. if (!point->CRLissuer)
  258. goto err;
  259. }
  260. }
  261. return point;
  262. err:
  263. if (point)
  264. DIST_POINT_free(point);
  265. return NULL;
  266. }
  267. static void *v2i_crld(const X509V3_EXT_METHOD *method,
  268. X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
  269. {
  270. STACK_OF(DIST_POINT) *crld = NULL;
  271. GENERAL_NAMES *gens = NULL;
  272. GENERAL_NAME *gen = NULL;
  273. CONF_VALUE *cnf;
  274. size_t i;
  275. if (!(crld = sk_DIST_POINT_new_null()))
  276. goto merr;
  277. for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
  278. DIST_POINT *point;
  279. cnf = sk_CONF_VALUE_value(nval, i);
  280. if (!cnf->value) {
  281. STACK_OF(CONF_VALUE) *dpsect;
  282. dpsect = X509V3_get_section(ctx, cnf->name);
  283. if (!dpsect)
  284. goto err;
  285. point = crldp_from_section(ctx, dpsect);
  286. X509V3_section_free(ctx, dpsect);
  287. if (!point)
  288. goto err;
  289. if (!sk_DIST_POINT_push(crld, point)) {
  290. DIST_POINT_free(point);
  291. goto merr;
  292. }
  293. } else {
  294. if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
  295. goto err;
  296. if (!(gens = GENERAL_NAMES_new()))
  297. goto merr;
  298. if (!sk_GENERAL_NAME_push(gens, gen))
  299. goto merr;
  300. gen = NULL;
  301. if (!(point = DIST_POINT_new()))
  302. goto merr;
  303. if (!sk_DIST_POINT_push(crld, point)) {
  304. DIST_POINT_free(point);
  305. goto merr;
  306. }
  307. if (!(point->distpoint = DIST_POINT_NAME_new()))
  308. goto merr;
  309. point->distpoint->name.fullname = gens;
  310. point->distpoint->type = 0;
  311. gens = NULL;
  312. }
  313. }
  314. return crld;
  315. merr:
  316. OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
  317. err:
  318. GENERAL_NAME_free(gen);
  319. GENERAL_NAMES_free(gens);
  320. sk_DIST_POINT_pop_free(crld, DIST_POINT_free);
  321. return NULL;
  322. }
  323. IMPLEMENT_ASN1_SET_OF(DIST_POINT)
  324. static int dpn_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
  325. void *exarg)
  326. {
  327. DIST_POINT_NAME *dpn = (DIST_POINT_NAME *)*pval;
  328. switch (operation) {
  329. case ASN1_OP_NEW_POST:
  330. dpn->dpname = NULL;
  331. break;
  332. case ASN1_OP_FREE_POST:
  333. if (dpn->dpname)
  334. X509_NAME_free(dpn->dpname);
  335. break;
  336. }
  337. return 1;
  338. }
  339. ASN1_CHOICE_cb(DIST_POINT_NAME, dpn_cb) = {
  340. ASN1_IMP_SEQUENCE_OF(DIST_POINT_NAME, name.fullname, GENERAL_NAME, 0),
  341. ASN1_IMP_SET_OF(DIST_POINT_NAME, name.relativename, X509_NAME_ENTRY, 1)
  342. } ASN1_CHOICE_END_cb(DIST_POINT_NAME, DIST_POINT_NAME, type)
  343. IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT_NAME)
  344. ASN1_SEQUENCE(DIST_POINT) = {
  345. ASN1_EXP_OPT(DIST_POINT, distpoint, DIST_POINT_NAME, 0),
  346. ASN1_IMP_OPT(DIST_POINT, reasons, ASN1_BIT_STRING, 1),
  347. ASN1_IMP_SEQUENCE_OF_OPT(DIST_POINT, CRLissuer, GENERAL_NAME, 2)
  348. } ASN1_SEQUENCE_END(DIST_POINT)
  349. IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT)
  350. ASN1_ITEM_TEMPLATE(CRL_DIST_POINTS) =
  351. ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CRLDistributionPoints, DIST_POINT)
  352. ASN1_ITEM_TEMPLATE_END(CRL_DIST_POINTS)
  353. IMPLEMENT_ASN1_FUNCTIONS(CRL_DIST_POINTS)
  354. ASN1_SEQUENCE(ISSUING_DIST_POINT) = {
  355. ASN1_EXP_OPT(ISSUING_DIST_POINT, distpoint, DIST_POINT_NAME, 0),
  356. ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyuser, ASN1_FBOOLEAN, 1),
  357. ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyCA, ASN1_FBOOLEAN, 2),
  358. ASN1_IMP_OPT(ISSUING_DIST_POINT, onlysomereasons, ASN1_BIT_STRING, 3),
  359. ASN1_IMP_OPT(ISSUING_DIST_POINT, indirectCRL, ASN1_FBOOLEAN, 4),
  360. ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyattr, ASN1_FBOOLEAN, 5)
  361. } ASN1_SEQUENCE_END(ISSUING_DIST_POINT)
  362. IMPLEMENT_ASN1_FUNCTIONS(ISSUING_DIST_POINT)
  363. static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out,
  364. int indent);
  365. static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
  366. STACK_OF(CONF_VALUE) *nval);
  367. const X509V3_EXT_METHOD v3_idp = {
  368. NID_issuing_distribution_point, X509V3_EXT_MULTILINE,
  369. ASN1_ITEM_ref(ISSUING_DIST_POINT),
  370. 0, 0, 0, 0,
  371. 0, 0,
  372. 0,
  373. v2i_idp,
  374. i2r_idp, 0,
  375. NULL
  376. };
  377. static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
  378. STACK_OF(CONF_VALUE) *nval)
  379. {
  380. ISSUING_DIST_POINT *idp = NULL;
  381. CONF_VALUE *cnf;
  382. char *name, *val;
  383. size_t i;
  384. int ret;
  385. idp = ISSUING_DIST_POINT_new();
  386. if (!idp)
  387. goto merr;
  388. for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
  389. cnf = sk_CONF_VALUE_value(nval, i);
  390. name = cnf->name;
  391. val = cnf->value;
  392. ret = set_dist_point_name(&idp->distpoint, ctx, cnf);
  393. if (ret > 0)
  394. continue;
  395. if (ret < 0)
  396. goto err;
  397. if (!strcmp(name, "onlyuser")) {
  398. if (!X509V3_get_value_bool(cnf, &idp->onlyuser))
  399. goto err;
  400. } else if (!strcmp(name, "onlyCA")) {
  401. if (!X509V3_get_value_bool(cnf, &idp->onlyCA))
  402. goto err;
  403. } else if (!strcmp(name, "onlyAA")) {
  404. if (!X509V3_get_value_bool(cnf, &idp->onlyattr))
  405. goto err;
  406. } else if (!strcmp(name, "indirectCRL")) {
  407. if (!X509V3_get_value_bool(cnf, &idp->indirectCRL))
  408. goto err;
  409. } else if (!strcmp(name, "onlysomereasons")) {
  410. if (!set_reasons(&idp->onlysomereasons, val))
  411. goto err;
  412. } else {
  413. OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NAME);
  414. X509V3_conf_err(cnf);
  415. goto err;
  416. }
  417. }
  418. return idp;
  419. merr:
  420. OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
  421. err:
  422. ISSUING_DIST_POINT_free(idp);
  423. return NULL;
  424. }
  425. static int print_gens(BIO *out, STACK_OF(GENERAL_NAME) *gens, int indent)
  426. {
  427. size_t i;
  428. for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
  429. BIO_printf(out, "%*s", indent + 2, "");
  430. GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i));
  431. BIO_puts(out, "\n");
  432. }
  433. return 1;
  434. }
  435. static int print_distpoint(BIO *out, DIST_POINT_NAME *dpn, int indent)
  436. {
  437. if (dpn->type == 0) {
  438. BIO_printf(out, "%*sFull Name:\n", indent, "");
  439. print_gens(out, dpn->name.fullname, indent);
  440. } else {
  441. X509_NAME ntmp;
  442. ntmp.entries = dpn->name.relativename;
  443. BIO_printf(out, "%*sRelative Name:\n%*s", indent, "", indent + 2, "");
  444. X509_NAME_print_ex(out, &ntmp, 0, XN_FLAG_ONELINE);
  445. BIO_puts(out, "\n");
  446. }
  447. return 1;
  448. }
  449. static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out,
  450. int indent)
  451. {
  452. ISSUING_DIST_POINT *idp = pidp;
  453. if (idp->distpoint)
  454. print_distpoint(out, idp->distpoint, indent);
  455. if (idp->onlyuser > 0)
  456. BIO_printf(out, "%*sOnly User Certificates\n", indent, "");
  457. if (idp->onlyCA > 0)
  458. BIO_printf(out, "%*sOnly CA Certificates\n", indent, "");
  459. if (idp->indirectCRL > 0)
  460. BIO_printf(out, "%*sIndirect CRL\n", indent, "");
  461. if (idp->onlysomereasons)
  462. print_reasons(out, "Only Some Reasons", idp->onlysomereasons, indent);
  463. if (idp->onlyattr > 0)
  464. BIO_printf(out, "%*sOnly Attribute Certificates\n", indent, "");
  465. if (!idp->distpoint && (idp->onlyuser <= 0) && (idp->onlyCA <= 0)
  466. && (idp->indirectCRL <= 0) && !idp->onlysomereasons
  467. && (idp->onlyattr <= 0))
  468. BIO_printf(out, "%*s<EMPTY>\n", indent, "");
  469. return 1;
  470. }
  471. static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
  472. int indent)
  473. {
  474. STACK_OF(DIST_POINT) *crld = pcrldp;
  475. DIST_POINT *point;
  476. size_t i;
  477. for (i = 0; i < sk_DIST_POINT_num(crld); i++) {
  478. BIO_puts(out, "\n");
  479. point = sk_DIST_POINT_value(crld, i);
  480. if (point->distpoint)
  481. print_distpoint(out, point->distpoint, indent);
  482. if (point->reasons)
  483. print_reasons(out, "Reasons", point->reasons, indent);
  484. if (point->CRLissuer) {
  485. BIO_printf(out, "%*sCRL Issuer:\n", indent, "");
  486. print_gens(out, point->CRLissuer, indent);
  487. }
  488. }
  489. return 1;
  490. }
  491. int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname)
  492. {
  493. size_t i;
  494. STACK_OF(X509_NAME_ENTRY) *frag;
  495. X509_NAME_ENTRY *ne;
  496. if (!dpn || (dpn->type != 1))
  497. return 1;
  498. frag = dpn->name.relativename;
  499. dpn->dpname = X509_NAME_dup(iname);
  500. if (!dpn->dpname)
  501. return 0;
  502. for (i = 0; i < sk_X509_NAME_ENTRY_num(frag); i++) {
  503. ne = sk_X509_NAME_ENTRY_value(frag, i);
  504. if (!X509_NAME_add_entry(dpn->dpname, ne, -1, i ? 0 : 1)) {
  505. X509_NAME_free(dpn->dpname);
  506. dpn->dpname = NULL;
  507. return 0;
  508. }
  509. }
  510. /* generate cached encoding of name */
  511. if (i2d_X509_NAME(dpn->dpname, NULL) < 0) {
  512. X509_NAME_free(dpn->dpname);
  513. dpn->dpname = NULL;
  514. return 0;
  515. }
  516. return 1;
  517. }