xref: /illumos-gate/usr/src/lib/libsasl/lib/config.c (revision 004388eb)
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 
73 struct configlist {
74     char *key;
75     char *value;
76 };
77 
78 #ifndef _SUN_SDK_
79 static struct configlist *configlist;
80 static int nconfiglist;
81 #endif /* !_SUN_SDK_ */
82 
83 #define CONFIGLISTGROWSIZE 100
84 
85 #ifdef _SUN_SDK_
86 int sasl_config_init(_sasl_global_context_t *gctx, const char *filename)
87 #else
88 int 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 
209 done:
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() */
228 void 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 
249 const 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
263 const 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_
277 int sasl_config_getint(_sasl_global_context_t *gctx, const char *key,int def)
278 #else
279 int 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_
294 int sasl_config_getswitch(_sasl_global_context_t *gctx,const char *key,int def)
295 #else
296 int 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