Home | History | Annotate | Download | only in lib
      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 (at) 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