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@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 
rc_read_dictionary(char * filename)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 
rc_dict_getattr(int attribute,int vendor)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 
rc_dict_findattr(char * attrname)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 
rc_dict_findval(char * valname)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 
rc_dict_getval(UINT4 value,char * attrname)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  */
rc_dict_findvendor(char * vendorname)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  */
rc_dict_getvendor(int id)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