1/*
2 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
3 * Use is subject to license terms.
4 */
5#pragma ident	"%Z%%M%	%I%	%E% SMI"
6
7/* SASL Config file API
8 * Rob Siemborski
9 * Tim Martin (originally in Cyrus distribution)
10 * $Id: config.c,v 1.13 2003/02/13 19:55:54 rjs3 Exp $
11 */
12/*
13 * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 *
19 * 1. Redistributions of source code must retain the above copyright
20 *    notice, this list of conditions and the following disclaimer.
21 *
22 * 2. Redistributions in binary form must reproduce the above copyright
23 *    notice, this list of conditions and the following disclaimer in
24 *    the documentation and/or other materials provided with the
25 *    distribution.
26 *
27 * 3. The name "Carnegie Mellon University" must not be used to
28 *    endorse or promote products derived from this software without
29 *    prior written permission. For permission or any other legal
30 *    details, please contact
31 *      Office of Technology Transfer
32 *      Carnegie Mellon University
33 *      5000 Forbes Avenue
34 *      Pittsburgh, PA  15213-3890
35 *      (412) 268-4387, fax: (412) 268-7395
36 *      tech-transfer@andrew.cmu.edu
37 *
38 * 4. Redistributions of any form whatsoever must retain the following
39 *    acknowledgment:
40 *    "This product includes software developed by Computing Services
41 *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
42 *
43 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
44 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
45 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
46 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
47 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
48 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
49 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
50 */
51
52/*
53 * Current Valid keys:
54 *
55 * canon_user_plugin: <string>
56 * pwcheck_method: <string>
57 * auto_transition: <boolean>
58 * plugin_list: <string>
59 *
60 * srvtab: <string>
61 */
62
63
64#include "sasl.h"
65#include "saslint.h"
66
67#include <stdio.h>
68#include <stdlib.h>
69#include <ctype.h>
70
71#include "config.h"	/* _SUN_SDK_ */
72
73struct configlist {
74    char *key;
75    char *value;
76};
77
78#ifndef _SUN_SDK_
79static struct configlist *configlist;
80static int nconfiglist;
81#endif /* !_SUN_SDK_ */
82
83#define CONFIGLISTGROWSIZE 100
84
85#ifdef _SUN_SDK_
86int sasl_config_init(_sasl_global_context_t *gctx, const char *filename)
87#else
88int sasl_config_init(const char *filename)
89#endif /* _SUN_SDK_ */
90{
91    FILE *infile;
92    int lineno = 0;
93    int alloced = 0;
94    char buf[4096];
95    char *p, *key;
96    int result;
97#ifdef _SUN_SDK_
98    int invalid_line = 0;
99
100    gctx->nconfiglist=0;
101#else
102    nconfiglist=0;
103#endif /* _SUN_SDK_ */
104
105    infile = fopen(filename, "rF");
106    if (!infile) {
107      return SASL_CONTINUE;
108    }
109#ifdef _SUN_SDK_
110    result = _sasl_strdup(filename, &gctx->config_path, NULL);
111    if (result != SASL_OK)
112	goto done;
113#endif /* _SUN_SDK_ */
114
115    while (fgets(buf, sizeof(buf), infile)) {
116	lineno++;
117
118	if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
119	for (p = buf; *p && isspace((int) *p); p++);
120	if (!*p || *p == '#') continue;
121
122	key = p;
123	while (*p && (isalnum((int) *p) || *p == '-' || *p == '_')) {
124	    if (isupper((int) *p)) *p = tolower(*p);
125	    p++;
126	}
127	if (*p != ':') {
128#ifdef _SUN_SDK_
129	  invalid_line = 1;
130	  goto done;
131#else
132	  return SASL_FAIL;
133#endif /* _SUN_SDK_ */
134	}
135	*p++ = '\0';
136
137	while (*p && isspace((int) *p)) p++;
138
139	if (!*p) {
140#ifdef _SUN_SDK_
141	  invalid_line = 1;
142	  goto done;
143#else
144	  return SASL_FAIL;
145#endif /* _SUN_SDK_ */
146	}
147
148#ifdef _SUN_SDK_
149	if (gctx->nconfiglist == alloced) {
150#else
151	if (nconfiglist == alloced) {
152#endif /* _SUN_SDK_ */
153	    alloced += CONFIGLISTGROWSIZE;
154#ifdef _SUN_SDK_
155	    gctx->configlist=sasl_REALLOC((char *)gctx->configlist,
156				    alloced * sizeof(struct configlist));
157	    if (gctx->configlist==NULL) {
158		result = SASL_NOMEM;
159		goto done;
160	    }
161#else
162	    configlist=sasl_REALLOC((char *)configlist,
163				    alloced * sizeof(struct configlist));
164	    if (configlist==NULL) return SASL_NOMEM;
165#endif /* _SUN_SDK_ */
166	}
167
168
169
170#ifdef _SUN_SDK_
171	result = _sasl_strdup(key,
172			      &(((struct configlist *)(gctx->configlist))
173				[gctx->nconfiglist].key),
174			      NULL);
175	if (result!=SASL_OK)
176	  goto done;
177#else
178	result = _sasl_strdup(key,
179			      &(configlist[nconfiglist].key),
180			      NULL);
181	if (result!=SASL_OK) return result;
182#endif /* _SUN_SDK_ */
183#ifdef _SUN_SDK_
184	result = _sasl_strdup(p,
185			      &(((struct configlist *)(gctx->configlist))
186				[gctx->nconfiglist].value),
187			      NULL);
188	if (result!=SASL_OK) {
189	    sasl_FREE(((struct configlist *)(gctx->configlist))
190				[gctx->nconfiglist].key);
191	    goto done;
192	}
193#else
194	result = _sasl_strdup(p,
195			      &(configlist[nconfiglist].value),
196			      NULL);
197	if (result!=SASL_OK) return result;
198#endif /* _SUN_SDK_ */
199
200#ifdef _SUN_SDK_
201	(gctx->nconfiglist)++;
202#else
203	nconfiglist++;
204#endif /* _SUN_SDK_ */
205    }
206#ifdef _SUN_SDK_
207    result = SASL_OK;
208
209done:
210    fclose(infile);
211
212    if (invalid_line) {
213	__sasl_log(gctx, gctx->server_global_callbacks.callbacks,
214		   SASL_LOG_ERR, "%s: bad config line: '%s'", filename, buf);
215	result = SASL_FAIL;
216    }
217
218    return result;
219#else
220    fclose(infile);
221
222    return SASL_OK;
223#endif /* _SUN_SDK_ */
224}
225
226#ifdef _SUN_SDK_
227/* Releases the resources acquired in sasl_config_init() */
228void sasl_config_free(_sasl_global_context_t *gctx)
229{
230    int i;
231
232    if (gctx->config_path != NULL)
233	sasl_FREE(gctx->config_path);
234    gctx->config_path = NULL;
235    if (gctx->configlist == NULL)
236	return;
237
238    for (i = 0; i < gctx->nconfiglist; i++) {
239	if ((((struct configlist *)gctx->configlist))[i].key)
240	    sasl_FREE(((struct configlist *)gctx->configlist)[i].key);
241	if (((struct configlist *)gctx->configlist)[i].value)
242	    sasl_FREE(((struct configlist *)gctx->configlist)[i].value);
243    }
244    sasl_FREE(gctx->configlist);
245    gctx->configlist = NULL;
246    gctx->nconfiglist = 0;
247}
248
249const char *sasl_config_getstring(_sasl_global_context_t *gctx,
250	const char *key, const char *def)
251{
252    int opt;
253    struct configlist *clist = (struct configlist *)gctx->configlist;
254
255    for (opt = 0; opt < gctx->nconfiglist; opt++) {
256	if (*key == clist[opt].key[0] &&
257	    !strcmp(key, clist[opt].key))
258	  return clist[opt].value;
259    }
260    return def;
261}
262#else
263const char *sasl_config_getstring(const char *key,const char *def)
264{
265    int opt;
266
267    for (opt = 0; opt < nconfiglist; opt++) {
268	if (*key == configlist[opt].key[0] &&
269	    !strcmp(key, configlist[opt].key))
270	  return configlist[opt].value;
271    }
272    return def;
273}
274#endif /* _SUN_SDK_ */
275
276#ifdef _SUN_SDK_
277int sasl_config_getint(_sasl_global_context_t *gctx, const char *key,int def)
278#else
279int sasl_config_getint(const char *key,int def)
280#endif /* _SUN_SDK_ */
281{
282#ifdef _SUN_SDK_
283    const char *val = sasl_config_getstring(gctx, key, (char *)0);
284#else
285    const char *val = sasl_config_getstring(key, (char *)0);
286#endif /* _SUN_SDK_ */
287
288    if (!val) return def;
289    if (!isdigit((int) *val) && (*val != '-' || !isdigit((int) val[1]))) return def;
290    return atoi(val);
291}
292
293#ifdef _SUN_SDK_
294int sasl_config_getswitch(_sasl_global_context_t *gctx,const char *key,int def)
295#else
296int sasl_config_getswitch(const char *key,int def)
297#endif /* _SUN_SDK_ */
298{
299#ifdef _SUN_SDK_
300    const char *val = sasl_config_getstring(gctx, key, (char *)0);
301#else
302    const char *val = sasl_config_getstring(key, (char *)0);
303#endif /* _SUN_SDK_ */
304
305    if (!val) return def;
306
307    if (*val == '0' || *val == 'n' ||
308	(*val == 'o' && val[1] == 'f') || *val == 'f') {
309	return 0;
310    }
311    else if (*val == '1' || *val == 'y' ||
312	     (*val == 'o' && val[1] == 'n') || *val == 't') {
313	return 1;
314    }
315    return def;
316}
317
318