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