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_ 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