1/* conf_lib.c */
2/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
3 * project 2000.
4 */
5/* ====================================================================
6 * Copyright (c) 2000 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 <openssl/err.h>
62#include <openssl/conf.h>
63#include <openssl/conf_api.h>
64#include <openssl/lhash.h>
65
66const char CONF_version[]="CONF" OPENSSL_VERSION_PTEXT;
67
68static CONF_METHOD *default_CONF_method=NULL;
69
70/* Init a 'CONF' structure from an old LHASH */
71
72void CONF_set_nconf(CONF *conf, LHASH *hash)
73	{
74	if (default_CONF_method == NULL)
75		default_CONF_method = NCONF_default();
76
77	default_CONF_method->init(conf);
78	conf->data = hash;
79	}
80
81/* The following section contains the "CONF classic" functions,
82   rewritten in terms of the new CONF interface. */
83
84int CONF_set_default_method(CONF_METHOD *meth)
85	{
86	default_CONF_method = meth;
87	return 1;
88	}
89
90LHASH *CONF_load(LHASH *conf, const char *file, long *eline)
91	{
92	LHASH *ltmp;
93	BIO *in=NULL;
94
95#ifdef OPENSSL_SYS_VMS
96	in=BIO_new_file(file, "r");
97#else
98	in=BIO_new_file(file, "rb");
99#endif
100	if (in == NULL)
101		{
102		CONFerr(CONF_F_CONF_LOAD,ERR_R_SYS_LIB);
103		return NULL;
104		}
105
106	ltmp = CONF_load_bio(conf, in, eline);
107	BIO_free(in);
108
109	return ltmp;
110	}
111
112#ifndef OPENSSL_NO_FP_API
113LHASH *CONF_load_fp(LHASH *conf, FILE *fp,long *eline)
114	{
115	BIO *btmp;
116	LHASH *ltmp;
117	if(!(btmp = BIO_new_fp(fp, BIO_NOCLOSE))) {
118		CONFerr(CONF_F_CONF_LOAD_FP,ERR_R_BUF_LIB);
119		return NULL;
120	}
121	ltmp = CONF_load_bio(conf, btmp, eline);
122	BIO_free(btmp);
123	return ltmp;
124	}
125#endif
126
127LHASH *CONF_load_bio(LHASH *conf, BIO *bp,long *eline)
128	{
129	CONF ctmp;
130	int ret;
131
132	CONF_set_nconf(&ctmp, conf);
133
134	ret = NCONF_load_bio(&ctmp, bp, eline);
135	if (ret)
136		return ctmp.data;
137	return NULL;
138	}
139
140STACK_OF(CONF_VALUE) *CONF_get_section(LHASH *conf,const char *section)
141	{
142	if (conf == NULL)
143		{
144		return NULL;
145		}
146	else
147		{
148		CONF ctmp;
149		CONF_set_nconf(&ctmp, conf);
150		return NCONF_get_section(&ctmp, section);
151		}
152	}
153
154char *CONF_get_string(LHASH *conf,const char *group,const char *name)
155	{
156	if (conf == NULL)
157		{
158		return NCONF_get_string(NULL, group, name);
159		}
160	else
161		{
162		CONF ctmp;
163		CONF_set_nconf(&ctmp, conf);
164		return NCONF_get_string(&ctmp, group, name);
165		}
166	}
167
168long CONF_get_number(LHASH *conf,const char *group,const char *name)
169	{
170	int status;
171	long result = 0;
172
173	if (conf == NULL)
174		{
175		status = NCONF_get_number_e(NULL, group, name, &result);
176		}
177	else
178		{
179		CONF ctmp;
180		CONF_set_nconf(&ctmp, conf);
181		status = NCONF_get_number_e(&ctmp, group, name, &result);
182		}
183
184	if (status == 0)
185		{
186		/* This function does not believe in errors... */
187		ERR_clear_error();
188		}
189	return result;
190	}
191
192void CONF_free(LHASH *conf)
193	{
194	CONF ctmp;
195	CONF_set_nconf(&ctmp, conf);
196	NCONF_free_data(&ctmp);
197	}
198
199#ifndef OPENSSL_NO_FP_API
200int CONF_dump_fp(LHASH *conf, FILE *out)
201	{
202	BIO *btmp;
203	int ret;
204
205	if(!(btmp = BIO_new_fp(out, BIO_NOCLOSE))) {
206		CONFerr(CONF_F_CONF_DUMP_FP,ERR_R_BUF_LIB);
207		return 0;
208	}
209	ret = CONF_dump_bio(conf, btmp);
210	BIO_free(btmp);
211	return ret;
212	}
213#endif
214
215int CONF_dump_bio(LHASH *conf, BIO *out)
216	{
217	CONF ctmp;
218	CONF_set_nconf(&ctmp, conf);
219	return NCONF_dump_bio(&ctmp, out);
220	}
221
222/* The following section contains the "New CONF" functions.  They are
223   completely centralised around a new CONF structure that may contain
224   basically anything, but at least a method pointer and a table of data.
225   These functions are also written in terms of the bridge functions used
226   by the "CONF classic" functions, for consistency.  */
227
228CONF *NCONF_new(CONF_METHOD *meth)
229	{
230	CONF *ret;
231
232	if (meth == NULL)
233		meth = NCONF_default();
234
235	ret = meth->create(meth);
236	if (ret == NULL)
237		{
238		CONFerr(CONF_F_NCONF_NEW,ERR_R_MALLOC_FAILURE);
239		return(NULL);
240		}
241
242	return ret;
243	}
244
245void NCONF_free(CONF *conf)
246	{
247	if (conf == NULL)
248		return;
249	conf->meth->destroy(conf);
250	}
251
252void NCONF_free_data(CONF *conf)
253	{
254	if (conf == NULL)
255		return;
256	conf->meth->destroy_data(conf);
257	}
258
259int NCONF_load(CONF *conf, const char *file, long *eline)
260	{
261	if (conf == NULL)
262		{
263		CONFerr(CONF_F_NCONF_LOAD,CONF_R_NO_CONF);
264		return 0;
265		}
266
267	return conf->meth->load(conf, file, eline);
268	}
269
270#ifndef OPENSSL_NO_FP_API
271int NCONF_load_fp(CONF *conf, FILE *fp,long *eline)
272	{
273	BIO *btmp;
274	int ret;
275	if(!(btmp = BIO_new_fp(fp, BIO_NOCLOSE)))
276		{
277		CONFerr(CONF_F_NCONF_LOAD_FP,ERR_R_BUF_LIB);
278		return 0;
279		}
280	ret = NCONF_load_bio(conf, btmp, eline);
281	BIO_free(btmp);
282	return ret;
283	}
284#endif
285
286int NCONF_load_bio(CONF *conf, BIO *bp,long *eline)
287	{
288	if (conf == NULL)
289		{
290		CONFerr(CONF_F_NCONF_LOAD_BIO,CONF_R_NO_CONF);
291		return 0;
292		}
293
294	return conf->meth->load_bio(conf, bp, eline);
295	}
296
297STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf,const char *section)
298	{
299	if (conf == NULL)
300		{
301		CONFerr(CONF_F_NCONF_GET_SECTION,CONF_R_NO_CONF);
302		return NULL;
303		}
304
305	if (section == NULL)
306		{
307		CONFerr(CONF_F_NCONF_GET_SECTION,CONF_R_NO_SECTION);
308		return NULL;
309		}
310
311	return _CONF_get_section_values(conf, section);
312	}
313
314char *NCONF_get_string(const CONF *conf,const char *group,const char *name)
315	{
316	char *s = _CONF_get_string(conf, group, name);
317
318        /* Since we may get a value from an environment variable even
319           if conf is NULL, let's check the value first */
320        if (s) return s;
321
322	if (conf == NULL)
323		{
324		CONFerr(CONF_F_NCONF_GET_STRING,
325                        CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE);
326		return NULL;
327		}
328	CONFerr(CONF_F_NCONF_GET_STRING,
329		CONF_R_NO_VALUE);
330	ERR_add_error_data(4,"group=",group," name=",name);
331	return NULL;
332	}
333
334int NCONF_get_number_e(const CONF *conf,const char *group,const char *name,
335		       long *result)
336	{
337	char *str;
338
339	if (result == NULL)
340		{
341		CONFerr(CONF_F_NCONF_GET_NUMBER_E,ERR_R_PASSED_NULL_PARAMETER);
342		return 0;
343		}
344
345	str = NCONF_get_string(conf,group,name);
346
347	if (str == NULL)
348		return 0;
349
350	for (*result = 0;conf->meth->is_number(conf, *str);)
351		{
352		*result = (*result)*10 + conf->meth->to_int(conf, *str);
353		str++;
354		}
355
356	return 1;
357	}
358
359#ifndef OPENSSL_NO_FP_API
360int NCONF_dump_fp(const CONF *conf, FILE *out)
361	{
362	BIO *btmp;
363	int ret;
364	if(!(btmp = BIO_new_fp(out, BIO_NOCLOSE))) {
365		CONFerr(CONF_F_NCONF_DUMP_FP,ERR_R_BUF_LIB);
366		return 0;
367	}
368	ret = NCONF_dump_bio(conf, btmp);
369	BIO_free(btmp);
370	return ret;
371	}
372#endif
373
374int NCONF_dump_bio(const CONF *conf, BIO *out)
375	{
376	if (conf == NULL)
377		{
378		CONFerr(CONF_F_NCONF_DUMP_BIO,CONF_R_NO_CONF);
379		return 0;
380		}
381
382	return conf->meth->dump(conf, out);
383	}
384
385
386/* This function should be avoided */
387#if 0
388long NCONF_get_number(CONF *conf,char *group,char *name)
389	{
390	int status;
391	long ret=0;
392
393	status = NCONF_get_number_e(conf, group, name, &ret);
394	if (status == 0)
395		{
396		/* This function does not believe in errors... */
397		ERR_get_error();
398		}
399	return ret;
400	}
401#endif
402