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_
sasl_config_init(_sasl_global_context_t * gctx,const char * filename)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