Patch from Frank Cusack to add support for MSCHAPv2.
[ppp.git] / pppd / plugins / radius / radiusclient / lib / dict.c
1 /*
2  * $Id: dict.c,v 1.2 2002/03/05 15:14:06 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         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
304 DICT_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
341 DICT_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
380 DICT_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
404 DICT_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  */
427 VENDOR_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  */
447 VENDOR_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 }