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