plugins/radius: Handle bindaddr keyword in radiusclient.conf
[ppp.git] / pppd / plugins / radius / dict.c
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
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 }