172c33676SMaxim Ag /* $OpenBSD: conf_mod.c,v 1.27 2017/01/29 17:49:22 beck Exp $ */
2f5b1c8a1SJohn Marino /* Written by Stephen Henson (steve@openssl.org) for the OpenSSL
3f5b1c8a1SJohn Marino  * project 2001.
4f5b1c8a1SJohn Marino  */
5f5b1c8a1SJohn Marino /* ====================================================================
6f5b1c8a1SJohn Marino  * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
7f5b1c8a1SJohn Marino  *
8f5b1c8a1SJohn Marino  * Redistribution and use in source and binary forms, with or without
9f5b1c8a1SJohn Marino  * modification, are permitted provided that the following conditions
10f5b1c8a1SJohn Marino  * are met:
11f5b1c8a1SJohn Marino  *
12f5b1c8a1SJohn Marino  * 1. Redistributions of source code must retain the above copyright
13f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer.
14f5b1c8a1SJohn Marino  *
15f5b1c8a1SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
16f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer in
17f5b1c8a1SJohn Marino  *    the documentation and/or other materials provided with the
18f5b1c8a1SJohn Marino  *    distribution.
19f5b1c8a1SJohn Marino  *
20f5b1c8a1SJohn Marino  * 3. All advertising materials mentioning features or use of this
21f5b1c8a1SJohn Marino  *    software must display the following acknowledgment:
22f5b1c8a1SJohn Marino  *    "This product includes software developed by the OpenSSL Project
23f5b1c8a1SJohn Marino  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24f5b1c8a1SJohn Marino  *
25f5b1c8a1SJohn Marino  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26f5b1c8a1SJohn Marino  *    endorse or promote products derived from this software without
27f5b1c8a1SJohn Marino  *    prior written permission. For written permission, please contact
28f5b1c8a1SJohn Marino  *    licensing@OpenSSL.org.
29f5b1c8a1SJohn Marino  *
30f5b1c8a1SJohn Marino  * 5. Products derived from this software may not be called "OpenSSL"
31f5b1c8a1SJohn Marino  *    nor may "OpenSSL" appear in their names without prior written
32f5b1c8a1SJohn Marino  *    permission of the OpenSSL Project.
33f5b1c8a1SJohn Marino  *
34f5b1c8a1SJohn Marino  * 6. Redistributions of any form whatsoever must retain the following
35f5b1c8a1SJohn Marino  *    acknowledgment:
36f5b1c8a1SJohn Marino  *    "This product includes software developed by the OpenSSL Project
37f5b1c8a1SJohn Marino  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38f5b1c8a1SJohn Marino  *
39f5b1c8a1SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40f5b1c8a1SJohn Marino  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41f5b1c8a1SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42f5b1c8a1SJohn Marino  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43f5b1c8a1SJohn Marino  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44f5b1c8a1SJohn Marino  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45f5b1c8a1SJohn Marino  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46f5b1c8a1SJohn Marino  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47f5b1c8a1SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48f5b1c8a1SJohn Marino  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49f5b1c8a1SJohn Marino  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50f5b1c8a1SJohn Marino  * OF THE POSSIBILITY OF SUCH DAMAGE.
51f5b1c8a1SJohn Marino  * ====================================================================
52f5b1c8a1SJohn Marino  *
53f5b1c8a1SJohn Marino  * This product includes cryptographic software written by Eric Young
54f5b1c8a1SJohn Marino  * (eay@cryptsoft.com).  This product includes software written by Tim
55f5b1c8a1SJohn Marino  * Hudson (tjh@cryptsoft.com).
56f5b1c8a1SJohn Marino  *
57f5b1c8a1SJohn Marino  */
58f5b1c8a1SJohn Marino 
59f5b1c8a1SJohn Marino #include <ctype.h>
60f5b1c8a1SJohn Marino #include <stdio.h>
61f5b1c8a1SJohn Marino #include <string.h>
62f5b1c8a1SJohn Marino #include <unistd.h>
63f5b1c8a1SJohn Marino 
64f5b1c8a1SJohn Marino #include <openssl/conf.h>
65f5b1c8a1SJohn Marino #include <openssl/crypto.h>
66f5b1c8a1SJohn Marino #include <openssl/dso.h>
67f5b1c8a1SJohn Marino #include <openssl/err.h>
68f5b1c8a1SJohn Marino #include <openssl/x509.h>
69f5b1c8a1SJohn Marino 
70f5b1c8a1SJohn Marino #define DSO_mod_init_name "OPENSSL_init"
71f5b1c8a1SJohn Marino #define DSO_mod_finish_name "OPENSSL_finish"
72f5b1c8a1SJohn Marino 
73f5b1c8a1SJohn Marino /* This structure contains a data about supported modules.
74f5b1c8a1SJohn Marino  * entries in this table correspond to either dynamic or
75f5b1c8a1SJohn Marino  * static modules.
76f5b1c8a1SJohn Marino  */
77f5b1c8a1SJohn Marino 
78f5b1c8a1SJohn Marino struct conf_module_st {
79f5b1c8a1SJohn Marino 	/* DSO of this module or NULL if static */
80f5b1c8a1SJohn Marino 	DSO *dso;
81f5b1c8a1SJohn Marino 	/* Name of the module */
82f5b1c8a1SJohn Marino 	char *name;
83f5b1c8a1SJohn Marino 	/* Init function */
84f5b1c8a1SJohn Marino 	conf_init_func *init;
85f5b1c8a1SJohn Marino 	/* Finish function */
86f5b1c8a1SJohn Marino 	conf_finish_func *finish;
87f5b1c8a1SJohn Marino 	/* Number of successfully initialized modules */
88f5b1c8a1SJohn Marino 	int links;
89f5b1c8a1SJohn Marino 	void *usr_data;
90f5b1c8a1SJohn Marino };
91f5b1c8a1SJohn Marino 
92f5b1c8a1SJohn Marino 
93f5b1c8a1SJohn Marino /* This structure contains information about modules that have been
94f5b1c8a1SJohn Marino  * successfully initialized. There may be more than one entry for a
95f5b1c8a1SJohn Marino  * given module.
96f5b1c8a1SJohn Marino  */
97f5b1c8a1SJohn Marino 
98f5b1c8a1SJohn Marino struct conf_imodule_st {
99f5b1c8a1SJohn Marino 	CONF_MODULE *pmod;
100f5b1c8a1SJohn Marino 	char *name;
101f5b1c8a1SJohn Marino 	char *value;
102f5b1c8a1SJohn Marino 	unsigned long flags;
103f5b1c8a1SJohn Marino 	void *usr_data;
104f5b1c8a1SJohn Marino };
105f5b1c8a1SJohn Marino 
106f5b1c8a1SJohn Marino static STACK_OF(CONF_MODULE) *supported_modules = NULL;
107f5b1c8a1SJohn Marino static STACK_OF(CONF_IMODULE) *initialized_modules = NULL;
108f5b1c8a1SJohn Marino 
109f5b1c8a1SJohn Marino static void module_free(CONF_MODULE *md);
110f5b1c8a1SJohn Marino static void module_finish(CONF_IMODULE *imod);
111f5b1c8a1SJohn Marino static int module_run(const CONF *cnf, char *name, char *value,
112f5b1c8a1SJohn Marino     unsigned long flags);
113f5b1c8a1SJohn Marino static CONF_MODULE *module_add(DSO *dso, const char *name,
114f5b1c8a1SJohn Marino     conf_init_func *ifunc, conf_finish_func *ffunc);
115f5b1c8a1SJohn Marino static CONF_MODULE *module_find(char *name);
116f5b1c8a1SJohn Marino static int module_init(CONF_MODULE *pmod, char *name, char *value,
117f5b1c8a1SJohn Marino     const CONF *cnf);
118f5b1c8a1SJohn Marino static CONF_MODULE *module_load_dso(const CONF *cnf, char *name, char *value,
119f5b1c8a1SJohn Marino     unsigned long flags);
120f5b1c8a1SJohn Marino 
121f5b1c8a1SJohn Marino /* Main function: load modules from a CONF structure */
122f5b1c8a1SJohn Marino 
123f5b1c8a1SJohn Marino int
CONF_modules_load(const CONF * cnf,const char * appname,unsigned long flags)124f5b1c8a1SJohn Marino CONF_modules_load(const CONF *cnf, const char *appname, unsigned long flags)
125f5b1c8a1SJohn Marino {
126f5b1c8a1SJohn Marino 	STACK_OF(CONF_VALUE) *values;
127f5b1c8a1SJohn Marino 	CONF_VALUE *vl;
128f5b1c8a1SJohn Marino 	char *vsection = NULL;
129f5b1c8a1SJohn Marino 
130f5b1c8a1SJohn Marino 	int ret, i;
131f5b1c8a1SJohn Marino 
132f5b1c8a1SJohn Marino 	if (!cnf)
133f5b1c8a1SJohn Marino 		return 1;
134f5b1c8a1SJohn Marino 
135f5b1c8a1SJohn Marino 	if (appname)
136f5b1c8a1SJohn Marino 		vsection = NCONF_get_string(cnf, NULL, appname);
137f5b1c8a1SJohn Marino 
138f5b1c8a1SJohn Marino 	if (!appname || (!vsection && (flags & CONF_MFLAGS_DEFAULT_SECTION)))
139f5b1c8a1SJohn Marino 		vsection = NCONF_get_string(cnf, NULL, "openssl_conf");
140f5b1c8a1SJohn Marino 
141f5b1c8a1SJohn Marino 	if (!vsection) {
142f5b1c8a1SJohn Marino 		ERR_clear_error();
143f5b1c8a1SJohn Marino 		return 1;
144f5b1c8a1SJohn Marino 	}
145f5b1c8a1SJohn Marino 
146f5b1c8a1SJohn Marino 	values = NCONF_get_section(cnf, vsection);
147f5b1c8a1SJohn Marino 
148f5b1c8a1SJohn Marino 	if (!values)
149f5b1c8a1SJohn Marino 		return 0;
150f5b1c8a1SJohn Marino 
151f5b1c8a1SJohn Marino 	for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
152f5b1c8a1SJohn Marino 		vl = sk_CONF_VALUE_value(values, i);
153f5b1c8a1SJohn Marino 		ret = module_run(cnf, vl->name, vl->value, flags);
154f5b1c8a1SJohn Marino 		if (ret <= 0)
155f5b1c8a1SJohn Marino 			if (!(flags & CONF_MFLAGS_IGNORE_ERRORS))
156f5b1c8a1SJohn Marino 				return ret;
157f5b1c8a1SJohn Marino 	}
158f5b1c8a1SJohn Marino 
159f5b1c8a1SJohn Marino 	return 1;
160f5b1c8a1SJohn Marino }
161f5b1c8a1SJohn Marino 
162f5b1c8a1SJohn Marino int
CONF_modules_load_file(const char * filename,const char * appname,unsigned long flags)163f5b1c8a1SJohn Marino CONF_modules_load_file(const char *filename, const char *appname,
164f5b1c8a1SJohn Marino     unsigned long flags)
165f5b1c8a1SJohn Marino {
166f5b1c8a1SJohn Marino 	char *file = NULL;
167f5b1c8a1SJohn Marino 	CONF *conf = NULL;
168f5b1c8a1SJohn Marino 	int ret = 0;
169f5b1c8a1SJohn Marino 	conf = NCONF_new(NULL);
170f5b1c8a1SJohn Marino 	if (!conf)
171f5b1c8a1SJohn Marino 		goto err;
172f5b1c8a1SJohn Marino 
173f5b1c8a1SJohn Marino 	if (filename == NULL) {
174f5b1c8a1SJohn Marino 		file = CONF_get1_default_config_file();
175f5b1c8a1SJohn Marino 		if (!file)
176f5b1c8a1SJohn Marino 			goto err;
177f5b1c8a1SJohn Marino 	} else
178f5b1c8a1SJohn Marino 		file = (char *)filename;
179f5b1c8a1SJohn Marino 
180f5b1c8a1SJohn Marino 	if (NCONF_load(conf, file, NULL) <= 0) {
181f5b1c8a1SJohn Marino 		if ((flags & CONF_MFLAGS_IGNORE_MISSING_FILE) &&
182f5b1c8a1SJohn Marino 		    (ERR_GET_REASON(ERR_peek_last_error()) ==
183f5b1c8a1SJohn Marino 		    CONF_R_NO_SUCH_FILE)) {
184f5b1c8a1SJohn Marino 			ERR_clear_error();
185f5b1c8a1SJohn Marino 			ret = 1;
186f5b1c8a1SJohn Marino 		}
187f5b1c8a1SJohn Marino 		goto err;
188f5b1c8a1SJohn Marino 	}
189f5b1c8a1SJohn Marino 
190f5b1c8a1SJohn Marino 	ret = CONF_modules_load(conf, appname, flags);
191f5b1c8a1SJohn Marino 
192f5b1c8a1SJohn Marino err:
193f5b1c8a1SJohn Marino 	if (filename == NULL)
194f5b1c8a1SJohn Marino 		free(file);
195f5b1c8a1SJohn Marino 	NCONF_free(conf);
196f5b1c8a1SJohn Marino 
197f5b1c8a1SJohn Marino 	return ret;
198f5b1c8a1SJohn Marino }
199f5b1c8a1SJohn Marino 
200f5b1c8a1SJohn Marino static int
module_run(const CONF * cnf,char * name,char * value,unsigned long flags)201f5b1c8a1SJohn Marino module_run(const CONF *cnf, char *name, char *value, unsigned long flags)
202f5b1c8a1SJohn Marino {
203f5b1c8a1SJohn Marino 	CONF_MODULE *md;
204f5b1c8a1SJohn Marino 	int ret;
205f5b1c8a1SJohn Marino 
206f5b1c8a1SJohn Marino 	md = module_find(name);
207f5b1c8a1SJohn Marino 
208f5b1c8a1SJohn Marino 	/* Module not found: try to load DSO */
209f5b1c8a1SJohn Marino 	if (!md && !(flags & CONF_MFLAGS_NO_DSO))
210f5b1c8a1SJohn Marino 		md = module_load_dso(cnf, name, value, flags);
211f5b1c8a1SJohn Marino 
212f5b1c8a1SJohn Marino 	if (!md) {
213f5b1c8a1SJohn Marino 		if (!(flags & CONF_MFLAGS_SILENT)) {
21472c33676SMaxim Ag 			CONFerror(CONF_R_UNKNOWN_MODULE_NAME);
215f5b1c8a1SJohn Marino 			ERR_asprintf_error_data("module=%s", name);
216f5b1c8a1SJohn Marino 		}
217f5b1c8a1SJohn Marino 		return -1;
218f5b1c8a1SJohn Marino 	}
219f5b1c8a1SJohn Marino 
220f5b1c8a1SJohn Marino 	ret = module_init(md, name, value, cnf);
221f5b1c8a1SJohn Marino 
222f5b1c8a1SJohn Marino 	if (ret <= 0) {
223f5b1c8a1SJohn Marino 		if (!(flags & CONF_MFLAGS_SILENT)) {
22472c33676SMaxim Ag 			CONFerror(CONF_R_MODULE_INITIALIZATION_ERROR);
225f5b1c8a1SJohn Marino 			ERR_asprintf_error_data
226f5b1c8a1SJohn Marino 			    ("module=%s, value=%s, retcode=%-8d",
227f5b1c8a1SJohn Marino 			    name, value, ret);
228f5b1c8a1SJohn Marino 		}
229f5b1c8a1SJohn Marino 	}
230f5b1c8a1SJohn Marino 
231f5b1c8a1SJohn Marino 	return ret;
232f5b1c8a1SJohn Marino }
233f5b1c8a1SJohn Marino 
234f5b1c8a1SJohn Marino /* Load a module from a DSO */
235f5b1c8a1SJohn Marino static CONF_MODULE *
module_load_dso(const CONF * cnf,char * name,char * value,unsigned long flags)236f5b1c8a1SJohn Marino module_load_dso(const CONF *cnf, char *name, char *value, unsigned long flags)
237f5b1c8a1SJohn Marino {
238f5b1c8a1SJohn Marino 	DSO *dso = NULL;
239f5b1c8a1SJohn Marino 	conf_init_func *ifunc;
240f5b1c8a1SJohn Marino 	conf_finish_func *ffunc;
241f5b1c8a1SJohn Marino 	char *path = NULL;
242f5b1c8a1SJohn Marino 	int errcode = 0;
243f5b1c8a1SJohn Marino 	CONF_MODULE *md;
244f5b1c8a1SJohn Marino 
245f5b1c8a1SJohn Marino 	/* Look for alternative path in module section */
246f5b1c8a1SJohn Marino 	path = NCONF_get_string(cnf, value, "path");
247f5b1c8a1SJohn Marino 	if (!path) {
248f5b1c8a1SJohn Marino 		ERR_clear_error();
249f5b1c8a1SJohn Marino 		path = name;
250f5b1c8a1SJohn Marino 	}
251f5b1c8a1SJohn Marino 	dso = DSO_load(NULL, path, NULL, 0);
252f5b1c8a1SJohn Marino 	if (!dso) {
253f5b1c8a1SJohn Marino 		errcode = CONF_R_ERROR_LOADING_DSO;
254f5b1c8a1SJohn Marino 		goto err;
255f5b1c8a1SJohn Marino 	}
256f5b1c8a1SJohn Marino 	ifunc = (conf_init_func *)DSO_bind_func(dso, DSO_mod_init_name);
257f5b1c8a1SJohn Marino 	if (!ifunc) {
258f5b1c8a1SJohn Marino 		errcode = CONF_R_MISSING_INIT_FUNCTION;
259f5b1c8a1SJohn Marino 		goto err;
260f5b1c8a1SJohn Marino 	}
261f5b1c8a1SJohn Marino 	ffunc = (conf_finish_func *)DSO_bind_func(dso, DSO_mod_finish_name);
262f5b1c8a1SJohn Marino 	/* All OK, add module */
263f5b1c8a1SJohn Marino 	md = module_add(dso, name, ifunc, ffunc);
264f5b1c8a1SJohn Marino 
265f5b1c8a1SJohn Marino 	if (!md)
266f5b1c8a1SJohn Marino 		goto err;
267f5b1c8a1SJohn Marino 
268f5b1c8a1SJohn Marino 	return md;
269f5b1c8a1SJohn Marino 
270f5b1c8a1SJohn Marino err:
271f5b1c8a1SJohn Marino 	if (dso)
272f5b1c8a1SJohn Marino 		DSO_free(dso);
27372c33676SMaxim Ag 	CONFerror(errcode);
274f5b1c8a1SJohn Marino 	ERR_asprintf_error_data("module=%s, path=%s", name, path);
275f5b1c8a1SJohn Marino 	return NULL;
276f5b1c8a1SJohn Marino }
277f5b1c8a1SJohn Marino 
278f5b1c8a1SJohn Marino /* add module to list */
279f5b1c8a1SJohn Marino static CONF_MODULE *
module_add(DSO * dso,const char * name,conf_init_func * ifunc,conf_finish_func * ffunc)280f5b1c8a1SJohn Marino module_add(DSO *dso, const char *name, conf_init_func *ifunc,
281f5b1c8a1SJohn Marino     conf_finish_func *ffunc)
282f5b1c8a1SJohn Marino {
283f5b1c8a1SJohn Marino 	CONF_MODULE *tmod = NULL;
284f5b1c8a1SJohn Marino 
285f5b1c8a1SJohn Marino 	if (name == NULL)
286f5b1c8a1SJohn Marino 		return NULL;
287f5b1c8a1SJohn Marino 	if (supported_modules == NULL)
288f5b1c8a1SJohn Marino 		supported_modules = sk_CONF_MODULE_new_null();
289f5b1c8a1SJohn Marino 	if (supported_modules == NULL)
290f5b1c8a1SJohn Marino 		return NULL;
291f5b1c8a1SJohn Marino 	tmod = malloc(sizeof(CONF_MODULE));
292f5b1c8a1SJohn Marino 	if (tmod == NULL)
293f5b1c8a1SJohn Marino 		return NULL;
294f5b1c8a1SJohn Marino 
295f5b1c8a1SJohn Marino 	tmod->dso = dso;
296f5b1c8a1SJohn Marino 	tmod->name = strdup(name);
297f5b1c8a1SJohn Marino 	tmod->init = ifunc;
298f5b1c8a1SJohn Marino 	tmod->finish = ffunc;
299f5b1c8a1SJohn Marino 	tmod->links = 0;
300f5b1c8a1SJohn Marino 
301f5b1c8a1SJohn Marino 	if (!sk_CONF_MODULE_push(supported_modules, tmod)) {
302f5b1c8a1SJohn Marino 		free(tmod);
303f5b1c8a1SJohn Marino 		return NULL;
304f5b1c8a1SJohn Marino 	}
305f5b1c8a1SJohn Marino 
306f5b1c8a1SJohn Marino 	return tmod;
307f5b1c8a1SJohn Marino }
308f5b1c8a1SJohn Marino 
309f5b1c8a1SJohn Marino /* Find a module from the list. We allow module names of the
310f5b1c8a1SJohn Marino  * form modname.XXXX to just search for modname to allow the
311f5b1c8a1SJohn Marino  * same module to be initialized more than once.
312f5b1c8a1SJohn Marino  */
313f5b1c8a1SJohn Marino 
314f5b1c8a1SJohn Marino static CONF_MODULE *
module_find(char * name)315f5b1c8a1SJohn Marino module_find(char *name)
316f5b1c8a1SJohn Marino {
317f5b1c8a1SJohn Marino 	CONF_MODULE *tmod;
318f5b1c8a1SJohn Marino 	int i, nchar;
319f5b1c8a1SJohn Marino 	char *p;
320f5b1c8a1SJohn Marino 
321f5b1c8a1SJohn Marino 	p = strrchr(name, '.');
322f5b1c8a1SJohn Marino 
323f5b1c8a1SJohn Marino 	if (p)
324f5b1c8a1SJohn Marino 		nchar = p - name;
325f5b1c8a1SJohn Marino 	else
326f5b1c8a1SJohn Marino 		nchar = strlen(name);
327f5b1c8a1SJohn Marino 
328f5b1c8a1SJohn Marino 	for (i = 0; i < sk_CONF_MODULE_num(supported_modules); i++) {
329f5b1c8a1SJohn Marino 		tmod = sk_CONF_MODULE_value(supported_modules, i);
330f5b1c8a1SJohn Marino 		if (!strncmp(tmod->name, name, nchar))
331f5b1c8a1SJohn Marino 			return tmod;
332f5b1c8a1SJohn Marino 	}
333f5b1c8a1SJohn Marino 
334f5b1c8a1SJohn Marino 	return NULL;
335f5b1c8a1SJohn Marino }
336f5b1c8a1SJohn Marino 
337f5b1c8a1SJohn Marino /* initialize a module */
338f5b1c8a1SJohn Marino static int
module_init(CONF_MODULE * pmod,char * name,char * value,const CONF * cnf)339f5b1c8a1SJohn Marino module_init(CONF_MODULE *pmod, char *name, char *value, const CONF *cnf)
340f5b1c8a1SJohn Marino {
341f5b1c8a1SJohn Marino 	int ret = 1;
342f5b1c8a1SJohn Marino 	int init_called = 0;
343f5b1c8a1SJohn Marino 	CONF_IMODULE *imod = NULL;
344f5b1c8a1SJohn Marino 
345f5b1c8a1SJohn Marino 	/* Otherwise add initialized module to list */
346f5b1c8a1SJohn Marino 	imod = malloc(sizeof(CONF_IMODULE));
347f5b1c8a1SJohn Marino 	if (!imod)
348f5b1c8a1SJohn Marino 		goto err;
349f5b1c8a1SJohn Marino 
350f5b1c8a1SJohn Marino 	imod->pmod = pmod;
351f5b1c8a1SJohn Marino 	imod->name = name ? strdup(name) : NULL;
352f5b1c8a1SJohn Marino 	imod->value = value ? strdup(value) : NULL;
353f5b1c8a1SJohn Marino 	imod->usr_data = NULL;
354f5b1c8a1SJohn Marino 
355f5b1c8a1SJohn Marino 	if (!imod->name || !imod->value)
356f5b1c8a1SJohn Marino 		goto memerr;
357f5b1c8a1SJohn Marino 
358f5b1c8a1SJohn Marino 	/* Try to initialize module */
359f5b1c8a1SJohn Marino 	if (pmod->init) {
360f5b1c8a1SJohn Marino 		ret = pmod->init(imod, cnf);
361f5b1c8a1SJohn Marino 		init_called = 1;
362f5b1c8a1SJohn Marino 		/* Error occurred, exit */
363f5b1c8a1SJohn Marino 		if (ret <= 0)
364f5b1c8a1SJohn Marino 			goto err;
365f5b1c8a1SJohn Marino 	}
366f5b1c8a1SJohn Marino 
367f5b1c8a1SJohn Marino 	if (initialized_modules == NULL) {
368f5b1c8a1SJohn Marino 		initialized_modules = sk_CONF_IMODULE_new_null();
369f5b1c8a1SJohn Marino 		if (!initialized_modules) {
37072c33676SMaxim Ag 			CONFerror(ERR_R_MALLOC_FAILURE);
371f5b1c8a1SJohn Marino 			goto err;
372f5b1c8a1SJohn Marino 		}
373f5b1c8a1SJohn Marino 	}
374f5b1c8a1SJohn Marino 
375f5b1c8a1SJohn Marino 	if (!sk_CONF_IMODULE_push(initialized_modules, imod)) {
37672c33676SMaxim Ag 		CONFerror(ERR_R_MALLOC_FAILURE);
377f5b1c8a1SJohn Marino 		goto err;
378f5b1c8a1SJohn Marino 	}
379f5b1c8a1SJohn Marino 
380f5b1c8a1SJohn Marino 	pmod->links++;
381f5b1c8a1SJohn Marino 
382f5b1c8a1SJohn Marino 	return ret;
383f5b1c8a1SJohn Marino 
384f5b1c8a1SJohn Marino err:
385f5b1c8a1SJohn Marino 	/* We've started the module so we'd better finish it */
386f5b1c8a1SJohn Marino 	if (pmod->finish && init_called)
387f5b1c8a1SJohn Marino 		pmod->finish(imod);
388f5b1c8a1SJohn Marino 
389f5b1c8a1SJohn Marino memerr:
390f5b1c8a1SJohn Marino 	if (imod) {
391f5b1c8a1SJohn Marino 		free(imod->name);
392f5b1c8a1SJohn Marino 		free(imod->value);
393f5b1c8a1SJohn Marino 		free(imod);
394f5b1c8a1SJohn Marino 	}
395f5b1c8a1SJohn Marino 
396f5b1c8a1SJohn Marino 	return -1;
397f5b1c8a1SJohn Marino }
398f5b1c8a1SJohn Marino 
399f5b1c8a1SJohn Marino /* Unload any dynamic modules that have a link count of zero:
400f5b1c8a1SJohn Marino  * i.e. have no active initialized modules. If 'all' is set
401f5b1c8a1SJohn Marino  * then all modules are unloaded including static ones.
402f5b1c8a1SJohn Marino  */
403f5b1c8a1SJohn Marino 
404f5b1c8a1SJohn Marino void
CONF_modules_unload(int all)405f5b1c8a1SJohn Marino CONF_modules_unload(int all)
406f5b1c8a1SJohn Marino {
407f5b1c8a1SJohn Marino 	int i;
408f5b1c8a1SJohn Marino 	CONF_MODULE *md;
409f5b1c8a1SJohn Marino 
410f5b1c8a1SJohn Marino 	CONF_modules_finish();
411f5b1c8a1SJohn Marino 
412f5b1c8a1SJohn Marino 	/* unload modules in reverse order */
413f5b1c8a1SJohn Marino 	for (i = sk_CONF_MODULE_num(supported_modules) - 1; i >= 0; i--) {
414f5b1c8a1SJohn Marino 		md = sk_CONF_MODULE_value(supported_modules, i);
415f5b1c8a1SJohn Marino 		/* If static or in use and 'all' not set ignore it */
416f5b1c8a1SJohn Marino 		if (((md->links > 0) || !md->dso) && !all)
417f5b1c8a1SJohn Marino 			continue;
418f5b1c8a1SJohn Marino 		/* Since we're working in reverse this is OK */
419f5b1c8a1SJohn Marino 		(void)sk_CONF_MODULE_delete(supported_modules, i);
420f5b1c8a1SJohn Marino 		module_free(md);
421f5b1c8a1SJohn Marino 	}
422f5b1c8a1SJohn Marino 	if (sk_CONF_MODULE_num(supported_modules) == 0) {
423f5b1c8a1SJohn Marino 		sk_CONF_MODULE_free(supported_modules);
424f5b1c8a1SJohn Marino 		supported_modules = NULL;
425f5b1c8a1SJohn Marino 	}
426f5b1c8a1SJohn Marino }
427f5b1c8a1SJohn Marino 
428f5b1c8a1SJohn Marino /* unload a single module */
429f5b1c8a1SJohn Marino static void
module_free(CONF_MODULE * md)430f5b1c8a1SJohn Marino module_free(CONF_MODULE *md)
431f5b1c8a1SJohn Marino {
432f5b1c8a1SJohn Marino 	if (md->dso)
433f5b1c8a1SJohn Marino 		DSO_free(md->dso);
434f5b1c8a1SJohn Marino 	free(md->name);
435f5b1c8a1SJohn Marino 	free(md);
436f5b1c8a1SJohn Marino }
437f5b1c8a1SJohn Marino 
438f5b1c8a1SJohn Marino /* finish and free up all modules instances */
439f5b1c8a1SJohn Marino 
440f5b1c8a1SJohn Marino void
CONF_modules_finish(void)441f5b1c8a1SJohn Marino CONF_modules_finish(void)
442f5b1c8a1SJohn Marino {
443f5b1c8a1SJohn Marino 	CONF_IMODULE *imod;
444f5b1c8a1SJohn Marino 
445f5b1c8a1SJohn Marino 	while (sk_CONF_IMODULE_num(initialized_modules) > 0) {
446f5b1c8a1SJohn Marino 		imod = sk_CONF_IMODULE_pop(initialized_modules);
447f5b1c8a1SJohn Marino 		module_finish(imod);
448f5b1c8a1SJohn Marino 	}
449f5b1c8a1SJohn Marino 	sk_CONF_IMODULE_free(initialized_modules);
450f5b1c8a1SJohn Marino 	initialized_modules = NULL;
451f5b1c8a1SJohn Marino }
452f5b1c8a1SJohn Marino 
453f5b1c8a1SJohn Marino /* finish a module instance */
454f5b1c8a1SJohn Marino 
455f5b1c8a1SJohn Marino static void
module_finish(CONF_IMODULE * imod)456f5b1c8a1SJohn Marino module_finish(CONF_IMODULE *imod)
457f5b1c8a1SJohn Marino {
458f5b1c8a1SJohn Marino 	if (imod->pmod->finish)
459f5b1c8a1SJohn Marino 		imod->pmod->finish(imod);
460f5b1c8a1SJohn Marino 	imod->pmod->links--;
461f5b1c8a1SJohn Marino 	free(imod->name);
462f5b1c8a1SJohn Marino 	free(imod->value);
463f5b1c8a1SJohn Marino 	free(imod);
464f5b1c8a1SJohn Marino }
465f5b1c8a1SJohn Marino 
466f5b1c8a1SJohn Marino /* Add a static module to OpenSSL */
467f5b1c8a1SJohn Marino 
468f5b1c8a1SJohn Marino int
CONF_module_add(const char * name,conf_init_func * ifunc,conf_finish_func * ffunc)469f5b1c8a1SJohn Marino CONF_module_add(const char *name, conf_init_func *ifunc,
470f5b1c8a1SJohn Marino     conf_finish_func *ffunc)
471f5b1c8a1SJohn Marino {
472f5b1c8a1SJohn Marino 	if (module_add(NULL, name, ifunc, ffunc))
473f5b1c8a1SJohn Marino 		return 1;
474f5b1c8a1SJohn Marino 	else
475f5b1c8a1SJohn Marino 		return 0;
476f5b1c8a1SJohn Marino }
477f5b1c8a1SJohn Marino 
478f5b1c8a1SJohn Marino void
CONF_modules_free(void)479f5b1c8a1SJohn Marino CONF_modules_free(void)
480f5b1c8a1SJohn Marino {
481f5b1c8a1SJohn Marino 	CONF_modules_finish();
482f5b1c8a1SJohn Marino 	CONF_modules_unload(1);
483f5b1c8a1SJohn Marino }
484f5b1c8a1SJohn Marino 
485f5b1c8a1SJohn Marino /* Utility functions */
486f5b1c8a1SJohn Marino 
487f5b1c8a1SJohn Marino const char *
CONF_imodule_get_name(const CONF_IMODULE * md)488f5b1c8a1SJohn Marino CONF_imodule_get_name(const CONF_IMODULE *md)
489f5b1c8a1SJohn Marino {
490f5b1c8a1SJohn Marino 	return md->name;
491f5b1c8a1SJohn Marino }
492f5b1c8a1SJohn Marino 
493f5b1c8a1SJohn Marino const char *
CONF_imodule_get_value(const CONF_IMODULE * md)494f5b1c8a1SJohn Marino CONF_imodule_get_value(const CONF_IMODULE *md)
495f5b1c8a1SJohn Marino {
496f5b1c8a1SJohn Marino 	return md->value;
497f5b1c8a1SJohn Marino }
498f5b1c8a1SJohn Marino 
499f5b1c8a1SJohn Marino void *
CONF_imodule_get_usr_data(const CONF_IMODULE * md)500f5b1c8a1SJohn Marino CONF_imodule_get_usr_data(const CONF_IMODULE *md)
501f5b1c8a1SJohn Marino {
502f5b1c8a1SJohn Marino 	return md->usr_data;
503f5b1c8a1SJohn Marino }
504f5b1c8a1SJohn Marino 
505f5b1c8a1SJohn Marino void
CONF_imodule_set_usr_data(CONF_IMODULE * md,void * usr_data)506f5b1c8a1SJohn Marino CONF_imodule_set_usr_data(CONF_IMODULE *md, void *usr_data)
507f5b1c8a1SJohn Marino {
508f5b1c8a1SJohn Marino 	md->usr_data = usr_data;
509f5b1c8a1SJohn Marino }
510f5b1c8a1SJohn Marino 
511f5b1c8a1SJohn Marino CONF_MODULE *
CONF_imodule_get_module(const CONF_IMODULE * md)512f5b1c8a1SJohn Marino CONF_imodule_get_module(const CONF_IMODULE *md)
513f5b1c8a1SJohn Marino {
514f5b1c8a1SJohn Marino 	return md->pmod;
515f5b1c8a1SJohn Marino }
516f5b1c8a1SJohn Marino 
517f5b1c8a1SJohn Marino unsigned long
CONF_imodule_get_flags(const CONF_IMODULE * md)518f5b1c8a1SJohn Marino CONF_imodule_get_flags(const CONF_IMODULE *md)
519f5b1c8a1SJohn Marino {
520f5b1c8a1SJohn Marino 	return md->flags;
521f5b1c8a1SJohn Marino }
522f5b1c8a1SJohn Marino 
523f5b1c8a1SJohn Marino void
CONF_imodule_set_flags(CONF_IMODULE * md,unsigned long flags)524f5b1c8a1SJohn Marino CONF_imodule_set_flags(CONF_IMODULE *md, unsigned long flags)
525f5b1c8a1SJohn Marino {
526f5b1c8a1SJohn Marino 	md->flags = flags;
527f5b1c8a1SJohn Marino }
528f5b1c8a1SJohn Marino 
529f5b1c8a1SJohn Marino void *
CONF_module_get_usr_data(CONF_MODULE * pmod)530f5b1c8a1SJohn Marino CONF_module_get_usr_data(CONF_MODULE *pmod)
531f5b1c8a1SJohn Marino {
532f5b1c8a1SJohn Marino 	return pmod->usr_data;
533f5b1c8a1SJohn Marino }
534f5b1c8a1SJohn Marino 
535f5b1c8a1SJohn Marino void
CONF_module_set_usr_data(CONF_MODULE * pmod,void * usr_data)536f5b1c8a1SJohn Marino CONF_module_set_usr_data(CONF_MODULE *pmod, void *usr_data)
537f5b1c8a1SJohn Marino {
538f5b1c8a1SJohn Marino 	pmod->usr_data = usr_data;
539f5b1c8a1SJohn Marino }
540f5b1c8a1SJohn Marino 
541f5b1c8a1SJohn Marino /* Return default config file name */
542f5b1c8a1SJohn Marino 
543f5b1c8a1SJohn Marino char *
CONF_get1_default_config_file(void)544f5b1c8a1SJohn Marino CONF_get1_default_config_file(void)
545f5b1c8a1SJohn Marino {
546f5b1c8a1SJohn Marino 	char *file = NULL;
547f5b1c8a1SJohn Marino 
548f5b1c8a1SJohn Marino 	if (asprintf(&file, "%s/openssl.cnf",
549f5b1c8a1SJohn Marino 	    X509_get_default_cert_area()) == -1)
550f5b1c8a1SJohn Marino 		return (NULL);
551f5b1c8a1SJohn Marino 	return file;
552f5b1c8a1SJohn Marino }
553f5b1c8a1SJohn Marino 
554f5b1c8a1SJohn Marino /* This function takes a list separated by 'sep' and calls the
555f5b1c8a1SJohn Marino  * callback function giving the start and length of each member
556f5b1c8a1SJohn Marino  * optionally stripping leading and trailing whitespace. This can
557f5b1c8a1SJohn Marino  * be used to parse comma separated lists for example.
558f5b1c8a1SJohn Marino  */
559f5b1c8a1SJohn Marino 
560f5b1c8a1SJohn Marino int
CONF_parse_list(const char * list_,int sep,int nospc,int (* list_cb)(const char * elem,int len,void * usr),void * arg)561f5b1c8a1SJohn Marino CONF_parse_list(const char *list_, int sep, int nospc,
562f5b1c8a1SJohn Marino     int (*list_cb)(const char *elem, int len, void *usr), void *arg)
563f5b1c8a1SJohn Marino {
564f5b1c8a1SJohn Marino 	int ret;
565f5b1c8a1SJohn Marino 	const char *lstart, *tmpend, *p;
566f5b1c8a1SJohn Marino 
567f5b1c8a1SJohn Marino 	if (list_ == NULL) {
56872c33676SMaxim Ag 		CONFerror(CONF_R_LIST_CANNOT_BE_NULL);
569f5b1c8a1SJohn Marino 		return 0;
570f5b1c8a1SJohn Marino 	}
571f5b1c8a1SJohn Marino 
572f5b1c8a1SJohn Marino 	lstart = list_;
573f5b1c8a1SJohn Marino 	for (;;) {
574f5b1c8a1SJohn Marino 		if (nospc) {
575f5b1c8a1SJohn Marino 			while (*lstart && isspace((unsigned char)*lstart))
576f5b1c8a1SJohn Marino 				lstart++;
577f5b1c8a1SJohn Marino 		}
578f5b1c8a1SJohn Marino 		p = strchr(lstart, sep);
579f5b1c8a1SJohn Marino 		if (p == lstart || !*lstart)
580f5b1c8a1SJohn Marino 			ret = list_cb(NULL, 0, arg);
581f5b1c8a1SJohn Marino 		else {
582f5b1c8a1SJohn Marino 			if (p)
583f5b1c8a1SJohn Marino 				tmpend = p - 1;
584f5b1c8a1SJohn Marino 			else
585f5b1c8a1SJohn Marino 				tmpend = lstart + strlen(lstart) - 1;
586f5b1c8a1SJohn Marino 			if (nospc) {
587f5b1c8a1SJohn Marino 				while (isspace((unsigned char)*tmpend))
588f5b1c8a1SJohn Marino 					tmpend--;
589f5b1c8a1SJohn Marino 			}
590f5b1c8a1SJohn Marino 			ret = list_cb(lstart, tmpend - lstart + 1, arg);
591f5b1c8a1SJohn Marino 		}
592f5b1c8a1SJohn Marino 		if (ret <= 0)
593f5b1c8a1SJohn Marino 			return ret;
594f5b1c8a1SJohn Marino 		if (p == NULL)
595f5b1c8a1SJohn Marino 			return 1;
596f5b1c8a1SJohn Marino 		lstart = p + 1;
597f5b1c8a1SJohn Marino 	}
598f5b1c8a1SJohn Marino }
599