1 /* This file is part of GNU Radius.
2    Copyright (C) 2000,2001,2002,2003,2004,2005,
3    2006,2007,2008 Free Software Foundation, Inc.
4 
5    Written by Sergey Poznyakoff
6 
7    GNU Radius is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    GNU Radius is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public
18    License along with GNU Radius; if not, write to the Free
19    Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20    Boston, MA 02110-1301 USA. */
21 
22 #ifdef HAVE_CONFIG_H
23 # include <config.h>
24 #endif
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <sys/types.h>
29 #include <pwd.h>
30 #include <ctype.h>
31 
32 #include <radlib.h>
33 
34 #ifndef DICT_INDEX_SIZE
35 # define DICT_INDEX_SIZE 2048
36 #endif
37 
38 enum dict_symbol_type {
39 	dict_symbol_uninitialized,
40 	dict_symbol_attribute,
41 	dict_symbol_alias
42 };
43 
44 typedef struct dict_symbol DICT_SYMBOL;
45 struct dict_symbol {
46         DICT_SYMBOL *next;          /* Link to the next attribute */
47 	char *name;
48 	enum dict_symbol_type type; /* Type of the entry */
49 	union {
50 		grad_dict_attr_t attr;
51 		grad_dict_attr_t *alias;
52 	} v;
53 };
54 
55 static grad_symtab_t    *dict_attr_tab;
56 static grad_dict_attr_t *dict_attr_index[DICT_INDEX_SIZE];
57 static grad_list_t /* of grad_dict_value_t */ *dictionary_values;
58 static grad_list_t /* of grad_dict_vendor_t */ *dictionary_vendors;
59 static int         vendorno;
60 
61 
62 static grad_dict_attr_t *
dict_symbol_ptr(DICT_SYMBOL * sym)63 dict_symbol_ptr(DICT_SYMBOL *sym)
64 {
65 	switch (sym->type) {
66 	case dict_symbol_uninitialized:
67 		grad_insist_fail("uninitialized dictionary symbol found!");
68 		break;
69 
70 	case dict_symbol_attribute:
71 		return &sym->v.attr;
72 
73 	case dict_symbol_alias:
74 		return sym->v.alias;
75 	}
76 }
77 
78 static grad_dict_attr_t *
dict_attr_lookup(const char * ident)79 dict_attr_lookup(const char *ident)
80 {
81 	DICT_SYMBOL *sym = grad_sym_lookup(dict_attr_tab, ident);
82 	if (sym)
83 		return dict_symbol_ptr(sym);
84 
85 	return NULL;
86 }
87 
88 /* ************************************************************************ */
89 
90 static int
free_vendor(void * ptr,void * closure ARG_UNUSED)91 free_vendor(void *ptr, void *closure ARG_UNUSED)
92 {
93         grad_dict_vendor_t *vp = ptr;
94         if (vp->vendorname)
95                 grad_free(vp->vendorname);
96 	grad_free(vp);
97 	return 0;
98 }
99 
100 static int
free_value(void * ptr,void * closure ARG_UNUSED)101 free_value(void *ptr, void *closure ARG_UNUSED)
102 {
103         grad_dict_value_t *vp = ptr;
104         grad_free(vp->name);
105 	grad_free(vp);
106 	return 0;
107 }
108 
109 void
dict_free()110 dict_free()
111 {
112 	grad_symtab_free(&dict_attr_tab);
113         memset(dict_attr_index, 0, sizeof dict_attr_index);
114 
115 	grad_list_destroy(&dictionary_values, free_value, NULL);
116         grad_list_destroy(&dictionary_vendors, free_vendor, NULL);
117 }
118 
119 static int
nfields(int fc,int minf,int maxf,grad_locus_t * loc)120 nfields(int fc, int minf, int maxf, grad_locus_t *loc)
121 {
122         if (fc < minf) {
123                 grad_log_loc(GRAD_LOG_ERR, loc, "%s", _("too few fields"));
124                 return -1;
125         } else if (maxf != -1 && fc > maxf) {
126                 grad_log_loc(GRAD_LOG_ERR, loc, "%s", _("too many fields"));
127                 return -1;
128         }
129         return 0;
130 }
131 
132 /*
133  *      Add vendor to the list.
134  */
135 static int
addvendor(char * name,int value)136 addvendor(char *name, int value)
137 {
138         grad_dict_vendor_t *vval;
139 
140         vval = grad_emalloc(sizeof(grad_dict_vendor_t));
141 
142         vval->vendorname = grad_estrdup(name);
143         vval->vendorpec  = value;
144         vval->vendorcode = vendorno++;
145 	if (!dictionary_vendors)
146 		dictionary_vendors = grad_list_create();
147 	grad_list_prepend(dictionary_vendors, vval);
148 
149         return 0;
150 }
151 
152 /* **************************************************************************
153    Parser table for built-in abinary attributes
154  */
155 
156 typedef struct attr_parser_tab ATTR_PARSER_TAB;
157 struct attr_parser_tab {
158 	ATTR_PARSER_TAB *next;
159 	int attr;
160 	grad_attr_parser_fp fun;
161 };
162 static ATTR_PARSER_TAB *attr_parser_tab;
163 
164 static grad_attr_parser_fp
dict_find_parser(int attr)165 dict_find_parser(int attr)
166 {
167 	ATTR_PARSER_TAB *ep;
168 	for (ep = attr_parser_tab; ep; ep = ep->next)
169 		if (ep->attr == attr)
170 			return ep->fun;
171 	return NULL;
172 }
173 
174 void
dict_register_parser(int attr,grad_attr_parser_fp fun)175 dict_register_parser(int attr, grad_attr_parser_fp fun)
176 {
177 	ATTR_PARSER_TAB *e = grad_emalloc(sizeof(*e));
178 	e->attr = attr;
179 	e->fun = fun;
180 	e->next = attr_parser_tab;
181 	attr_parser_tab = e;
182 }
183 
184 static void
parser_tab_init()185 parser_tab_init()
186 {
187 	if (!attr_parser_tab) {
188 		/* Register ascend filters */
189 		dict_register_parser(242, grad_ascend_parse_filter);
190 		dict_register_parser(243, grad_ascend_parse_filter);
191 	}
192 }
193 
194 static void
parser_tab_free()195 parser_tab_free()
196 {
197 	ATTR_PARSER_TAB *ep = attr_parser_tab;
198 
199 	while (ep) {
200 		ATTR_PARSER_TAB *next = ep->next;
201 		grad_free(ep);
202 		ep = next;
203 	}
204 	attr_parser_tab = NULL;
205 }
206 
207 /* **************************************************************************
208  * Parser
209  */
210 static int parse_dict(char *name);
211 
212 #define KEYWORD      fv[0]
213 #define ATTR_NAME    fv[1]
214 #define ATTR_VALUE   fv[2]
215 #define ATTR_TYPE    fv[3]
216 #define ATTR_VENDOR  fv[4]
217 #define ATTR_FLAGS   ((fc == 6) ? fv[5] : fv[4])
218 #define HAS_VENDOR(c,p)     ((c>=5) && strcmp(p[4],"-") && p[4][0] != '[')
219 #define HAS_FLAGS(c,p)      ((c==6) || (c==5 && p[4][0] == '['))
220 #define VALUE_ATTR   fv[1]
221 #define VALUE_NAME   fv[2]
222 #define VALUE_NUM    fv[3]
223 #define VENDOR_NAME  fv[1]
224 #define VENDOR_VALUE fv[2]
225 
226 static grad_keyword_t type_kw[] = {
227         { "string", GRAD_TYPE_STRING },
228         { "integer", GRAD_TYPE_INTEGER },
229         { "ipaddr", GRAD_TYPE_IPADDR },
230         { "date", GRAD_TYPE_DATE }
231 };
232 
233 struct parse_data {
234 	int vendor;
235 	grad_locus_t begin_locus;
236 	int errcnt;
237 };
238 
239 /*ARGSUSED*/
240 static int
_dict_include(struct parse_data * pd,int fc,char ** fv,grad_locus_t * loc)241 _dict_include(struct parse_data *pd, int fc, char **fv, grad_locus_t *loc)
242 {
243         if (nfields(fc, 2, 2, loc))
244                 return 0;
245         parse_dict(fv[1]);
246         return 0;
247 }
248 
249 static int
parse_flags(char ** ptr,int * flags,grad_locus_t * loc)250 parse_flags(char **ptr, int *flags, grad_locus_t *loc)
251 {
252         int i;
253         char *p;
254 
255         for (p = *ptr+1, i = 0; i < GRAD_CF_MAX; i++) {
256                 if (*p == 0) {
257                         grad_log_loc(GRAD_LOG_ERR, loc, _("missing ]"), *p);
258                         return 1;
259                 }
260                 switch (*p++) {
261                 case 'C':
262                 case 'L':
263                         *flags |= GRAD_AF_LHS(i);
264                         break;
265                 case '-':
266                         *flags &= ~GRAD_AF_LHS(i);
267                         break;
268                 case ']':
269                         p--;
270                         goto stop;
271                 default:
272                         grad_log_loc(GRAD_LOG_ERR, loc,
273 				     _("invalid syntax flag %c"),
274 				     p[-1]);
275                         return 1;
276                 }
277                 switch (*p++) {
278                 case 'R':
279                         *flags |= GRAD_AF_RHS(i);
280                         break;
281                 case '-':
282                         *flags &= ~GRAD_AF_RHS(i);
283                         break;
284                 default:
285                         grad_log_loc(GRAD_LOG_ERR, loc,
286 				     _("invalid syntax flag %c"),
287 				     p[-1]);
288                         return 1;
289                 }
290         }
291   stop:
292         for (; i < GRAD_CF_MAX; i++)
293                 *flags |= GRAD_AF_LHS(i)|GRAD_AF_RHS(i);
294         *ptr = p;
295         return 0;
296 }
297 
298 static int
parse_attr_properties(grad_locus_t * loc,char * str,int * flags,int * prop)299 parse_attr_properties(grad_locus_t *loc, char *str, int *flags, int *prop)
300 {
301 	int errcnt = 0;
302 	char *p;
303 
304 	for (p = str; *p; p++) {
305 		switch (*p) {
306 		case 'C':
307 		case 'L':
308 			*flags |= GRAD_AF_LHS(GRAD_CF_USERS)
309 				   |GRAD_AF_LHS(GRAD_CF_HINTS)
310 				   |GRAD_AF_LHS(GRAD_CF_HUNTGROUPS);
311 			break;
312 		case 'R':
313 			*flags |= GRAD_AF_RHS(GRAD_CF_USERS)
314 				   |GRAD_AF_RHS(GRAD_CF_HINTS)
315 				   |GRAD_AF_RHS(GRAD_CF_HUNTGROUPS);
316 			break;
317 		case '[':
318 			if (parse_flags(&p, flags, loc)) {
319 				while (*++p);
320 				--p;
321 				errcnt++;
322 			}
323 			break;
324 		case '=':
325 			GRAD_SET_ADDITIVITY(*prop, GRAD_AP_ADD_REPLACE);
326 			break;
327 		case '+':
328 			GRAD_SET_ADDITIVITY(*prop, GRAD_AP_ADD_APPEND);
329 			break;
330 		case 'N':
331 			GRAD_SET_ADDITIVITY(*prop, GRAD_AP_ADD_NONE);
332 			break;
333 		case 'P':
334 			*prop |= GRAD_AP_PROPAGATE;
335 			break;
336 		case 'l':
337 			*flags &= ~GRAD_AP_INTERNAL;
338 			break;
339 		case '1':
340 		case '2':
341 		case '3':
342 		case '4':
343 		case '5':
344 		case '6':
345 		case '7':
346 		case '8':
347 		case '9':
348 			*prop |= GRAD_AP_USER_FLAG(*p-'0');
349 			break;
350 		case 'b':
351 			*prop |= GRAD_AP_BINARY_STRING;
352 			break;
353 		case 'E':
354 			*prop |= GRAD_AP_ENCRYPT_RFC2138;
355 			break;
356 		case 'T':
357 			*prop |= GRAD_AP_ENCRYPT_RFC2868;
358 			break;
359 		case 'c':
360 			/* Retained for compatibility */
361 			break;
362 		default:
363 			grad_log_loc(GRAD_LOG_ERR, loc,
364 				     _("invalid flag %c"),
365 				     *p);
366 			errcnt++;
367 			break;
368 		}
369 	}
370 	return errcnt;
371 }
372 
373 static void
set_default_attr_properties(int value,int * flags,int * prop)374 set_default_attr_properties(int value, int *flags, int *prop)
375 {
376         *flags = GRAD_AF_DEFAULT_FLAGS;
377         *prop  = GRAD_AP_DEFAULT_ADD;
378 
379 	if (GRAD_VENDOR_CODE(value) == 0) {
380 		if (value > 255)
381 			*flags |= GRAD_AP_INTERNAL;
382 		/* FIXME: A temporary hack until all users update
383 		   their dictionaries */
384 		else if (value == DA_USER_PASSWORD
385 			 || value == DA_USER_PASSWORD)
386 			*prop |= GRAD_AP_ENCRYPT_RFC2138;
387 	}
388 }
389 
390 static int
_dict_attribute(struct parse_data * pd,int fc,char ** fv,grad_locus_t * loc)391 _dict_attribute(struct parse_data *pd, int fc, char **fv, grad_locus_t *loc)
392 {
393 	DICT_SYMBOL *sym;
394         grad_dict_attr_t *attr;
395         int type;
396         int vendor = 0;
397         unsigned value;
398         char *p;
399 	grad_attr_parser_fp fp = NULL;
400         int flags;
401         int prop;
402 
403         if (nfields(fc, 4, 6, loc))
404                 return 0;
405 
406 	GRAD_DEBUG7(100,
407 	      "%s:%lu: ATTR_NAME=%s ATTR_VALUE=%s ATTR_TYPE=%s ATTR_VENDOR=%s ATTR_FLAGS=%s",
408 	       loc->file, loc->line,
409 	       ATTR_NAME,ATTR_VALUE,ATTR_TYPE,
410 	       HAS_VENDOR(fc, fv) ? ATTR_VENDOR : pd->vendor ? "BLOCK" : "N/A",
411 	       HAS_FLAGS(fc,fv) ? ATTR_FLAGS : "N/A");
412 
413         /*
414          * Validate all entries
415          */
416 
417         value = strtol(ATTR_VALUE, &p, 0);
418         if (*p) {
419                 grad_log_loc(GRAD_LOG_ERR, loc,
420 			     _("value not a number (near %s)"),
421 			     p);
422                 pd->errcnt++;
423                 return 0;
424         }
425 
426 	if (strcmp(ATTR_TYPE, "abinary") == 0) {
427 		type = GRAD_TYPE_STRING;
428 		fp = dict_find_parser(value);
429 		if (!fp) {
430 			grad_log_loc(GRAD_LOG_WARN, loc,
431 			      _("no parser registered for this attribute"));
432 			return 0;
433 		}
434 	} else
435 		type = grad_xlat_keyword(type_kw, ATTR_TYPE, GRAD_TYPE_INVALID);
436 
437         if (type == GRAD_TYPE_INVALID) {
438                 grad_log_loc(GRAD_LOG_ERR, loc,
439 			     "%s",
440 			     _("invalid type"));
441                 pd->errcnt++;
442                 return 0;
443         }
444 
445         if (HAS_VENDOR(fc, fv)) {
446                 if ((vendor = grad_vendor_name_to_id(ATTR_VENDOR)) == 0) {
447                         grad_log_loc(GRAD_LOG_ERR, loc, _("unknown vendor"));
448 			pd->errcnt++;
449                         return 0;
450                 }
451         } else if (pd->vendor)
452 		vendor = pd->vendor;
453 
454 	value |= (vendor << 16);
455 
456 	set_default_attr_properties(value, &flags, &prop);
457 
458         if (HAS_FLAGS(fc,fv)) {
459 		int rc = parse_attr_properties(loc, ATTR_FLAGS, &flags, &prop);
460 		if (rc) {
461 			pd->errcnt++;
462 			return 0;
463 		}
464         }
465 
466 	sym = grad_sym_lookup_or_install(dict_attr_tab, ATTR_NAME, 1);
467 	switch (sym->type) {
468 	case dict_symbol_uninitialized:
469 		sym->type = dict_symbol_attribute;
470 		attr = &sym->v.attr;
471 		break;
472 
473 	case dict_symbol_attribute:
474 		grad_log_loc(GRAD_LOG_WARN, loc,
475 			     _("Redefining attribute %s"),
476 			     ATTR_NAME);
477 		attr = &sym->v.attr;
478 		break;
479 
480 	case dict_symbol_alias:
481 		grad_log_loc(GRAD_LOG_WARN, loc,
482 			     _("Redefining alias %s"),
483 			     ATTR_NAME);
484 		attr = sym->v.alias;
485 	}
486 
487 	attr->name = sym->name;
488         attr->value = value;
489         attr->type = type;
490         attr->prop = flags | prop;
491 	attr->parser = fp;
492         if (attr->value >= 0 && attr->value < DICT_INDEX_SIZE)
493                 dict_attr_index[attr->value] = attr;
494 
495         return 0;
496 }
497 
498 /* Syntax:
499    ALIAS oldname newname */
500 static int
_dict_alias(struct parse_data * pd,int fc,char ** fv,grad_locus_t * loc)501 _dict_alias(struct parse_data *pd, int fc, char **fv, grad_locus_t *loc)
502 {
503 	DICT_SYMBOL *sym;
504 	grad_dict_attr_t *attr;
505 
506 	if (nfields(fc, 3, 3, loc))
507                 return 0;
508 
509         attr = dict_attr_lookup(fv[1]);
510 	if (!attr) {
511 		grad_log_loc(GRAD_LOG_ERR, loc,
512 			     _("Attribute %s is not defined"),
513 			     fv[1]);
514 		return 0;
515 	}
516 
517 	sym = grad_sym_lookup_or_install(dict_attr_tab, fv[2], 1);
518 	if (sym->type != dict_symbol_uninitialized) {
519 		grad_log_loc(GRAD_LOG_ERR, loc,
520 			     _("Symbol %s already declared"),
521 			     fv[2]);
522 		/*FIXME: location of the previous declaration*/
523 		/* Not a fatal error: do not increase error count */
524 		return 0;
525 	}
526 	sym->type = dict_symbol_alias;
527 	sym->v.alias = attr;
528 	return 0;
529 }
530 
531 /* Syntax:
532 
533    PROPERTY Attribute Flags */
534 static int
_dict_property(struct parse_data * pd,int fc,char ** fv,grad_locus_t * loc)535 _dict_property(struct parse_data *pd, int fc, char **fv, grad_locus_t *loc)
536 {
537 	grad_dict_attr_t *attr;
538 	int i;
539 	int flags;
540 	int prop;
541 
542 	if (nfields(fc, 3, -1, loc))
543                 return 0;
544 
545         attr = dict_attr_lookup(fv[1]);
546 	if (!attr) {
547 		grad_log_loc(GRAD_LOG_ERR, loc,
548 			     _("Attribute %s is not defined"),
549 			     fv[1]);
550 		return 0;
551 	}
552 
553 	for (i = 2; i < fc; i++) {
554 		switch (fv[i][0]) {
555 		case '+':
556 			flags = prop = 0;
557 			if (parse_attr_properties(loc, fv[i]+1,
558 						  &flags, &prop)) {
559 				pd->errcnt++;
560 				break;
561 			}
562 			attr->prop |= flags | prop;
563 			break;
564 
565 		case '-':
566 			flags = prop = 0;
567 			if (parse_attr_properties(loc, fv[i]+1,
568 						  &flags, &prop)) {
569 				pd->errcnt++;
570 				break;
571 			}
572 			attr->prop &= ~(flags | prop);
573 			break;
574 
575 		default:
576 			if (i > 2) {
577 				grad_log_loc(GRAD_LOG_ERR, loc,
578 					     _("PROPERTY syntax error"));
579 				pd->errcnt++;
580 			} else {
581 				set_default_attr_properties(attr->value,
582 							    &flags, &prop);
583 				if (parse_attr_properties(loc, fv[i],
584 							  &flags, &prop) == 0)
585 					attr->prop = flags | prop;
586 				else
587 					pd->errcnt++;
588 				break;
589 			}
590 		}
591 	}
592 	return 0;
593 }
594 
595 static int
_dict_value(struct parse_data * pd,int fc,char ** fv,grad_locus_t * loc)596 _dict_value(struct parse_data *pd, int fc, char **fv, grad_locus_t *loc)
597 {
598         grad_dict_value_t *dval;
599         grad_dict_attr_t *attr;
600         char *p;
601         int value;
602 
603         if (nfields(fc, 4, 4, loc))
604                 return 0;
605 
606         value = strtol(VALUE_NUM, &p, 0);
607         if (*p) {
608                 grad_log_loc(GRAD_LOG_ERR, loc,
609 			     _("value not a number (near %s)"),
610 			     p);
611                 pd->errcnt++;
612                 return 0;
613         }
614 
615         attr = dict_attr_lookup(VALUE_ATTR);
616 	if (!attr) {
617 		grad_log_loc(GRAD_LOG_ERR, loc,
618 			     _("Attribute %s is not defined"),
619 			     VALUE_ATTR);
620                 pd->errcnt++;
621 		return 0;
622 	}
623 
624 	attr->prop |= GRAD_AP_TRANSLATE;
625 
626         /* Create a new VALUE entry for the list */
627         dval = grad_emalloc(sizeof(grad_dict_value_t));
628 
629         dval->name = grad_estrdup(VALUE_NAME);
630         dval->attr = attr;
631         dval->value = value;
632 
633         /* Append */
634 	if (!dictionary_values)
635 		dictionary_values = grad_list_create();
636 	grad_list_append(dictionary_values, dval);
637 
638         return 0;
639 }
640 
641 static int
_dict_vendor(struct parse_data * pd,int fc,char ** fv,grad_locus_t * loc)642 _dict_vendor(struct parse_data *pd, int fc, char **fv, grad_locus_t *loc)
643 {
644         int value;
645         char *p;
646 
647         if (nfields(fc, 3, 3, loc))
648                 return 1;
649 
650         value = strtol(VENDOR_VALUE, &p, 0);
651         if (*p) {
652                 grad_log_loc(GRAD_LOG_ERR, loc,
653 			     _("value not a number (near %s)"),
654 			     p);
655                 pd->errcnt++;
656                 return 1;
657         }
658 
659         if (addvendor(VENDOR_NAME, value) < 0) {
660                 pd->errcnt++;
661 		return 1;
662         }
663 
664         return 0;
665 
666 }
667 
668 static void
_dict_begin(struct parse_data * pd,int fc,char ** fv,grad_locus_t * loc)669 _dict_begin(struct parse_data *pd, int fc, char **fv, grad_locus_t *loc)
670 {
671 	if (pd->vendor) {
672 		grad_log_loc(GRAD_LOG_ERR, loc, _("blocks cannot be nested"));
673 		grad_log_loc(GRAD_LOG_ERR, &pd->begin_locus,
674 			     _("block opened here"));
675 		pd->errcnt++;
676 		return;
677 	}
678 
679         if (nfields(fc, 3, 4, loc)) {
680 		pd->errcnt++;
681                 return;
682 	}
683 
684 	if (strcmp (fv[1], "VENDOR")) {
685 		grad_log_loc(GRAD_LOG_ERR, loc,
686 			     _("block syntax: expected `VENDOR' but found `%s'"),
687 			     fv[1]);
688 		pd->errcnt++;
689 		return;
690 	}
691 
692 	if (fc == 4 && _dict_vendor(pd, fc-1, fv+1, loc))
693 		return;
694 
695 	if ((pd->vendor = grad_vendor_name_to_id(fv[2])) == 0) {
696 		grad_log_loc(GRAD_LOG_ERR, loc, _("unknown vendor"));
697 		pd->errcnt++;
698 		return;
699 	}
700 	pd->begin_locus = *loc;
701 	GRAD_DEBUG4(1, "%s:%lu: BEGIN VENDOR %s (%d)",
702 		  loc->file, loc->line, fv[2], pd->vendor);
703 }
704 
705 static void
_dict_end(struct parse_data * pd,int fc,char ** fv,grad_locus_t * loc)706 _dict_end(struct parse_data *pd, int fc, char **fv, grad_locus_t *loc)
707 {
708 	if (!pd->vendor) {
709 		grad_log_loc(GRAD_LOG_ERR, loc, _("unexpected END"));
710 		pd->errcnt++;
711 	}
712 	GRAD_DEBUG1(1, "END VENDOR %d", pd->vendor);
713 	pd->vendor = 0;
714 }
715 
716 static void
_dict_begin_vendor(struct parse_data * pd,int fc,char ** fv,grad_locus_t * loc)717 _dict_begin_vendor(struct parse_data *pd, int fc, char **fv, grad_locus_t *loc)
718 {
719 	char *args[4];
720 
721         if (nfields(fc, 2, 2, loc)) {
722 		pd->errcnt++;
723 		return;
724 	}
725 
726 	args[0] = "BEGIN";
727 	args[1] = "VENDOR";
728 	args[2] = fv[1];
729 	args[3] = NULL;
730 	_dict_begin(pd, 3, args, loc);
731 }
732 
733 static void
_dict_end_vendor(struct parse_data * pd,int fc,char ** fv,grad_locus_t * loc)734 _dict_end_vendor(struct parse_data *pd, int fc, char **fv, grad_locus_t *loc)
735 {
736 	_dict_end(pd, fc, fv, loc);
737 }
738 
739 enum {
740         KW_INCLUDE,
741         KW_ATTRIBUTE,
742 	KW_ALIAS,
743         KW_VALUE,
744         KW_VENDOR,
745 	KW_PROPERTY,
746 	KW_BEGIN,
747 	KW_BEGIN_VENDOR,
748 	KW_END_VENDOR,
749 	KW_END
750 };
751 
752 static grad_keyword_t dict_kw[] = {
753         { "$INCLUDE", KW_INCLUDE },
754         { "ATTRIBUTE", KW_ATTRIBUTE },
755 	{ "ALIAS", KW_ALIAS },
756         { "VALUE", KW_VALUE },
757         { "VENDOR", KW_VENDOR },
758 	{ "PROPERTY", KW_PROPERTY },
759 	{ "BEGIN", KW_BEGIN },
760 	{ "END", KW_END },
761 	{ "BEGIN-VENDOR", KW_BEGIN_VENDOR },
762 	{ "END-VENDOR", KW_END_VENDOR },
763         { NULL, 0 }
764 };
765 
766 static int
parse_dict_entry(void * closure,int fc,char ** fv,grad_locus_t * loc)767 parse_dict_entry(void *closure, int fc, char **fv, grad_locus_t *loc)
768 {
769 	struct parse_data *pd = closure;
770         switch (grad_xlat_keyword(dict_kw, KEYWORD, -1)) {
771         case KW_INCLUDE:
772                 _dict_include(pd, fc, fv, loc);
773                 break;
774 
775         case KW_ATTRIBUTE:
776                 _dict_attribute(pd, fc, fv, loc);
777                 break;
778 
779 	case KW_ALIAS:
780 		_dict_alias(pd, fc, fv, loc);
781 		break;
782 
783         case KW_VALUE:
784                 _dict_value(pd, fc, fv, loc);
785                 break;
786 
787         case KW_VENDOR:
788                 _dict_vendor(pd, fc, fv, loc);
789                 break;
790 
791 	case KW_PROPERTY:
792 		_dict_property(pd, fc, fv, loc);
793 		break;
794 
795 	case KW_BEGIN:
796 		_dict_begin(pd, fc, fv, loc);
797 		break;
798 
799 	case KW_END:
800 		_dict_end(pd, fc, fv, loc);
801 		break;
802 
803 	case KW_BEGIN_VENDOR:
804 		_dict_begin_vendor(pd, fc, fv, loc);
805 		break;
806 
807 	case KW_END_VENDOR:
808 		_dict_end_vendor(pd, fc, fv, loc);
809 		break;
810 
811         default:
812                 grad_log_loc(GRAD_LOG_ERR, loc, "%s", _("unknown keyword"));
813                 break;
814         }
815         return 0;
816 }
817 
818 static int
parse_dict(char * name)819 parse_dict(char *name)
820 {
821         char *path;
822         int   rc;
823 	struct parse_data pd;
824 
825 	pd.errcnt = 0;
826 	pd.vendor = 0;
827 
828 	if (name[0] == '/')
829 		path = grad_estrdup(name);
830 	else
831 		path = grad_mkfilename(grad_config_dir, name);
832 	GRAD_DEBUG1(1,"parsing %s", path);
833         rc = grad_read_raddb_file(path, 1, NULL, parse_dict_entry, &pd);
834 	if (pd.vendor) {
835 		grad_log_loc(GRAD_LOG_ERR, &pd.begin_locus, _("BEGIN without END"));
836 		pd.vendor = 0;
837 		pd.errcnt++;
838 	}
839         if (pd.errcnt)
840                 grad_log(GRAD_LOG_NOTICE,
841 		         dngettext(PACKAGE,
842 				   "%s: %d error", "%s: %d errors",
843 				   pd.errcnt), path, pd.errcnt);
844         grad_free(path);
845         return rc;
846 }
847 
848 int
grad_dict_init()849 grad_dict_init()
850 {
851 	parser_tab_free();
852         dict_free();
853 
854 	parser_tab_init();
855 	dict_attr_tab = grad_symtab_create(sizeof(DICT_SYMBOL), NULL);
856         vendorno = 1;
857         return parse_dict(RADIUS_DICTIONARY);
858 }
859 
860 void
grad_dict_free()861 grad_dict_free()
862 {
863 	parser_tab_free();
864         dict_free();
865 }
866 
867 /* **************************************************************************
868  * Lookup functions
869  */
870 
871 /*
872  * Return the full attribute structure based on the
873  * attribute id number.
874  */
875 
876 struct attr_value {
877         unsigned value;
878         grad_dict_attr_t *da;
879 };
880 
881 static int
attrval_cmp(void * data,grad_symbol_t * s)882 attrval_cmp(void *data, grad_symbol_t *s)
883 {
884 	struct attr_value *av = data;
885 	DICT_SYMBOL *sym = (DICT_SYMBOL *) s;
886 
887 	if (sym->type == dict_symbol_attribute
888 	    && sym->v.attr.value == av->value) {
889                 av->da = &sym->v.attr;
890 		return 1;
891         }
892         return 0;
893 }
894 
895 grad_dict_attr_t *
grad_attr_number_to_dict(int attribute)896 grad_attr_number_to_dict(int attribute)
897 {
898         struct attr_value av;
899         if (attribute >= 0 && attribute < DICT_INDEX_SIZE)
900                 return dict_attr_index[attribute];
901         av.value = attribute;
902         av.da = NULL;
903         grad_symtab_iterate(dict_attr_tab, attrval_cmp, &av);
904         return av.da;
905 }
906 
907 /*
908  *  Return the full attribute structure based on the attribute name.
909  */
910 
911 grad_dict_attr_t *
grad_attr_name_to_dict(const char * attrname)912 grad_attr_name_to_dict(const char *attrname)
913 {
914         return dict_attr_lookup(attrname);
915 }
916 
917 /*
918  * Return the full value structure based on the value name.
919  */
920 struct val_lookup {
921         const char *name;
922         char *attrname;
923         int number;
924 };
925 
926 static int
valname_cmp(const void * item,const void * data)927 valname_cmp(const void *item, const void *data)
928 {
929 	const grad_dict_value_t *v = item;
930 	const struct val_lookup *d = data;
931         if (d->number == v->attr->value && strcmp(v->name, d->name) == 0)
932 		return 0;
933 	return 1;
934 }
935 
936 grad_dict_value_t *
grad_value_name_to_value(const char * valname,int attr)937 grad_value_name_to_value(const char *valname, int attr)
938 {
939         struct val_lookup data;
940         data.name = valname;
941         data.number = attr;
942 	return grad_list_locate(dictionary_values, &data, valname_cmp);
943 }
944 
945 /*
946  * Return the full value structure based on the actual value and
947  * the associated attribute name.
948  */
949 static int
valnum_cmp(const void * item,const void * data)950 valnum_cmp(const void *item, const void *data)
951 {
952 	const grad_dict_value_t *v = item;
953 	const struct val_lookup *d = data;
954 
955         if (strcmp(d->attrname, v->attr->name) == 0 && d->number == v->value)
956 		return 0;
957 	return 1;
958 }
959 
960 grad_dict_value_t *
grad_value_lookup(grad_uint32_t value,char * attrname)961 grad_value_lookup(grad_uint32_t value, char *attrname)
962 {
963         struct val_lookup data;
964         data.number = value;
965         data.attrname = attrname;
966 	return grad_list_locate(dictionary_values, &data, valnum_cmp);
967 }
968 
969 /*
970  * Get the PEC (Private Enterprise Code) of the vendor
971  * based on it's internal number.
972  */
973 static int
code_cmp(const void * item,const void * data)974 code_cmp(const void *item, const void *data)
975 {
976 	const grad_dict_vendor_t *v = item;
977 	const int *code = data;
978 
979         return v->vendorcode != *code;
980 }
981 
982 int
grad_vendor_id_to_pec(int code)983 grad_vendor_id_to_pec(int code)
984 {
985         grad_dict_vendor_t *vp;
986 
987 	vp = grad_list_locate(dictionary_vendors, &code, code_cmp);
988         return vp ? vp->vendorpec : 0;
989 }
990 
991 /*
992  * Get the internal code of the vendor based on its PEC.
993  */
994 static int
pec_cmp(const void * item,const void * data)995 pec_cmp(const void *item, const void *data)
996 {
997 	const grad_dict_vendor_t *v = item;
998 	const int *pec = data;
999 
1000         return v->vendorpec != *pec;
1001 }
1002 
1003 int
grad_vendor_pec_to_id(int pec)1004 grad_vendor_pec_to_id(int pec)
1005 {
1006         grad_dict_vendor_t *vp;
1007 
1008 	vp = grad_list_locate(dictionary_vendors, &pec, pec_cmp);
1009         return vp ? vp->vendorcode : 0;
1010 }
1011 
1012 char *
grad_vendor_pec_to_name(int pec)1013 grad_vendor_pec_to_name(int pec)
1014 {
1015         grad_dict_vendor_t *vp;
1016 
1017 	vp = grad_list_locate(dictionary_vendors, &pec, pec_cmp);
1018         return vp ? vp->vendorname : NULL;
1019 }
1020 
1021 
1022 /*
1023  * Get the internal code of the vendor based on its name.
1024  */
1025 static int
vendor_cmp(const void * item,const void * data)1026 vendor_cmp(const void *item, const void *data)
1027 {
1028 	const grad_dict_vendor_t *v = item;
1029 	const char *s = data;
1030 
1031         return strcmp(v->vendorname, s);
1032 }
1033 
1034 int
grad_vendor_name_to_id(char * name)1035 grad_vendor_name_to_id(char *name)
1036 {
1037         grad_dict_vendor_t *vp;
1038 
1039 	vp = grad_list_locate(dictionary_vendors, name, vendor_cmp);
1040         return vp ? vp->vendorcode : 0;
1041 }
1042 
1043 struct dict_iterator {
1044 	dict_iterator_fp fp;
1045 	void *closure;
1046 };
1047 
1048 int
dict_iter_helper(void * data,grad_symbol_t * symbol)1049 dict_iter_helper(void *data, grad_symbol_t *symbol)
1050 {
1051 	struct dict_iterator *p = data;
1052 	DICT_SYMBOL *dsym = (DICT_SYMBOL *) symbol;
1053 	grad_dict_attr_t *attr;
1054 
1055 	return p->fp(p->closure, dsym->name, dict_symbol_ptr(dsym));
1056 }
1057 
1058 void
grad_dictionary_iterate(dict_iterator_fp fp,void * closure)1059 grad_dictionary_iterate(dict_iterator_fp fp, void *closure)
1060 {
1061 	static struct dict_iterator d;
1062 	d.fp = fp;
1063 	d.closure = closure;
1064 	grad_symtab_iterate(dict_attr_tab, dict_iter_helper, &d);
1065 }
1066 
1067 struct dict_value_iterator {
1068 	dict_value_iterator_fp fp;
1069 	void *closure;
1070 };
1071 
1072 static int
dict_value_iter_helper(void * item,void * data)1073 dict_value_iter_helper(void *item, void *data)
1074 {
1075 	struct dict_value_iterator *p = data;
1076 	return p->fp(p->closure, item);
1077 }
1078 
1079 void
grad_dictionary_value_iterate(dict_value_iterator_fp fp,void * closure)1080 grad_dictionary_value_iterate(dict_value_iterator_fp fp, void *closure)
1081 {
1082 	static struct dict_value_iterator d;
1083 	d.fp = fp;
1084 	d.closure = closure;
1085 	grad_list_iterate(dictionary_values, dict_value_iter_helper, &d);
1086 }
1087 
1088 
1089