95a0838abd13fb9082893534614bc1e891d1754b
[ppp.git] / pppd / plugins / radius / radiusclient / lib / dict.c
1 /*
2  * $Id: dict.c,v 1.1 2002/01/22 16:03:02 dfs 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
23 static DICT_ATTR *dictionary_attributes = NULL;
24 static DICT_VALUE *dictionary_values = NULL;
25 static 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
37 int 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
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         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                         rc_log(LOG_ERR, "rc_read_dictionary: invalid vendor on line %d of dictionary %s",
77                                line_no, filename);
78                         return (-1);
79                     }
80                     /* Validate entry */
81                     if (strlen (namestr) > NAME_LENGTH) {
82                         rc_log(LOG_ERR, "rc_read_dictionary: invalid name length on line %d of dictionary %s",
83                                line_no, filename);
84                         return (-1);
85                     }
86                     /* Create new vendor entry */
87                     vdict = (VENDOR_DICT *) malloc (sizeof (VENDOR_DICT));
88                     if (!vdict) {
89                         rc_log(LOG_CRIT, "rc_read_dictionary: out of memory");
90                         return (-1);
91                     }
92                     strcpy(vdict->vendorname, namestr);
93                     vdict->vendorcode = value;
94                     vdict->attributes = NULL;
95                     vdict->next = vendor_dictionaries;
96                     vendor_dictionaries = vdict;
97                 }
98                 else if (strncmp (buffer, "ATTRIBUTE", 9) == 0)
99                 {
100
101                         /* Read the ATTRIBUTE line.  It is one of:
102                          * ATTRIBUTE attr_name attr_val type         OR
103                          * ATTRIBUTE attr_name attr_val type vendor  */
104                         vendorstr[0] = 0;
105                         n = sscanf(buffer, "%s%s%s%s%s", dummystr, namestr, valstr, typestr, vendorstr);
106                         if (n != 4 && n != 5)
107                         {
108                                 rc_log(LOG_ERR, "rc_read_dictionary: invalid attribute on line %d of dictionary %s",
109                                          line_no, filename);
110                                 return (-1);
111                         }
112
113                         /*
114                          * Validate all entries
115                          */
116                         if (strlen (namestr) > NAME_LENGTH)
117                         {
118                                 rc_log(LOG_ERR, "rc_read_dictionary: invalid name length on line %d of dictionary %s",
119                                          line_no, filename);
120                                 return (-1);
121                         }
122
123                         if (strlen (vendorstr) > NAME_LENGTH)
124                         {
125                                 rc_log(LOG_ERR, "rc_read_dictionary: invalid name length on line %d of dictionary %s",
126                                          line_no, filename);
127                                 return (-1);
128                         }
129
130                         if (!isdigit (*valstr))
131                         {
132                                 rc_log(LOG_ERR,
133                                  "rc_read_dictionary: invalid value on line %d of dictionary %s",
134                                          line_no, filename);
135                                 return (-1);
136                         }
137                         value = atoi (valstr);
138
139                         if (strcmp (typestr, "string") == 0)
140                         {
141                                 type = PW_TYPE_STRING;
142                         }
143                         else if (strcmp (typestr, "integer") == 0)
144                         {
145                                 type = PW_TYPE_INTEGER;
146                         }
147                         else if (strcmp (typestr, "ipaddr") == 0)
148                         {
149                                 type = PW_TYPE_IPADDR;
150                         }
151                         else if (strcmp (typestr, "date") == 0)
152                         {
153                                 type = PW_TYPE_DATE;
154                         }
155                         else
156                         {
157                                 rc_log(LOG_ERR,
158                                   "rc_read_dictionary: invalid type on line %d of dictionary %s",
159                                          line_no, filename);
160                                 return (-1);
161                         }
162
163                         /* Search for vendor if supplied */
164                         if (*vendorstr) {
165                             vdict = rc_dict_findvendor(vendorstr);
166                             if (!vdict) {
167                                 rc_log(LOG_ERR,
168                                        "rc_read_dictionary: unknown vendor on line %d of dictionary %s",
169                                        line_no, filename);
170                                 return (-1);
171                             }
172                         } else {
173                             vdict = NULL;
174                         }
175                         /* Create a new attribute for the list */
176                         if ((attr =
177                                 (DICT_ATTR *) malloc (sizeof (DICT_ATTR)))
178                                                         == (DICT_ATTR *) NULL)
179                         {
180                                 rc_log(LOG_CRIT, "rc_read_dictionary: out of memory");
181                                 return (-1);
182                         }
183                         strcpy (attr->name, namestr);
184                         if (vdict) {
185                             attr->vendorcode = vdict->vendorcode;
186                         } else {
187                             attr->vendorcode = VENDOR_NONE;
188                         }
189                         attr->value = value;
190                         attr->type = type;
191
192                         /* Insert it into the list */
193                         if (vdict) {
194                             attr->next = vdict->attributes;
195                             vdict->attributes = attr;
196                         } else {
197                             attr->next = dictionary_attributes;
198                             dictionary_attributes = attr;
199                         }
200                 }
201                 else if (strncmp (buffer, "VALUE", 5) == 0)
202                 {
203                         /* Read the VALUE line */
204                         if (sscanf (buffer, "%s%s%s%s", dummystr, attrstr,
205                                     namestr, valstr) != 4)
206                         {
207                                 rc_log(LOG_ERR,
208                            "rc_read_dictionary: invalid value entry on line %d of dictionary %s",
209                                          line_no, filename);
210                                 return (-1);
211                         }
212
213                         /*
214                          * Validate all entries
215                          */
216                         if (strlen (attrstr) > NAME_LENGTH)
217                         {
218                                 rc_log(LOG_ERR,
219                       "rc_read_dictionary: invalid attribute length on line %d of dictionary %s",
220                                          line_no, filename);
221                                 return (-1);
222                         }
223
224                         if (strlen (namestr) > NAME_LENGTH)
225                         {
226                                 rc_log(LOG_ERR,
227                            "rc_read_dictionary: invalid name length on line %d of dictionary %s",
228                                          line_no, filename);
229                                 return (-1);
230                         }
231
232                         if (!isdigit (*valstr))
233                         {
234                                 rc_log(LOG_ERR,
235                                  "rc_read_dictionary: invalid value on line %d of dictionary %s",
236                                          line_no, filename);
237                                 return (-1);
238                         }
239                         value = atoi (valstr);
240
241                         /* Create a new VALUE entry for the list */
242                         if ((dval =
243                                 (DICT_VALUE *) malloc (sizeof (DICT_VALUE)))
244                                                         == (DICT_VALUE *) NULL)
245                         {
246                                 rc_log(LOG_CRIT, "rc_read_dictionary: out of memory");
247                                 return (-1);
248                         }
249                         strcpy (dval->attrname, attrstr);
250                         strcpy (dval->name, namestr);
251                         dval->value = value;
252
253                         /* Insert it into the list */
254                         dval->next = dictionary_values;
255                         dictionary_values = dval;
256                 }
257         }
258         fclose (dictfd);
259         return (0);
260 }
261
262 /*
263  * Function: rc_dict_getattr
264  *
265  * Purpose: Return the full attribute structure based on the
266  *          attribute id number and vendor code.  If vendor code is VENDOR_NONE,
267  *          non-vendor-specific attributes are used
268  *
269  */
270
271 DICT_ATTR *rc_dict_getattr (int attribute, int vendor)
272 {
273         DICT_ATTR      *attr;
274         VENDOR_DICT    *dict;
275
276         if (vendor == VENDOR_NONE) {
277             attr = dictionary_attributes;
278             while (attr != (DICT_ATTR *) NULL) {
279                 if (attr->value == attribute) {
280                     return (attr);
281                 }
282                 attr = attr->next;
283             }
284         } else {
285             dict = rc_dict_getvendor(vendor);
286             if (!dict) {
287                 return NULL;
288             }
289             attr = dict->attributes;
290             while (attr) {
291                 if (attr->value == attribute) {
292                     return attr;
293                 }
294                 attr = attr->next;
295             }
296         }
297         return NULL;
298 }
299
300 /*
301  * Function: rc_dict_findattr
302  *
303  * Purpose: Return the full attribute structure based on the
304  *          attribute name.
305  *
306  */
307
308 DICT_ATTR *rc_dict_findattr (char *attrname)
309 {
310         DICT_ATTR      *attr;
311         VENDOR_DICT    *dict;
312
313         attr = dictionary_attributes;
314         while (attr != (DICT_ATTR *) NULL)
315         {
316                 if (strcasecmp (attr->name, attrname) == 0)
317                 {
318                         return (attr);
319                 }
320                 attr = attr->next;
321         }
322
323         /* Search vendor-specific dictionaries */
324         dict = vendor_dictionaries;
325         while (dict) {
326             attr = dict->attributes;
327             while (attr) {
328                 if (strcasecmp (attr->name, attrname) == 0) {
329                     return (attr);
330                 }
331                 attr = attr->next;
332             }
333             dict = dict->next;
334         }
335         return ((DICT_ATTR *) NULL);
336 }
337
338
339 /*
340  * Function: rc_dict_findval
341  *
342  * Purpose: Return the full value structure based on the
343  *         value name.
344  *
345  */
346
347 DICT_VALUE *rc_dict_findval (char *valname)
348 {
349         DICT_VALUE     *val;
350
351         val = dictionary_values;
352         while (val != (DICT_VALUE *) NULL)
353         {
354                 if (strcasecmp (val->name, valname) == 0)
355                 {
356                         return (val);
357                 }
358                 val = val->next;
359         }
360         return ((DICT_VALUE *) NULL);
361 }
362
363 /*
364  * Function: dict_getval
365  *
366  * Purpose: Return the full value structure based on the
367  *          actual value and the associated attribute name.
368  *
369  */
370
371 DICT_VALUE * rc_dict_getval (UINT4 value, char *attrname)
372 {
373         DICT_VALUE     *val;
374
375         val = dictionary_values;
376         while (val != (DICT_VALUE *) NULL)
377         {
378                 if (strcmp (val->attrname, attrname) == 0 &&
379                                 val->value == value)
380                 {
381                         return (val);
382                 }
383                 val = val->next;
384         }
385         return ((DICT_VALUE *) NULL);
386 }
387
388 /*
389  * Function: rc_dict_findvendor
390  *
391  * Purpose: Return the vendor's dictionary given the vendor name.
392  *
393  */
394 VENDOR_DICT * rc_dict_findvendor (char *vendorname)
395 {
396     VENDOR_DICT *dict;
397
398     dict = vendor_dictionaries;
399     while (dict) {
400         if (!strcmp(vendorname, dict->vendorname)) {
401             return dict;
402         }
403         dict = dict->next;
404     }
405     return NULL;
406 }
407
408 /*
409  * Function: rc_dict_getvendor
410  *
411  * Purpose: Return the vendor's dictionary given the vendor ID
412  *
413  */
414 VENDOR_DICT * rc_dict_getvendor (int id)
415 {
416     VENDOR_DICT *dict;
417
418     dict = vendor_dictionaries;
419     while (dict) {
420         if (id == dict->vendorcode) {
421             return dict;
422         }
423         dict = dict->next;
424     }
425     return NULL;
426 }