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