Home | History | Annotate | Download | only in radius
      1 /*
      2  * $Id: dict.c,v 1.1 2004/11/14 07:26:26 paulus Exp $
      3  *
      4  * Copyright (C) 2002 Roaring Penguin Software Inc.
      5  *
      6  * Copyright (C) 1995,1996,1997 Lars Fenneberg
      7  *
      8  * Copyright 1992 Livingston Enterprises, Inc.
      9  *
     10  * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan
     11  * and Merit Network, Inc. All Rights Reserved
     12  *
     13  * See the file COPYRIGHT for the respective terms and conditions.
     14  * If the file is missing contact me at lf (at) elemental.net
     15  * and I'll send you a copy.
     16  *
     17  */
     18 
     19 #include <includes.h>
     20 #include <radiusclient.h>
     21 
     22 static DICT_ATTR *dictionary_attributes = NULL;
     23 static DICT_VALUE *dictionary_values = NULL;
     24 static VENDOR_DICT *vendor_dictionaries = NULL;
     25 
     26 /*
     27  * Function: rc_read_dictionary
     28  *
     29  * Purpose: Initialize the dictionary.  Read all ATTRIBUTES into
     30  *	    the dictionary_attributes list.  Read all VALUES into
     31  *	    the dictionary_values list.  Construct VENDOR dictionaries
     32  *          as required.
     33  *
     34  */
     35 
     36 int rc_read_dictionary (char *filename)
     37 {
     38 	FILE           *dictfd;
     39 	char            dummystr[AUTH_ID_LEN];
     40 	char            namestr[AUTH_ID_LEN];
     41 	char            valstr[AUTH_ID_LEN];
     42 	char            attrstr[AUTH_ID_LEN];
     43 	char            typestr[AUTH_ID_LEN];
     44 	char            vendorstr[AUTH_ID_LEN];
     45 	int             line_no;
     46 	DICT_ATTR      *attr;
     47 	DICT_VALUE     *dval;
     48 	VENDOR_DICT    *vdict;
     49 	char            buffer[256];
     50 	int             value;
     51 	int             type;
     52 	int             n;
     53 	int             retcode;
     54 	if ((dictfd = fopen (filename, "r")) == (FILE *) NULL)
     55 	{
     56 		error( "rc_read_dictionary: couldn't open dictionary %s: %s",
     57 				filename, strerror(errno));
     58 		return (-1);
     59 	}
     60 
     61 	line_no = 0;
     62 	retcode = 0;
     63 	while (fgets (buffer, sizeof (buffer), dictfd) != (char *) NULL)
     64 	{
     65 		line_no++;
     66 
     67 		/* Skip empty space */
     68 		if (*buffer == '#' || *buffer == '\0' || *buffer == '\n')
     69 		{
     70 			continue;
     71 		}
     72 
     73 		if (strncmp (buffer, "VENDOR", 6) == 0) {
     74 		    /* Read the VENDOR line */
     75 		    if (sscanf(buffer, "%s%s%d", dummystr, namestr, &value) != 3) {
     76 			error("rc_read_dictionary: invalid vendor on line %d of dictionary %s",
     77 			      line_no, filename);
     78 			retcode = -1;
     79 			break;
     80 		    }
     81 		    /* Validate entry */
     82 		    if (strlen (namestr) > NAME_LENGTH) {
     83 			error("rc_read_dictionary: invalid name length on line %d of dictionary %s",
     84 			      line_no, filename);
     85 			retcode = -1;
     86 			break;
     87 		    }
     88 		    /* Create new vendor entry */
     89 		    vdict = (VENDOR_DICT *) malloc (sizeof (VENDOR_DICT));
     90 		    if (!vdict) {
     91 			novm("rc_read_dictionary");
     92 			retcode = -1;
     93 			break;
     94 		    }
     95 		    strcpy(vdict->vendorname, namestr);
     96 		    vdict->vendorcode = value;
     97 		    vdict->attributes = NULL;
     98 		    vdict->next = vendor_dictionaries;
     99 		    vendor_dictionaries = vdict;
    100 		}
    101 		else if (strncmp (buffer, "ATTRIBUTE", 9) == 0)
    102 		{
    103 
    104 			/* Read the ATTRIBUTE line.  It is one of:
    105 			 * ATTRIBUTE attr_name attr_val type         OR
    106 			 * ATTRIBUTE attr_name attr_val type vendor  */
    107 			vendorstr[0] = 0;
    108 			n = sscanf(buffer, "%s%s%s%s%s", dummystr, namestr, valstr, typestr, vendorstr);
    109 			if (n != 4 && n != 5)
    110 			{
    111 				error("rc_read_dictionary: invalid attribute on line %d of dictionary %s",
    112 				      line_no, filename);
    113 				retcode = -1;
    114 				break;
    115 			}
    116 
    117 			/*
    118 			 * Validate all entries
    119 			 */
    120 			if (strlen (namestr) > NAME_LENGTH)
    121 			{
    122 				error("rc_read_dictionary: invalid name length on line %d of dictionary %s",
    123 				      line_no, filename);
    124 				retcode = -1;
    125 				break;
    126 			}
    127 
    128 			if (strlen (vendorstr) > NAME_LENGTH)
    129 			{
    130 				error("rc_read_dictionary: invalid name length on line %d of dictionary %s",
    131 				      line_no, filename);
    132 				retcode = -1;
    133 				break;
    134 			}
    135 
    136 			if (!isdigit (*valstr))
    137 			{
    138 				error("rc_read_dictionary: invalid value on line %d of dictionary %s",
    139 				      line_no, filename);
    140 				retcode = -1;
    141 				break;
    142 			}
    143 			value = atoi (valstr);
    144 
    145 			if (strcmp (typestr, "string") == 0)
    146 			{
    147 				type = PW_TYPE_STRING;
    148 			}
    149 			else if (strcmp (typestr, "integer") == 0)
    150 			{
    151 				type = PW_TYPE_INTEGER;
    152 			}
    153 			else if (strcmp (typestr, "ipaddr") == 0)
    154 			{
    155 				type = PW_TYPE_IPADDR;
    156 			}
    157 			else if (strcmp (typestr, "date") == 0)
    158 			{
    159 				type = PW_TYPE_DATE;
    160 			}
    161 			else
    162 			{
    163 				error("rc_read_dictionary: invalid type on line %d of dictionary %s",
    164 				      line_no, filename);
    165 				retcode = -1;
    166 				break;
    167 			}
    168 
    169 			/* Search for vendor if supplied */
    170 			if (*vendorstr) {
    171 			    vdict = rc_dict_findvendor(vendorstr);
    172 			    if (!vdict) {
    173 				    error("rc_read_dictionary: unknown vendor on line %d of dictionary %s",
    174 					  line_no, filename);
    175 				    retcode = -1;
    176 				    break;
    177 			    }
    178 			} else {
    179 			    vdict = NULL;
    180 			}
    181 			/* Create a new attribute for the list */
    182 			if ((attr =
    183 				(DICT_ATTR *) malloc (sizeof (DICT_ATTR)))
    184 							== (DICT_ATTR *) NULL)
    185 			{
    186 				novm("rc_read_dictionary");
    187 				retcode = -1;
    188 				break;
    189 			}
    190 			strcpy (attr->name, namestr);
    191 			if (vdict) {
    192 			    attr->vendorcode = vdict->vendorcode;
    193 			} else {
    194 			    attr->vendorcode = VENDOR_NONE;
    195 			}
    196 			attr->value = value;
    197 			attr->type = type;
    198 
    199 			/* Insert it into the list */
    200 			if (vdict) {
    201 			    attr->next = vdict->attributes;
    202 			    vdict->attributes = attr;
    203 			} else {
    204 			    attr->next = dictionary_attributes;
    205 			    dictionary_attributes = attr;
    206 			}
    207 		}
    208 		else if (strncmp (buffer, "VALUE", 5) == 0)
    209 		{
    210 			/* Read the VALUE line */
    211 			if (sscanf (buffer, "%s%s%s%s", dummystr, attrstr,
    212 				    namestr, valstr) != 4)
    213 			{
    214 				error("rc_read_dictionary: invalid value entry on line %d of dictionary %s",
    215 				      line_no, filename);
    216 				retcode = -1;
    217 				break;
    218 			}
    219 
    220 			/*
    221 			 * Validate all entries
    222 			 */
    223 			if (strlen (attrstr) > NAME_LENGTH)
    224 			{
    225 				error("rc_read_dictionary: invalid attribute length on line %d of dictionary %s",
    226 				      line_no, filename);
    227 				retcode = -1;
    228 				break;
    229 			}
    230 
    231 			if (strlen (namestr) > NAME_LENGTH)
    232 			{
    233 				error("rc_read_dictionary: invalid name length on line %d of dictionary %s",
    234 				      line_no, filename);
    235 				retcode = -1;
    236 				break;
    237 			}
    238 
    239 			if (!isdigit (*valstr))
    240 			{
    241 				error("rc_read_dictionary: invalid value on line %d of dictionary %s",
    242 				      line_no, filename);
    243 				retcode = -1;
    244 				break;
    245 			}
    246 			value = atoi (valstr);
    247 
    248 			/* Create a new VALUE entry for the list */
    249 			if ((dval =
    250 				(DICT_VALUE *) malloc (sizeof (DICT_VALUE)))
    251 							== (DICT_VALUE *) NULL)
    252 			{
    253 				novm("rc_read_dictionary");
    254 				retcode = -1;
    255 				break;
    256 			}
    257 			strcpy (dval->attrname, attrstr);
    258 			strcpy (dval->name, namestr);
    259 			dval->value = value;
    260 
    261 			/* Insert it into the list */
    262 			dval->next = dictionary_values;
    263 			dictionary_values = dval;
    264 		}
    265 		else if (strncmp (buffer, "INCLUDE", 7) == 0)
    266 		{
    267 			/* Read the INCLUDE line */
    268 			if (sscanf (buffer, "%s%s", dummystr, namestr) != 2)
    269 			{
    270 				error("rc_read_dictionary: invalid include entry on line %d of dictionary %s",
    271 				      line_no, filename);
    272 				retcode = -1;
    273 				break;
    274 			}
    275 			if (rc_read_dictionary(namestr) == -1)
    276 			{
    277 				retcode = -1;
    278 				break;
    279 			}
    280 		}
    281 	}
    282 	fclose (dictfd);
    283 	return retcode;
    284 }
    285 
    286 /*
    287  * Function: rc_dict_getattr
    288  *
    289  * Purpose: Return the full attribute structure based on the
    290  *	    attribute id number and vendor code.  If vendor code is VENDOR_NONE,
    291  *          non-vendor-specific attributes are used
    292  *
    293  */
    294 
    295 DICT_ATTR *rc_dict_getattr (int attribute, int vendor)
    296 {
    297 	DICT_ATTR      *attr;
    298 	VENDOR_DICT    *dict;
    299 
    300 	if (vendor == VENDOR_NONE) {
    301 	    attr = dictionary_attributes;
    302 	    while (attr != (DICT_ATTR *) NULL) {
    303 		if (attr->value == attribute) {
    304 		    return (attr);
    305 		}
    306 		attr = attr->next;
    307 	    }
    308 	} else {
    309 	    dict = rc_dict_getvendor(vendor);
    310 	    if (!dict) {
    311 		return NULL;
    312 	    }
    313 	    attr = dict->attributes;
    314 	    while (attr) {
    315 		if (attr->value == attribute) {
    316 		    return attr;
    317 		}
    318 		attr = attr->next;
    319 	    }
    320 	}
    321 	return NULL;
    322 }
    323 
    324 /*
    325  * Function: rc_dict_findattr
    326  *
    327  * Purpose: Return the full attribute structure based on the
    328  *	    attribute name.
    329  *
    330  */
    331 
    332 DICT_ATTR *rc_dict_findattr (char *attrname)
    333 {
    334 	DICT_ATTR      *attr;
    335 	VENDOR_DICT    *dict;
    336 
    337 	attr = dictionary_attributes;
    338 	while (attr != (DICT_ATTR *) NULL)
    339 	{
    340 		if (strcasecmp (attr->name, attrname) == 0)
    341 		{
    342 			return (attr);
    343 		}
    344 		attr = attr->next;
    345 	}
    346 
    347 	/* Search vendor-specific dictionaries */
    348 	dict = vendor_dictionaries;
    349 	while (dict) {
    350 	    attr = dict->attributes;
    351 	    while (attr) {
    352 		if (strcasecmp (attr->name, attrname) == 0) {
    353 		    return (attr);
    354 		}
    355 		attr = attr->next;
    356 	    }
    357 	    dict = dict->next;
    358 	}
    359 	return ((DICT_ATTR *) NULL);
    360 }
    361 
    362 
    363 /*
    364  * Function: rc_dict_findval
    365  *
    366  * Purpose: Return the full value structure based on the
    367  *         value name.
    368  *
    369  */
    370 
    371 DICT_VALUE *rc_dict_findval (char *valname)
    372 {
    373 	DICT_VALUE     *val;
    374 
    375 	val = dictionary_values;
    376 	while (val != (DICT_VALUE *) NULL)
    377 	{
    378 		if (strcasecmp (val->name, valname) == 0)
    379 		{
    380 			return (val);
    381 		}
    382 		val = val->next;
    383 	}
    384 	return ((DICT_VALUE *) NULL);
    385 }
    386 
    387 /*
    388  * Function: dict_getval
    389  *
    390  * Purpose: Return the full value structure based on the
    391  *          actual value and the associated attribute name.
    392  *
    393  */
    394 
    395 DICT_VALUE * rc_dict_getval (UINT4 value, char *attrname)
    396 {
    397 	DICT_VALUE     *val;
    398 
    399 	val = dictionary_values;
    400 	while (val != (DICT_VALUE *) NULL)
    401 	{
    402 		if (strcmp (val->attrname, attrname) == 0 &&
    403 				val->value == value)
    404 		{
    405 			return (val);
    406 		}
    407 		val = val->next;
    408 	}
    409 	return ((DICT_VALUE *) NULL);
    410 }
    411 
    412 /*
    413  * Function: rc_dict_findvendor
    414  *
    415  * Purpose: Return the vendor's dictionary given the vendor name.
    416  *
    417  */
    418 VENDOR_DICT * rc_dict_findvendor (char *vendorname)
    419 {
    420     VENDOR_DICT *dict;
    421 
    422     dict = vendor_dictionaries;
    423     while (dict) {
    424 	if (!strcmp(vendorname, dict->vendorname)) {
    425 	    return dict;
    426 	}
    427 	dict = dict->next;
    428     }
    429     return NULL;
    430 }
    431 
    432 /*
    433  * Function: rc_dict_getvendor
    434  *
    435  * Purpose: Return the vendor's dictionary given the vendor ID
    436  *
    437  */
    438 VENDOR_DICT * rc_dict_getvendor (int id)
    439 {
    440     VENDOR_DICT *dict;
    441 
    442     dict = vendor_dictionaries;
    443     while (dict) {
    444 	if (id == dict->vendorcode) {
    445 	    return dict;
    446 	}
    447 	dict = dict->next;
    448     }
    449     return NULL;
    450 }
    451