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