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
22static DICT_ATTR *dictionary_attributes = NULL;
23static DICT_VALUE *dictionary_values = NULL;
24static 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
36int 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
295DICT_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
332DICT_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
371DICT_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
395DICT_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 */
418VENDOR_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 */
438VENDOR_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