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