conf_mod.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. /* conf_mod.c */
  2. /* Written by Stephen Henson (shenson@bigfoot.com) for the OpenSSL
  3. * project 2001.
  4. */
  5. /* ====================================================================
  6. * Copyright (c) 2001 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 <ctype.h>
  60. #include <openssl/crypto.h>
  61. #include "cryptlib.h"
  62. #include <openssl/conf.h>
  63. #include <openssl/dso.h>
  64. #include <openssl/x509.h>
  65. #define DSO_mod_init_name "OPENSSL_init"
  66. #define DSO_mod_finish_name "OPENSSL_finish"
  67. /* This structure contains a data about supported modules.
  68. * entries in this table correspond to either dynamic or
  69. * static modules.
  70. */
  71. struct conf_module_st
  72. {
  73. /* DSO of this module or NULL if static */
  74. DSO *dso;
  75. /* Name of the module */
  76. char *name;
  77. /* Init function */
  78. conf_init_func *init;
  79. /* Finish function */
  80. conf_finish_func *finish;
  81. /* Number of successfully initialized modules */
  82. int links;
  83. void *usr_data;
  84. };
  85. /* This structure contains information about modules that have been
  86. * successfully initialized. There may be more than one entry for a
  87. * given module.
  88. */
  89. struct conf_imodule_st
  90. {
  91. CONF_MODULE *pmod;
  92. char *name;
  93. char *value;
  94. unsigned long flags;
  95. void *usr_data;
  96. };
  97. static STACK_OF(CONF_MODULE) *supported_modules = NULL;
  98. static STACK_OF(CONF_IMODULE) *initialized_modules = NULL;
  99. static void module_free(CONF_MODULE *md);
  100. static void module_finish(CONF_IMODULE *imod);
  101. static int module_run(const CONF *cnf, char *name, char *value,
  102. unsigned long flags);
  103. static CONF_MODULE *module_add(DSO *dso, const char *name,
  104. conf_init_func *ifunc, conf_finish_func *ffunc);
  105. static CONF_MODULE *module_find(char *name);
  106. static int module_init(CONF_MODULE *pmod, char *name, char *value,
  107. const CONF *cnf);
  108. static CONF_MODULE *module_load_dso(const CONF *cnf, char *name, char *value,
  109. unsigned long flags);
  110. /* Main function: load modules from a CONF structure */
  111. int CONF_modules_load(const CONF *cnf, const char *appname,
  112. unsigned long flags)
  113. {
  114. STACK_OF(CONF_VALUE) *values;
  115. CONF_VALUE *vl;
  116. char *vsection = NULL;
  117. int ret, i;
  118. if (!cnf)
  119. return 1;
  120. if (appname)
  121. vsection = NCONF_get_string(cnf, NULL, appname);
  122. if (!appname || (!vsection && (flags & CONF_MFLAGS_DEFAULT_SECTION)))
  123. vsection = NCONF_get_string(cnf, NULL, "openssl_conf");
  124. if (!vsection)
  125. {
  126. ERR_clear_error();
  127. return 1;
  128. }
  129. values = NCONF_get_section(cnf, vsection);
  130. if (!values)
  131. return 0;
  132. for (i = 0; i < sk_CONF_VALUE_num(values); i++)
  133. {
  134. vl = sk_CONF_VALUE_value(values, i);
  135. ret = module_run(cnf, vl->name, vl->value, flags);
  136. if (ret <= 0)
  137. if(!(flags & CONF_MFLAGS_IGNORE_ERRORS))
  138. return ret;
  139. }
  140. return 1;
  141. }
  142. int CONF_modules_load_file(const char *filename, const char *appname,
  143. unsigned long flags)
  144. {
  145. char *file = NULL;
  146. CONF *conf = NULL;
  147. int ret = 0;
  148. conf = NCONF_new(NULL);
  149. if (!conf)
  150. goto err;
  151. if (filename == NULL)
  152. {
  153. file = CONF_get1_default_config_file();
  154. if (!file)
  155. goto err;
  156. }
  157. else
  158. file = (char *)filename;
  159. if (NCONF_load(conf, file, NULL) <= 0)
  160. {
  161. if ((flags & CONF_MFLAGS_IGNORE_MISSING_FILE) &&
  162. (ERR_GET_REASON(ERR_peek_last_error()) == CONF_R_NO_SUCH_FILE))
  163. {
  164. ERR_clear_error();
  165. ret = 1;
  166. }
  167. goto err;
  168. }
  169. ret = CONF_modules_load(conf, appname, flags);
  170. err:
  171. if (filename == NULL)
  172. OPENSSL_free(file);
  173. NCONF_free(conf);
  174. return ret;
  175. }
  176. static int module_run(const CONF *cnf, char *name, char *value,
  177. unsigned long flags)
  178. {
  179. CONF_MODULE *md;
  180. int ret;
  181. md = module_find(name);
  182. /* Module not found: try to load DSO */
  183. if (!md && !(flags & CONF_MFLAGS_NO_DSO))
  184. md = module_load_dso(cnf, name, value, flags);
  185. if (!md)
  186. {
  187. if (!(flags & CONF_MFLAGS_SILENT))
  188. {
  189. CONFerr(CONF_F_MODULE_RUN, CONF_R_UNKNOWN_MODULE_NAME);
  190. ERR_add_error_data(2, "module=", name);
  191. }
  192. return -1;
  193. }
  194. ret = module_init(md, name, value, cnf);
  195. if (ret <= 0)
  196. {
  197. if (!(flags & CONF_MFLAGS_SILENT))
  198. {
  199. char rcode[DECIMAL_SIZE(ret)+1];
  200. CONFerr(CONF_F_MODULE_RUN, CONF_R_MODULE_INITIALIZATION_ERROR);
  201. BIO_snprintf(rcode, sizeof rcode, "%-8d", ret);
  202. ERR_add_error_data(6, "module=", name, ", value=", value, ", retcode=", rcode);
  203. }
  204. }
  205. return ret;
  206. }
  207. /* Load a module from a DSO */
  208. static CONF_MODULE *module_load_dso(const CONF *cnf, char *name, char *value,
  209. unsigned long flags)
  210. {
  211. DSO *dso = NULL;
  212. conf_init_func *ifunc;
  213. conf_finish_func *ffunc;
  214. char *path = NULL;
  215. int errcode = 0;
  216. CONF_MODULE *md;
  217. /* Look for alternative path in module section */
  218. path = NCONF_get_string(cnf, value, "path");
  219. if (!path)
  220. {
  221. ERR_clear_error();
  222. path = name;
  223. }
  224. dso = DSO_load(NULL, path, NULL, 0);
  225. if (!dso)
  226. {
  227. errcode = CONF_R_ERROR_LOADING_DSO;
  228. goto err;
  229. }
  230. ifunc = (conf_init_func *)DSO_bind_func(dso, DSO_mod_init_name);
  231. if (!ifunc)
  232. {
  233. errcode = CONF_R_MISSING_INIT_FUNCTION;
  234. goto err;
  235. }
  236. ffunc = (conf_finish_func *)DSO_bind_func(dso, DSO_mod_finish_name);
  237. /* All OK, add module */
  238. md = module_add(dso, name, ifunc, ffunc);
  239. if (!md)
  240. goto err;
  241. return md;
  242. err:
  243. if (dso)
  244. DSO_free(dso);
  245. CONFerr(CONF_F_MODULE_LOAD_DSO, errcode);
  246. ERR_add_error_data(4, "module=", name, ", path=", path);
  247. return NULL;
  248. }
  249. /* add module to list */
  250. static CONF_MODULE *module_add(DSO *dso, const char *name,
  251. conf_init_func *ifunc, conf_finish_func *ffunc)
  252. {
  253. CONF_MODULE *tmod = NULL;
  254. if (supported_modules == NULL)
  255. supported_modules = sk_CONF_MODULE_new_null();
  256. if (supported_modules == NULL)
  257. return NULL;
  258. tmod = OPENSSL_malloc(sizeof(CONF_MODULE));
  259. if (tmod == NULL)
  260. return NULL;
  261. tmod->dso = dso;
  262. tmod->name = BUF_strdup(name);
  263. tmod->init = ifunc;
  264. tmod->finish = ffunc;
  265. tmod->links = 0;
  266. if (!sk_CONF_MODULE_push(supported_modules, tmod))
  267. {
  268. OPENSSL_free(tmod);
  269. return NULL;
  270. }
  271. return tmod;
  272. }
  273. /* Find a module from the list. We allow module names of the
  274. * form modname.XXXX to just search for modname to allow the
  275. * same module to be initialized more than once.
  276. */
  277. static CONF_MODULE *module_find(char *name)
  278. {
  279. CONF_MODULE *tmod;
  280. int i, nchar;
  281. char *p;
  282. p = strrchr(name, '.');
  283. if (p)
  284. nchar = p - name;
  285. else
  286. nchar = strlen(name);
  287. for (i = 0; i < sk_CONF_MODULE_num(supported_modules); i++)
  288. {
  289. tmod = sk_CONF_MODULE_value(supported_modules, i);
  290. if (!strncmp(tmod->name, name, nchar))
  291. return tmod;
  292. }
  293. return NULL;
  294. }
  295. /* initialize a module */
  296. static int module_init(CONF_MODULE *pmod, char *name, char *value,
  297. const CONF *cnf)
  298. {
  299. int ret = 1;
  300. int init_called = 0;
  301. CONF_IMODULE *imod = NULL;
  302. /* Otherwise add initialized module to list */
  303. imod = OPENSSL_malloc(sizeof(CONF_IMODULE));
  304. if (!imod)
  305. goto err;
  306. imod->pmod = pmod;
  307. imod->name = BUF_strdup(name);
  308. imod->value = BUF_strdup(value);
  309. imod->usr_data = NULL;
  310. if (!imod->name || !imod->value)
  311. goto memerr;
  312. /* Try to initialize module */
  313. if(pmod->init)
  314. {
  315. ret = pmod->init(imod, cnf);
  316. init_called = 1;
  317. /* Error occurred, exit */
  318. if (ret <= 0)
  319. goto err;
  320. }
  321. if (initialized_modules == NULL)
  322. {
  323. initialized_modules = sk_CONF_IMODULE_new_null();
  324. if (!initialized_modules)
  325. {
  326. CONFerr(CONF_F_MODULE_INIT, ERR_R_MALLOC_FAILURE);
  327. goto err;
  328. }
  329. }
  330. if (!sk_CONF_IMODULE_push(initialized_modules, imod))
  331. {
  332. CONFerr(CONF_F_MODULE_INIT, ERR_R_MALLOC_FAILURE);
  333. goto err;
  334. }
  335. pmod->links++;
  336. return ret;
  337. err:
  338. /* We've started the module so we'd better finish it */
  339. if (pmod->finish && init_called)
  340. pmod->finish(imod);
  341. memerr:
  342. if (imod)
  343. {
  344. if (imod->name)
  345. OPENSSL_free(imod->name);
  346. if (imod->value)
  347. OPENSSL_free(imod->value);
  348. OPENSSL_free(imod);
  349. }
  350. return -1;
  351. }
  352. /* Unload any dynamic modules that have a link count of zero:
  353. * i.e. have no active initialized modules. If 'all' is set
  354. * then all modules are unloaded including static ones.
  355. */
  356. void CONF_modules_unload(int all)
  357. {
  358. int i;
  359. CONF_MODULE *md;
  360. CONF_modules_finish();
  361. /* unload modules in reverse order */
  362. for (i = sk_CONF_MODULE_num(supported_modules) - 1; i >= 0; i--)
  363. {
  364. md = sk_CONF_MODULE_value(supported_modules, i);
  365. /* If static or in use and 'all' not set ignore it */
  366. if (((md->links > 0) || !md->dso) && !all)
  367. continue;
  368. /* Since we're working in reverse this is OK */
  369. sk_CONF_MODULE_delete(supported_modules, i);
  370. module_free(md);
  371. }
  372. if (sk_CONF_MODULE_num(supported_modules) == 0)
  373. {
  374. sk_CONF_MODULE_free(supported_modules);
  375. supported_modules = NULL;
  376. }
  377. }
  378. /* unload a single module */
  379. static void module_free(CONF_MODULE *md)
  380. {
  381. if (md->dso)
  382. DSO_free(md->dso);
  383. OPENSSL_free(md->name);
  384. OPENSSL_free(md);
  385. }
  386. /* finish and free up all modules instances */
  387. void CONF_modules_finish(void)
  388. {
  389. CONF_IMODULE *imod;
  390. while (sk_CONF_IMODULE_num(initialized_modules) > 0)
  391. {
  392. imod = sk_CONF_IMODULE_pop(initialized_modules);
  393. module_finish(imod);
  394. }
  395. sk_CONF_IMODULE_free(initialized_modules);
  396. initialized_modules = NULL;
  397. }
  398. /* finish a module instance */
  399. static void module_finish(CONF_IMODULE *imod)
  400. {
  401. if (imod->pmod->finish)
  402. imod->pmod->finish(imod);
  403. imod->pmod->links--;
  404. OPENSSL_free(imod->name);
  405. OPENSSL_free(imod->value);
  406. OPENSSL_free(imod);
  407. }
  408. /* Add a static module to OpenSSL */
  409. int CONF_module_add(const char *name, conf_init_func *ifunc,
  410. conf_finish_func *ffunc)
  411. {
  412. if (module_add(NULL, name, ifunc, ffunc))
  413. return 1;
  414. else
  415. return 0;
  416. }
  417. void CONF_modules_free(void)
  418. {
  419. CONF_modules_finish();
  420. CONF_modules_unload(1);
  421. }
  422. /* Utility functions */
  423. const char *CONF_imodule_get_name(const CONF_IMODULE *md)
  424. {
  425. return md->name;
  426. }
  427. const char *CONF_imodule_get_value(const CONF_IMODULE *md)
  428. {
  429. return md->value;
  430. }
  431. void *CONF_imodule_get_usr_data(const CONF_IMODULE *md)
  432. {
  433. return md->usr_data;
  434. }
  435. void CONF_imodule_set_usr_data(CONF_IMODULE *md, void *usr_data)
  436. {
  437. md->usr_data = usr_data;
  438. }
  439. CONF_MODULE *CONF_imodule_get_module(const CONF_IMODULE *md)
  440. {
  441. return md->pmod;
  442. }
  443. unsigned long CONF_imodule_get_flags(const CONF_IMODULE *md)
  444. {
  445. return md->flags;
  446. }
  447. void CONF_imodule_set_flags(CONF_IMODULE *md, unsigned long flags)
  448. {
  449. md->flags = flags;
  450. }
  451. void *CONF_module_get_usr_data(CONF_MODULE *pmod)
  452. {
  453. return pmod->usr_data;
  454. }
  455. void CONF_module_set_usr_data(CONF_MODULE *pmod, void *usr_data)
  456. {
  457. pmod->usr_data = usr_data;
  458. }
  459. /* Return default config file name */
  460. char *CONF_get1_default_config_file(void)
  461. {
  462. char *file;
  463. int len;
  464. file = getenv("OPENSSL_CONF");
  465. if (file)
  466. return BUF_strdup(file);
  467. len = strlen(X509_get_default_cert_area());
  468. #ifndef OPENSSL_SYS_VMS
  469. len++;
  470. #endif
  471. len += strlen(OPENSSL_CONF);
  472. file = OPENSSL_malloc(len + 1);
  473. if (!file)
  474. return NULL;
  475. BUF_strlcpy(file,X509_get_default_cert_area(),len + 1);
  476. #ifndef OPENSSL_SYS_VMS
  477. BUF_strlcat(file,"/",len + 1);
  478. #endif
  479. BUF_strlcat(file,OPENSSL_CONF,len + 1);
  480. return file;
  481. }
  482. /* This function takes a list separated by 'sep' and calls the
  483. * callback function giving the start and length of each member
  484. * optionally stripping leading and trailing whitespace. This can
  485. * be used to parse comma separated lists for example.
  486. */
  487. int CONF_parse_list(const char *list_, int sep, int nospc,
  488. int (*list_cb)(const char *elem, int len, void *usr), void *arg)
  489. {
  490. int ret;
  491. const char *lstart, *tmpend, *p;
  492. lstart = list_;
  493. for(;;)
  494. {
  495. if (nospc)
  496. {
  497. while(*lstart && isspace((unsigned char)*lstart))
  498. lstart++;
  499. }
  500. p = strchr(lstart, sep);
  501. if (p == lstart || !*lstart)
  502. ret = list_cb(NULL, 0, arg);
  503. else
  504. {
  505. if (p)
  506. tmpend = p - 1;
  507. else
  508. tmpend = lstart + strlen(lstart) - 1;
  509. if (nospc)
  510. {
  511. while(isspace((unsigned char)*tmpend))
  512. tmpend--;
  513. }
  514. ret = list_cb(lstart, tmpend - lstart + 1, arg);
  515. }
  516. if (ret <= 0)
  517. return ret;
  518. if (p == NULL)
  519. return 1;
  520. lstart = p + 1;
  521. }
  522. }