2 Copyright (c) 1995-1998 by Cisco systems, Inc.
4 Permission to use, copy, modify, and distribute this software for
5 any purpose and without fee is hereby granted, provided that this
6 copyright and permission notice appear on all copies of the
7 software and supporting documentation, the name of Cisco Systems,
8 Inc. not be used in advertising or publicity pertaining to
9 distribution of the program without specific prior permission, and
10 notice be given in supporting documentation that modification,
11 copying and distribution is by permission of Cisco Systems, Inc.
13 Cisco Systems, Inc. makes no representations about the suitability
14 of this software for any purpose. THIS SOFTWARE IS PROVIDED ``AS
15 IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
16 WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS FOR A PARTICULAR PURPOSE.
28 #ifndef WITH_INCLUDED_REGEX
40 #include "do_author.h" /* for "struct identity" */
42 #ifdef WITH_INCLUDED_REGEX
43 #include "tac_regexp.h"
47 static void sym_get TAC_ARGS((void));
48 static void when_expr_root_init TAC_ARGS((void));
49 static void rch TAC_ARGS((void));
50 static int parse_entity TAC_ARGS((int entity_type));
51 static NODE *parse_svcs TAC_ARGS((void));
52 static int parse_conditional_block TAC_ARGS((ENTITY *entity));
53 static NODE *parse_cmd_matches TAC_ARGS((void));
54 static NODE *parse_attrs TAC_ARGS((void));
55 static void getsym TAC_ARGS((void));
56 static ENTITY *new_entity TAC_ARGS((int type, char *name, int line));
57 static enum eval_result entity_svc_default TAC_ARGS((ENTITY *entity));
63 <decl> := <top_level_decl> | <entity_decl>
65 <top_level_decl> := <authen_default> |
66 accounting file = <string> |
67 default authorization = permit |
69 authorization = ( first | recursive )
71 <authen_default> := default authentication = file <filename>
76 <permission> := permit | deny
78 <filename> := <string>
80 <password> := <string>
82 <user_decl> := user = <string> {
88 <host_decl> := host = <string> {
94 <group_decl> := group = <string> {
100 <service_default> := default service = ( permit | deny | default )
102 <password_spec> := file <filename> |
104 cleartext <password> |
115 <user_attr> := name = <string> |
116 login = <password_spec> |
119 arap = cleartext <string> |
120 chap = cleartext <string> |
122 ms-chap = cleartext <string> |
124 pap = cleartext <string> |
127 pap = pam <pam_service> |
129 opap = cleartext <string> |
130 global = cleartext <string> |
132 before authorization = <string> |
133 after authorization = <string> |
136 <host_attr> := key = <string> |
139 <group_attr> := enlist = <entity_spec> |
143 <when_attr> := member = <string> |
144 enlist = <entity_spec> |
148 <when_attr_block> := <when_decl> {
152 <svc> := <svc_auth> | <cmd_auth>
154 <cmd_auth> := cmd = <string> {
158 <when_match> := <permission> <string> |
161 <when_match_block> := <when_decl> {
165 <svc_auth> := service = ( exec | arap | slip | ppp protocol = <string> ) {
166 # first matching <svc_auth> is the FINAL one, no further graph scanning occurs!
167 [ default attribute = permit ]
171 <when_AV_pair> := [ optional ] <string> = <string> |
174 <when_AV_pair_block> := <when_decl> {
178 <when_decl> := when = <expr>
180 # to avoid ambiguous precence by forbid of "or" & "and" without parentheses:
181 <expr> := <entity_spec> |
186 <expr_or> := <expr> |
189 <expr_and> := <expr> |
190 <expr> and <expr_and>
192 <entity_spec> := ( user | host | group ) <string>
195 static char sym_buf[MAX_INPUT_LINE_LEN]; /* parse buffer */
196 static int sym_pos=0; /* current place in sym_buf */
197 static int sym_ch; /* current parse character */
198 static int sym_code; /* parser output */
199 static int sym_line = 1; /* current line number for parsing */
200 static FILE *cf = NULL; /* config file pointer */
201 static int sym_error = 0; /* a parsing error has occurred */
202 static int no_user_dflt = 0; /* default if user doesn't exist */
203 /* ='default authorization': 0/S_permit */
204 static int algorithm_recursive = 0; /* use newer authorization alogrithm? */
205 /* 1 if 'authorization = recursive' */
206 static char *authen_default = NULL; /* top level authentication default */
207 /* ='default authentication' */
208 static int authen_default_method = 0; /* For method check */
209 /* ='default authentication' symbol */
210 static char *nopasswd_str = "nopassword";
213 /* Only the first 2 fields (name and hash) are used by the hash table
214 routines to hashh structures into a table.
217 static void *grouptable[HASH_TAB_SIZE]; /* Table of group declarations */
218 static void *usertable[HASH_TAB_SIZE]; /* Table of user declarations */
219 static void *hosttable[HASH_TAB_SIZE]; /* Table of host declarations */
222 struct enlist_entity_item {
223 struct enlist_entity_item *next;
224 int parent_type; char *parent;
225 int child_type; char * child; /* will be created when not found (for "enlist") */
229 static struct enlist_entity_item * enlist_entity_list;
230 static struct enlist_entity_item **enlist_entity_list_tailp = &enlist_entity_list;
233 static void parse_error TAC_ARGS((char *fmt,...)) G_GNUC_PRINTF(1, 2);
237 #include <stdarg.h> /* ANSI C, variable length args */
239 parse_error(char *fmt,...)
243 #include <varargs.h> /* has 'vararg' definitions */
246 parse_error(fmt, va_alist)
248 va_dcl /* no terminating semi-colon */
250 #endif /* __STDC__ */
252 char msg[256]; /* temporary string */
260 vsprintf(msg, fmt, ap);
263 report(LOG_ERR, "%s", msg);
264 fprintf(stderr, "Error: %s\n", msg);
268 const char *cfg_nodestring TAC_ARGS((int type));
276 return ("unknown node type");
284 return ("N_svc_exec");
286 return ("N_svc_slip");
288 return ("N_svc_ppp");
290 return ("N_svc_arap");
292 return ("N_svc_cmd");
300 const char *entity_type_to_string TAC_ARGS((int entity_type));
303 entity_type_to_string(entity_type)
306 switch (entity_type) {
317 static void **entity_type_to_hashtable TAC_ARGS((int entity_type));
320 entity_type_to_hashtable(entity_type)
323 switch (entity_type) {
334 void scan_invalidate_entities TAC_ARGS((enum invalidate_scan what));
337 scan_invalidate_entities(what)
338 enum invalidate_scan what;
340 scan_invalidate_entities_hashtable( usertable, what);
341 scan_invalidate_entities_hashtable( hosttable, what);
342 scan_invalidate_entities_hashtable(grouptable, what);
346 static void free_attrs TAC_ARGS((NODE *node));
355 unlink_expr(node->when);
356 free_expr(node->when);
359 switch (node->type) {
362 if (debug & DEBUG_CLEAN_FLAG)
363 report(LOG_DEBUG, "free_cmd_match %s %s",
364 cfg_nodestring(node->type),
365 (const char *) node->value);
368 report(LOG_ERR, "Illegal node type %s for free_attrs",
369 cfg_nodestring(node->type));
380 static void free_cmd_matches TAC_ARGS((NODE *node));
383 free_cmd_matches(node)
389 if (debug & DEBUG_CLEAN_FLAG)
390 report(LOG_DEBUG, "free_cmd_match %s %s",
391 cfg_nodestring(node->type),
392 (const char *) node->value);
394 unlink_expr(node->when);
395 free_expr(node->when);
398 free(node->value); /* text */
400 #ifdef WITH_INCLUDED_REGEX
402 free(node->value1); /* tac_regexp compiled text */
404 #else /* WITH_INCLUDED_REGEX */
406 regfree((regex_t *) node->value1); /* POSIX regex compiled text */
408 #endif /* WITH_INCLUDED_REGEX */
416 static void free_svcs TAC_ARGS((NODE *node));
425 unlink_expr(node->when);
426 free_expr(node->when);
429 switch (node->type) {
431 if (debug & DEBUG_CLEAN_FLAG)
432 report(LOG_DEBUG, "free %s %s",
433 cfg_nodestring(node->type),
434 (const char *) node->value);
435 free(node->value); /* cmd name */
436 free_cmd_matches(node->value1);
449 if (debug & DEBUG_CLEAN_FLAG)
450 report(LOG_DEBUG, "free %s", cfg_nodestring(node->type));
451 free_attrs(node->value);
458 report(LOG_ERR, "Illegal node type %d for free_svcs", node->type);
464 static void free_enlist_entity_item TAC_ARGS((struct enlist_entity_item *item));
467 free_enlist_entity_item(item)
468 struct enlist_entity_item *item;
472 free_expr(item->when);
476 static void free_entity TAC_ARGS((ENTITY *entity));
482 if (debug & DEBUG_CLEAN_FLAG)
483 report(LOG_DEBUG, "free %s %s",
484 entity_type_to_string(entity->type), entity->name);
486 /* function MUST be called while the whole entity is still VALID! */
487 scan_free_entity(entity);
491 if (entity->full_name)
492 free(entity->full_name);
496 free(entity->expires);
505 free(entity->mschap);
512 free(entity->global);
515 if (entity->before_author)
516 free(entity->before_author);
517 if (entity->after_author)
518 free(entity->after_author);
521 free_svcs(entity->svcs);
524 static void free_hashtable TAC_ARGS((void **hashtable));
527 free_hashtable(hashtable)
531 ENTITY *entity,**entityp;
533 for (i = 0; i < HASH_TAB_SIZE; i++) {
534 entityp = (ENTITY **) (hashtable+i);
535 while ((entity = *entityp)) {
536 *entityp = entity->hash;
548 void cfg_clean_config TAC_ARGS((void));
550 /* Free all allocated structures preparatory to re-reading the config file */
554 struct enlist_entity_item *enlist_entity_item;
556 if (authen_default) {
557 free(authen_default);
558 authen_default = NULL;
561 if (algorithm_recursive) {
562 algorithm_recursive = 0;
565 if (authen_default_method) {
566 authen_default_method = 0;
574 if (session.acctfile) {
575 free(session.acctfile);
576 session.acctfile = NULL;
579 if (session.db_acct) {
580 free(session.db_acct);
581 session.db_acct = NULL;
584 free_hashtable( usertable);
585 free_hashtable( hosttable);
586 free_hashtable(grouptable);
588 while (enlist_entity_list) {
589 enlist_entity_item = enlist_entity_list;
590 enlist_entity_list = enlist_entity_item->next;
591 free_enlist_entity_item(enlist_entity_item);
592 free(enlist_entity_item);
594 enlist_entity_list_tailp = &enlist_entity_list;
597 static int parse_permission TAC_ARGS((void));
602 int symbol = sym_code;
604 if (sym_code != S_permit && sym_code != S_deny) {
605 parse_error("expecting permit or deny but found '%s' on line %d",
614 static int parse TAC_ARGS((int symbol));
621 if (sym_code != symbol) {
622 parse_error("expecting '%s' but found '%s' on line %d",
623 (symbol == S_string ? "string" : codestring(symbol)),
631 static int parse_opt_svc_default TAC_ARGS((void));
634 parse_opt_svc_default()
638 if (sym_code != S_default) {
648 parse_error("expecting 'permit', 'deny' or 'default' but found '%s' on line %d",
653 if (!algorithm_recursive) {
654 parse_error("'default service = %s' supported only if set top level 'authorization = recursive', on line %d",
667 static int parse_opt_attr_default TAC_ARGS((void));
670 parse_opt_attr_default()
672 if (sym_code != S_default)
683 Parse lines in the config file, creating data structures
684 Return 1 on error, otherwise 0 */
686 static int parse_decls TAC_ARGS((void));
691 no_user_dflt = 0; /* default if user doesn't exist */
692 algorithm_recursive = 0; /* use backward compatible alg. by default */
693 when_expr_root_init();
694 enlist_entity_list_tailp = &enlist_entity_list;
699 bzero(grouptable, sizeof(grouptable));
700 bzero(usertable, sizeof(usertable));
701 bzero(hosttable, sizeof(hosttable));
705 /* Top level of parser */
716 if (session.acctfile)
717 free(session.acctfile);
718 session.acctfile = tac_strdup(sym_buf);
723 case S_db_accounting:
727 free(session.db_acct);
728 session.db_acct = tac_strdup(sym_buf);
738 "Expecting default authorization/authentication on lines %d",
742 case S_authentication:
743 if (authen_default) {
745 "Multiply defined authentication default on line %d",
749 parse(S_authentication);
764 authen_default_method = sym_code;
768 parse_error("expecting default_method keyword after 'default authentication = ' on line %d",sym_line);
773 authen_default = tac_strdup(sym_buf);
777 case S_authorization:
778 parse(S_authorization);
781 no_user_dflt = S_permit;
783 "default authorization = permit is now deprecated. Please use user = DEFAULT instead");
787 case S_authorization:
792 parse_error("expecting 'first' or 'recursive' but found '%s' on line %d",
798 algorithm_recursive = 0;
803 algorithm_recursive = 1;
808 /* Process a key declaration. */
812 parse_error("multiply defined key on lines %d and %d",
813 session.keyline, sym_line);
816 session.key = tac_strdup(sym_buf);
817 session.keyline = sym_line;
824 parse_entity(sym_code);
828 parse_error("Unrecognised token %s on line %d", sym_buf, sym_line);
834 /* Assign a value to a field. Issue an error message and return 1 if
835 it's already been assigned. This is a macro because I was sick of
836 repeating the same code fragment over and over */
838 #define ASSIGN(field) \
839 sym_get(); parse(S_separator); if (field) { \
840 parse_error("Duplicate value for %s %s and %s on line %d", \
841 codestring(sym_code), field, sym_buf, sym_line); \
844 field = tac_strdup(sym_buf);
846 static struct expr *when_expr_root;
847 #define WHEN_EXPR_ROOT_SANE() \
848 (when_expr_root && !when_expr_root->next && when_expr_root->type==S_and)
849 #define WHEN_EXPR_ROOT_EMPTY() \
850 (WHEN_EXPR_ROOT_SANE() && !when_expr_root->u.and_or.child_first)
852 static struct expr *parse_expr_node TAC_ARGS((int single_item));
855 parse_expr_node(single_item)
858 struct expr *expr_root = NULL;
859 struct expr **succ_exprp = &expr_root;
866 expr = (struct expr *) tac_malloc(sizeof(struct expr));
867 expr->line = sym_line;
870 succ_exprp = &expr->next;
873 expr->u.not.child = parse_expr_node(1 /* single_item */);
874 if (!expr->u.not.child) {
875 free_expr(expr_root);
883 expr = (struct expr *) tac_malloc(sizeof(struct expr));
884 expr->line = sym_line;
887 succ_exprp = &expr->next;
888 expr->type = sym_code;
890 expr->u.entity.name = tac_strdup(sym_buf);
892 expr->u.entity.entity = NULL; /* not known yet */
897 expr = parse_expr_node(0 /* single_item */);
902 report(LOG_ERR, "Illegal filled next field of parsed parenthesed expr");
903 free_expr(expr_root);
906 succ_exprp = &expr->next;
910 parse_error("expecting 'not', 'user', 'host', 'group' or '(' but found '%s' on line %d",
912 free_expr(expr_root);
916 if (single_item) /* used by 'not' operator with high precedence */
923 if (expr_root->type == (sym_code==S_and ? S_or : S_and)) {
924 parse_error("ambiguous use of 'and' together with 'or', parentheses required on line %d",
926 free_expr(expr_root);
929 if (expr_root->type != sym_code) {
930 expr = (struct expr *) tac_malloc(sizeof(struct expr));
931 expr->line = sym_line;
933 expr->type = sym_code;
934 expr->u.and_or.child_first = expr_root;
945 static struct expr *parse_when_decl TAC_ARGS((void));
951 if (!algorithm_recursive) {
952 parse_error("'when' conditionals supported only if set top level 'authorization = recursive', on line %d",
957 return (parse_expr_node(0 /* single_item */));
960 static void when_expr_root_init TAC_ARGS((void));
963 when_expr_root_init()
965 free_expr(when_expr_root);
966 when_expr_root = new_expr(S_and);
969 static int push_parsed_when_decl TAC_ARGS((void));
972 push_parsed_when_decl()
974 struct expr *parsed_expr;
976 parsed_expr = parse_when_decl();
979 if (!WHEN_EXPR_ROOT_SANE()) {
980 report(LOG_ERR, "INTERNAL: when_expr_root not valid during push_parsed_when_decl()!");
981 free_expr(parsed_expr);
984 if (parsed_expr->next) {
985 report(LOG_ERR, "INTERNAL: Illegal filled next field of parsed expr");
986 free_expr(parsed_expr);
989 parsed_expr->next = when_expr_root->u.and_or.child_first;
990 when_expr_root->u.and_or.child_first = parsed_expr;
991 when_expr_root->line = parsed_expr->line;
995 static int pop_when_decl TAC_ARGS((void));
1000 struct expr *first_expr;
1002 if (!WHEN_EXPR_ROOT_SANE()) {
1003 report(LOG_ERR, "INTERNAL: when_expr_root not valid during pop_when_decl()!");
1006 first_expr = when_expr_root->u.and_or.child_first;
1008 report(LOG_ERR, "No expr in stack and pop_when_decl() called");
1011 when_expr_root->u.and_or.child_first = first_expr->next;
1012 first_expr->next = NULL;
1013 free_expr(first_expr);
1017 static struct expr *copy_current_when_decl TAC_ARGS((void));
1019 static struct expr *
1020 copy_current_when_decl()
1022 return (dupl_expr(when_expr_root));
1025 static struct expr *when_expr_dungeon;
1027 static void starve_when_decl TAC_ARGS((void));
1032 if (!WHEN_EXPR_ROOT_SANE()) {
1033 report(LOG_WARNING, "INTERNAL: when_expr_root not sane during starve_when_decl!");
1035 when_expr_root->next = when_expr_dungeon;
1036 when_expr_dungeon = when_expr_root;
1037 when_expr_root = NULL;
1038 when_expr_root_init();
1041 static int feed_when_decl TAC_ARGS((void));
1046 if (!when_expr_dungeon) {
1047 report(LOG_ERR, "INTERNAL: No expr in dungeon and feed_when_decl() called");
1050 if (!WHEN_EXPR_ROOT_EMPTY()) {
1051 report(LOG_WARNING, "INTERNAL: Some 'when' expression found still pushed in dungeon during feed_when_decl()!");
1053 free_expr(when_expr_root);
1054 when_expr_root = when_expr_dungeon;
1055 when_expr_dungeon = when_expr_dungeon->next;
1056 when_expr_root->next = NULL;
1060 ENTITY *entity_lookup TAC_ARGS((int type, const char *name));
1063 entity_lookup(type, name)
1067 return (hash_lookup(entity_type_to_hashtable(type), name));
1070 static int enlist_entity_connect TAC_ARGS((void));
1073 enlist_entity_connect()
1075 struct enlist_entity_item *item;
1076 ENTITY *parent_entity, *child_entity;
1078 while ((item=enlist_entity_list)) {
1080 parent_entity = entity_lookup(item->parent_type, item->parent);
1081 if (!parent_entity) {
1082 parse_error("Entity %s %s not defined, referenced as parent on line %d",
1083 entity_type_to_string(item->parent_type), item->parent, item->line);
1086 child_entity = entity_lookup(item-> child_type, item-> child);
1087 if (!child_entity) {
1088 child_entity = new_entity(item->child_type, item->child, item->line);
1090 return (1); /* 'hash_add_entry()' conflict */
1091 item->child = NULL; /* don't free string ref'ed from 'child_entity'! */
1094 if (!enlist_entity_direct(parent_entity, child_entity, item->when))
1095 return (1); /* entities not found */
1097 enlist_entity_list = item->next;
1099 free_enlist_entity_item(item);
1102 enlist_entity_list_tailp = &enlist_entity_list;
1106 static void enlist_entity TAC_ARGS((int parent_type, const char *parent, int child_type, const char *child));
1109 enlist_entity(parent_type, parent, child_type, child)
1115 struct enlist_entity_item *item =
1116 (struct enlist_entity_item *) tac_malloc(sizeof(struct enlist_entity_item));
1119 *enlist_entity_list_tailp = item;
1120 enlist_entity_list_tailp = &item->next;
1122 item->parent_type = parent_type;
1123 item->parent = tac_strdup(parent);
1124 item-> child_type = child_type;
1125 item->child = tac_strdup(child);
1126 item->when = copy_current_when_decl();
1127 item->line = sym_line;
1130 static int parse_entity_spec TAC_ARGS((void));
1132 /* returns 0 for error, otherwise S_user, S_host or S_group; sym_buf filled */
1138 if (sym_code != S_user
1139 && sym_code != S_host
1140 && sym_code != S_group
1142 parse_error("Expecting 'user', 'host' or ' group' as entity specification, found %s on line %d",
1153 static int parse_conditional_block_item TAC_ARGS((ENTITY *entity));
1156 parse_conditional_block_item(entity)
1163 /* case S_closebra: not needed, handled by our caller parse_conditional_block() */
1166 parse_error("Unrecognised keyword %s for entity on line %d",
1173 enlist_entity(S_group, sym_buf, entity->type, entity->name);
1178 int parsed_entity_type;
1180 if (entity->type != S_group) {
1181 parse_error("'enlist' keyword allowed only in 'group' section on line %d",
1187 parsed_entity_type = parse_entity_spec();
1188 if (!parsed_entity_type)
1190 enlist_entity(entity->type, entity->name, parsed_entity_type, sym_buf);
1200 * Already parsed some services/commands. Thanks to Gabor Kiss
1201 * who found this bug.
1204 for (p=entity->svcs; p->next; p=p->next)
1206 p->next = parse_svcs();
1208 entity->svcs = parse_svcs();
1213 if (parse_conditional_block(entity))
1221 static int parse_conditional_block TAC_ARGS((ENTITY *entity));
1224 parse_conditional_block(entity)
1227 int retval = -1 /* GCC paranoia */;
1229 if (push_parsed_when_decl())
1234 if (sym_code == S_closebra) {
1236 retval = 0; /* success */
1240 if (parse_conditional_block_item(entity)) {
1241 retval = 1; /* failure */
1246 if (pop_when_decl())
1252 /* passed 'name' WILL be directly stored to returned ENTITY, don't touch it! */
1254 static ENTITY *new_entity TAC_ARGS((int type, char *name, int line));
1257 new_entity(type, name, line)
1262 ENTITY *entity = (ENTITY *) tac_malloc(sizeof(ENTITY));
1263 ENTITY *hash_conflict;
1265 bzero(entity, sizeof(ENTITY));
1266 tac_list_init(&entity->to_parent_membership_list);
1267 tac_list_init(&entity->to_child_membership_list );
1268 entity->to_child_membership_num = 0;
1269 scan_init_entity(entity);
1271 entity->type = type;
1272 entity->name = name;
1273 entity->line = line;
1275 hash_conflict = hash_add_entry(entity_type_to_hashtable(type), (void *) entity);
1276 if (hash_conflict) {
1277 parse_error("multiply defined %s %s on lines %d and %d",
1278 entity_type_to_string(type),
1279 entity->name, hash_conflict->line, sym_line);
1287 static int parse_entity TAC_ARGS((int entity_type));
1290 parse_entity(entity_type)
1295 char **fieldp = NULL /* GCC paranoia */;
1296 char buf[MAX_INPUT_LINE_LEN];
1301 entity = new_entity(entity_type, tac_strdup(sym_buf) /* name */, sym_line /* line */);
1303 return (1); /* 'hash_add_entry()' conflict, 'tac_strdup(sym_buf)' leaked! */
1308 /* Is the default deny for svcs or cmds to be overridden? */
1309 entity->svc_dflt = parse_opt_svc_default();
1312 if (entity_type != S_user)
1315 ASSIGN(entity->key);
1325 ASSIGN(entity->time);
1331 parse(S_authorization);
1332 if (entity->before_author)
1333 free(entity->before_author);
1334 entity->before_author = tac_strdup(sym_buf);
1340 parse(S_authorization);
1341 if (entity->after_author)
1342 free(entity->after_author);
1343 entity->after_author = tac_strdup(sym_buf);
1348 if (entity->login) {
1349 parse_error("Duplicate value for %s %s and %s on line %d",
1350 codestring(sym_code), entity->login,
1359 entity->login = tac_strdup(sym_buf);
1363 /* set to dummy string, so that we detect a duplicate
1364 * password definition attempt
1366 entity->login = tac_strdup(nopasswd_str);
1367 entity->nopasswd = 1;
1375 #endif /* USE_PAM */
1379 sprintf(buf, "%s ", sym_buf);
1381 strcat(buf, sym_buf);
1382 entity->login = tac_strdup(buf);
1388 "expecting 'file', 'cleartext', 'pam'.'nopassword', 'skey', or 'des' keyword after 'login =' on line %d",
1392 "expecting 'file', 'cleartext', 'nopassword', 'skey', or 'des' keyword after 'login =' on line %d",
1394 #endif /* USE_PAM */
1401 parse_error("Duplicate value for %s %s and %s on line %d",
1402 codestring(sym_code), entity->pap,
1415 sprintf(buf, "%s ", sym_buf);
1417 strcat(buf, sym_buf);
1418 entity->pap = tac_strdup(buf);
1421 sprintf(buf, "%s ", sym_buf);
1422 entity->pap = tac_strdup(buf);
1428 "expecting 'cleartext', 'pam', or 'des' keyword after 'pap =' on line %d",
1432 "expecting 'cleartext', or 'des' keyword after 'pap =' on line %d",
1440 ASSIGN(entity->full_name);
1445 ASSIGN(entity->expires);
1450 ASSIGN(entity->msg);
1461 save_sym = sym_code;
1464 sprintf(buf, "%s ", sym_buf);
1466 strcat(buf, sym_buf);
1470 fieldp = &entity->arap;
1473 fieldp = &entity->chap;
1477 fieldp = &entity->mschap;
1481 fieldp = &entity->pap;
1484 fieldp = &entity->opap;
1487 fieldp = &entity->global;
1490 report(LOG_ERR, "INTERNAL: fieldp not recognized (on line %d)",
1496 parse_error("Duplicate value for %s %s and %s on line %d",
1497 codestring(save_sym), *fieldp, sym_buf, sym_line);
1500 *fieldp = tac_strdup(buf);
1512 if (sscanf(sym_buf, "%d", &entity->maxsess) != 1) {
1513 parse_error("expecting integer, found '%s' on line %d",
1518 #endif /* MAXSESS */
1521 if (STREQ(sym_buf, "password")) {
1523 "\npassword = <string> is obsolete. Use login = des <string>\n");
1526 if (parse_conditional_block_item(entity))
1527 return (0); /* error message already printed */
1532 static NODE *parse_svcs TAC_ARGS((void));
1547 result = (NODE *) tac_malloc(sizeof(NODE));
1549 bzero(result, sizeof(NODE));
1550 result->line = sym_line;
1552 /* cmd declaration */
1553 if (sym_code == S_cmd) {
1556 result->value = tac_strdup(sym_buf);
1561 result->value1 = parse_cmd_matches();
1563 if (feed_when_decl())
1564 tac_exit(1); /* no error return possibility */
1566 result->type = N_svc_cmd;
1567 result->when = copy_current_when_decl();
1568 expr_sink_register(result->when);
1570 result->next = parse_svcs();
1574 /* svc declaration */
1579 parse_error("expecting service type but found %s on line %d",
1584 result->type = N_svc;
1585 /* should perhaps check that this is an allowable service name */
1586 result->value1 = tac_strdup(sym_buf);
1589 result->type = N_svc_exec;
1592 result->type = N_svc_arap;
1595 result->type = N_svc_slip;
1598 result->type = N_svc_ppp;
1602 /* Should perhaps check that this is a known PPP protocol name */
1603 result->value1 = tac_strdup(sym_buf);
1611 result->dflt = parse_opt_attr_default();
1612 result->value = parse_attrs();
1617 result->when = copy_current_when_decl();
1618 expr_sink_register(result->when);
1620 result->next = parse_svcs();
1624 /* <cmd_match> := <permission> <string> */
1626 static NODE *parse_cmd_matches TAC_ARGS((void));
1631 NODE *retval = NULL, **succp = &retval;
1640 if (push_parsed_when_decl())
1641 tac_exit(1); /* no error return possibility */
1643 result = parse_cmd_matches();
1645 if (pop_when_decl())
1646 tac_exit(1); /* no error return possibility */
1652 result = (NODE *) tac_malloc(sizeof(NODE));
1654 bzero(result, sizeof(NODE));
1655 result->line = sym_line;
1657 result->type = (parse_permission() == S_permit) ? N_permit : N_deny;
1658 result->value = tac_strdup(sym_buf);
1660 #ifdef WITH_INCLUDED_REGEX
1662 result->value1 = (void *) tac_regcomp(result->value);
1664 #else /* WITH_INCLUDED_REGEX */
1666 result->value1 = tac_malloc(sizeof(regex_t));
1667 if (regcomp(result->value1, result->value /* regex */, REG_NOSUB /* cflags */)) {
1668 free(result->value1);
1669 result->value1 = NULL;
1672 #endif /* WITH_INCLUDED_REGEX */
1674 if (!result->value1) {
1675 report(LOG_ERR, "in regular expression %s on line %d",
1681 result->when = copy_current_when_decl();
1682 expr_sink_register(result->when);
1684 result->next = NULL;
1687 while (result->next)
1688 result = result->next; /* skip parsed chain from parse_cmd_matches() */
1689 succp = &result->next;
1694 static NODE *parse_attrs TAC_ARGS((void));
1699 NODE *retval = NULL, **succp = &retval;
1701 char buf[MAX_INPUT_LINE_LEN];
1712 if (push_parsed_when_decl())
1713 tac_exit(1); /* no error return possibility */
1715 result = parse_attrs();
1717 if (pop_when_decl())
1718 tac_exit(1); /* no error return possibility */
1726 result = (NODE *) tac_malloc(sizeof(NODE));
1728 bzero(result, sizeof(NODE));
1729 result->line = sym_line;
1731 result->type = optional ? N_optarg : N_arg;
1733 strcpy(buf, sym_buf);
1735 strcat(buf, sym_buf);
1737 strcat(buf, sym_buf);
1740 result->value = tac_strdup(buf);
1742 result->when = copy_current_when_decl();
1743 expr_sink_register(result->when);
1745 result->next = NULL;
1748 while (result->next)
1749 result = result->next; /* skip parsed chain from parse_attrs() */
1750 succp = &result->next;
1756 static void sym_get TAC_ARGS((void));
1763 if (debug & DEBUG_PARSE_FLAG) {
1764 report(LOG_DEBUG, "line=%d sym=%s code=%d buf='%s'",
1765 sym_line, codestring(sym_code), sym_code, sym_buf);
1769 static char *sym_buf_add TAC_ARGS((int c));
1773 int c; /* promoted "char" type */
1775 if (sym_pos >= MAX_INPUT_LINE_LEN) {
1776 sym_buf[MAX_INPUT_LINE_LEN-1] = '\0';
1777 if (debug & DEBUG_PARSE_FLAG) {
1778 report(LOG_DEBUG, "line too long: line=%d sym=%s code=%d buf='%s'",
1779 sym_line, codestring(sym_code), sym_code, sym_buf);
1784 sym_buf[sym_pos++] = c;
1788 static void getsym TAC_ARGS((void));
1808 while (sym_ch == ' ' || sym_ch == '\t')
1813 strcpy(sym_buf, "=");
1814 sym_code = S_separator;
1819 strcpy(sym_buf, "{");
1820 sym_code = S_openbra;
1825 strcpy(sym_buf, "}");
1826 sym_code = S_closebra;
1831 strcpy(sym_buf, "(");
1832 sym_code = S_openparen;
1837 strcpy(sym_buf, ")");
1838 sym_code = S_closeparen;
1843 while ((sym_ch != '\n') && (sym_ch != EOF))
1852 if (sym_ch == '"') {
1856 /* backslash-double-quote is supported inside strings */
1858 if (sym_ch == '\\') {
1862 /* preserve the slash for \n */
1863 if (!sym_buf_add('\\')) {
1864 sym_code = S_unknown;
1871 if (!sym_buf_add(sym_ch)) {
1872 sym_code = S_unknown;
1879 sym_code = S_unknown;
1884 if (!sym_buf_add(sym_ch)) {
1885 sym_code = S_unknown;
1893 if (!sym_buf_add('\0')) {
1894 sym_code = S_unknown;
1898 sym_code = S_string;
1903 while (sym_ch != '\t' && sym_ch != ' ' && sym_ch != '='
1904 && sym_ch != '\n') {
1906 if (!sym_buf_add(sym_ch)) {
1907 sym_code = S_unknown;
1914 if (!sym_buf_add('\0')) {
1915 sym_code = S_unknown;
1919 sym_code = keycode(sym_buf);
1920 if (sym_code == S_unknown)
1921 sym_code = S_string;
1926 static void rch TAC_ARGS((void));
1937 if (parse_only && sym_ch != EOF)
1938 fprintf(stderr, "%c", sym_ch);
1942 static VALUE get_value TAC_ARGS((ENTITY *entity, int field));
1944 /* Find the value of a field. Does not recurse. */
1946 get_value(entity, field)
1952 v.pval = NULL; /* do both just for sure... */
1956 parse_error("get_value: illegal entity");
1962 v.pval = entity->name;
1966 v.pval = entity->login;
1970 v.pval = entity->global;
1974 v.pval = entity->expires;
1978 v.pval = entity->arap;
1982 v.pval = entity->chap;
1987 v.pval = entity->mschap;
1992 v.pval = entity->pap;
1996 v.pval = entity->opap;
2000 v.pval = entity->msg;
2004 v.pval = entity->svcs;
2008 v.pval = entity->before_author;
2012 v.pval = entity->after_author;
2016 v.intval = entity->svc_dflt;
2021 v.intval = entity->maxsess;
2026 v.intval = entity->nopasswd;
2030 v.pval = entity->time;
2034 if (entity->type == S_user) {
2035 report(LOG_ERR, "get_value: S_key field not supported in %s %s",
2036 entity_type_to_string(entity->type), entity->name);
2040 v.pval = entity->key;
2044 report(LOG_ERR, "get_value: unknown field %d", field);
2051 /* Internal graph scanning routines */
2053 static enum value_scan_func_result value_scan TAC_ARGS((int type, const char *name, int recurse, value_scan_func_t func, void *func_data));
2055 static enum value_scan_func_result
2056 value_scan(type, name, recurse, func, func_data)
2060 value_scan_func_t func;
2065 if (debug & DEBUG_CONFIG_FLAG)
2066 report(LOG_DEBUG, "value_scan: find %s %s, recurse=%d",
2067 entity_type_to_string(type), name, recurse);
2069 entity = entity_lookup(type, name);
2071 if (debug & DEBUG_CONFIG_FLAG)
2072 report(LOG_DEBUG, "value_scan: no %s named %s",
2073 entity_type_to_string(type), name);
2074 return (VSFR_CONTINUE);
2077 return (value_scan_entity(entity, recurse, func, func_data));
2080 /* For each user, check she doesn't circularly reference a
2081 group. Return 1 if it does */
2083 static int circularity_check_failed;
2085 static void circularity_check_fail TAC_ARGS((struct membership *membership));
2088 circularity_check_fail(membership)
2089 struct membership *membership;
2093 circularity_check_failed = 1;
2095 report(LOG_ERR, "recursively defined groups:");
2096 while (membership) {
2097 entity = MEMBERSHIP_TO_CHILD_ENTITY(membership);
2098 report(LOG_ERR, "%s %s",
2099 entity_type_to_string(entity->type), entity->name);
2100 membership = value_scan_backward(entity);
2104 static enum value_scan_func_result circularity_check_func TAC_ARGS((ENTITY *entity, void *func_data));
2106 static enum value_scan_func_result
2107 circularity_check_func(entity, func_data /* unused */)
2111 /* only useful to speedup case of failure */
2112 if (circularity_check_failed)
2113 return (VSFR_FOUND);
2115 return (VSFR_CONTINUE);
2118 static int circularity_check TAC_ARGS((void));
2124 ENTITY **users_base = (ENTITY **) hash_get_entries(usertable);
2128 for (users = users_base; *users; users++) {
2131 if (debug & DEBUG_PARSE_FLAG)
2132 report(LOG_DEBUG, "circularity_check: user=%s", entity->name);
2134 circularity_check_failed = 0;
2135 value_scan_forward_seen_hook = circularity_check_fail;
2136 value_scan_entity(entity, TAC_PLUS_RECURSE,
2137 (value_scan_func_t) circularity_check_func, NULL /* func_data-unused */);
2138 value_scan_forward_seen_hook = NULL;
2139 if (circularity_check_failed)
2143 return (circularity_check_failed);
2147 /* Return a value for a group or user (isuser says if
2148 this name is a group or a user name).
2150 If no value exists, and recurse is true, also check groups we are a
2151 member of, recursively.
2153 Returns void * because it can return a string or a node pointer
2154 (should really return a union pointer).
2157 static VALUE cfg_get_value_VALUE; /* private */
2159 static enum value_scan_func_result cfg_get_value_func TAC_ARGS((ENTITY *entity, int *attrp));
2161 static enum value_scan_func_result
2162 cfg_get_value_func(entity,attrp /* func_data */)
2166 /* found the entry. Lookup value from attr=value */
2167 cfg_get_value_VALUE = get_value(entity, *attrp);
2168 if (cfg_get_value_VALUE.pval)
2169 return (VSFR_FOUND);
2171 return (VSFR_CONTINUE);
2174 static VALUE cfg_get_value TAC_ARGS((int type, const char *name, int attr, int recurse));
2177 cfg_get_value(type, name, attr, recurse)
2182 if (debug & DEBUG_CONFIG_FLAG)
2183 report(LOG_DEBUG, "cfg_get_value: type=%s name=%s attr=%s recurse=%d",
2184 entity_type_to_string(type), name, codestring(attr), recurse);
2186 cfg_get_value_VALUE.pval = NULL;
2187 value_scan(type, name, recurse,
2188 (value_scan_func_t) cfg_get_value_func, &attr /* func_data */);
2189 return (cfg_get_value_VALUE);
2193 /* Wrappers for cfg_get_value:
2196 int cfg_get_intvalue TAC_ARGS((int type, const char *name, int attr, int recurse));
2199 cfg_get_intvalue(type, name, attr, recurse)
2204 int val = cfg_get_value(type, name, attr, recurse).intval;
2206 if (debug & DEBUG_CONFIG_FLAG)
2207 report(LOG_DEBUG, "cfg_get_intvalue: returns %d", val);
2211 const char *cfg_get_pvalue TAC_ARGS((int type, const char *name, int attr, int recurse));
2214 cfg_get_pvalue(type, name, attr, recurse)
2219 char *p = cfg_get_value(type, name, attr, recurse).pval;
2221 if (debug & DEBUG_CONFIG_FLAG)
2222 report(LOG_DEBUG, "cfg_get_pvalue: returns %s",
2227 /* Read the config file and do some basic sanity checking on
2228 * it. Return 1 if we find any errors.
2230 int cfg_read_config TAC_ARGS((const char *cfile));
2233 cfg_read_config(cfile)
2238 if ((cf = fopen(cfile, "r")) == NULL) {
2239 report(LOG_ERR, "read_config: fopen() error for file %s %s, exiting",
2240 cfile, sys_errlist[errno]);
2243 if (parse_decls() || sym_error) {
2249 || enlist_entity_connect()
2250 || expr_sink_commit()
2251 /* circularity is allowed in the new fully-recursive algorithm */
2252 || (!algorithm_recursive && circularity_check())
2257 if (!WHEN_EXPR_ROOT_EMPTY() || when_expr_dungeon) {
2258 report(LOG_ERR, "Some 'when' expression found still pushed on stack");
2267 /* return 1 if user exists, 0 otherwise
2269 int cfg_user_exists TAC_ARGS((const char *username));
2272 cfg_user_exists(username)
2273 const char *username;
2275 return (NULL != hash_lookup(usertable, username));
2278 /* return expiry string of user. If none, try groups she is a member
2279 * on, and so on, recursively if recurse is non-zero
2281 const char *cfg_get_expires TAC_ARGS((const char *username, int recurse));
2284 cfg_get_expires(username, recurse)
2285 const char *username;
2288 return (cfg_get_pvalue(S_user, username, S_expires, recurse));
2291 /* return time string of user. If none, try groups she is a member
2292 * on, and so on, recursively if recurse is non-zero
2294 const char *cfg_get_timestamp TAC_ARGS((const char *username, int recurse));
2297 cfg_get_timestamp(username, recurse)
2298 const char *username;
2301 return (cfg_get_pvalue(S_user, username, S_time, recurse));
2304 /* return password string of user. If none, try groups she is a member
2305 * on, and so on, recursively if recurse is non-zero
2307 const char *cfg_get_login_secret TAC_ARGS((const char *user, int recurse));
2310 cfg_get_login_secret(user, recurse)
2314 return (cfg_get_pvalue(S_user, user, S_login, recurse));
2317 /* return value of the nopasswd field. If none, try groups she is a member
2318 * on, and so on, recursively if recurse is non-zero
2320 int cfg_get_user_nopasswd TAC_ARGS((const char *user, int recurse));
2323 cfg_get_user_nopasswd(user, recurse)
2327 return (cfg_get_intvalue(S_user, user, S_nopasswd, recurse));
2330 /* return user's secret. If none, try groups she is a member
2331 * on, and so on, recursively if recurse is non-zero
2333 const char *cfg_get_arap_secret TAC_ARGS((const char *user, int recurse));
2336 cfg_get_arap_secret(user, recurse)
2340 return (cfg_get_pvalue(S_user, user, S_arap, recurse));
2343 const char *cfg_get_chap_secret TAC_ARGS((const char *user, int recurse));
2346 cfg_get_chap_secret(user, recurse)
2350 return (cfg_get_pvalue(S_user, user, S_chap, recurse));
2355 const char *cfg_get_mschap_secret TAC_ARGS((const char *user, int recurse));
2358 cfg_get_mschap_secret(user, recurse)
2362 return (cfg_get_pvalue(S_user, user, S_mschap, recurse));
2367 const char *cfg_get_pap_secret TAC_ARGS((const char *user, int recurse));
2370 cfg_get_pap_secret(user, recurse)
2374 return (cfg_get_pvalue(S_user, user, S_pap, recurse));
2377 const char *cfg_get_opap_secret TAC_ARGS((const char *user, int recurse));
2380 cfg_get_opap_secret(user, recurse)
2384 return (cfg_get_pvalue(S_user, user, S_opap, recurse));
2387 /* return the global password for the user (or the group, etc.) */
2389 const char *cfg_get_global_secret TAC_ARGS((const char *user, int recurse));
2392 cfg_get_global_secret(user, recurse)
2396 return (cfg_get_pvalue(S_user, user, S_global, recurse));
2401 /* Return a pointer to a node representing a PAM Service name */
2403 const char *cfg_get_pam_service TAC_ARGS((const char *user, int recurse));
2406 cfg_get_pam_service(user, recurse)
2410 const char *cfg_passwd;
2413 cfg_passwd = cfg_get_pap_secret(user, recurse);
2416 cfg_passwd = cfg_get_global_secret(user, recurse);
2418 if (!cfg_passwd && !cfg_user_exists(user)) {
2419 cfg_passwd = cfg_get_authen_default();
2420 switch (cfg_get_authen_default_method()) {
2423 if (debug & DEBUG_AUTHOR_FLAG)
2424 report(LOG_DEBUG, "Get Default PAM Service :%s",cfg_passwd);
2429 if (debug & DEBUG_AUTHOR_FLAG)
2430 report(LOG_DEBUG, "I havent find any PAM Service!!");
2431 return(NULL);/* Haven't any PAM Service!! */
2435 p = tac_find_substring("pam ", cfg_passwd);
2437 if(p) { /* We find PAM services */
2438 if (debug & DEBUG_AUTHOR_FLAG)
2439 report(LOG_DEBUG, "I get PAM sevice:%s",p);
2443 if (debug & DEBUG_AUTHOR_FLAG)
2444 report(LOG_DEBUG, "No any PAM Sevice");
2449 #endif /* For PAM */
2452 /* Return a pointer to a node representing a given service
2453 authorization, taking care of recursion issues correctly. Protocol
2454 is only read if the svctype is N_svc_ppp. svcname is only read if type
2458 struct cfg_get_svc_node_param {
2460 const char *protocol, *svcname;
2465 static enum value_scan_func_result cfg_get_svc_node_func TAC_ARGS((ENTITY *entity, struct cfg_get_svc_node_param *param));
2467 static enum value_scan_func_result
2468 cfg_get_svc_node_func(entity, param /* func_data */)
2470 struct cfg_get_svc_node_param *param;
2473 enum eval_result svc_default;
2475 for (svc = (NODE *) get_value(entity, S_svc).pval; svc; svc = svc->next) {
2476 if (svc->type != param->svctype)
2478 if (param->svctype == N_svc_ppp && param->protocol && !STREQ(svc->value1, param->protocol))
2480 if (param->svctype == N_svc && param->svcname && !STREQ(svc->value1, param->svcname ))
2482 if (expr_eval(svc->when) != ER_TRUE) /* expensive */
2485 if (debug & DEBUG_CONFIG_FLAG)
2487 "cfg_get_svc_node: found %s proto=%s svcname=%s",
2488 cfg_nodestring(param->svctype),
2489 param->protocol ? param->protocol : "",
2490 param->svcname ? param->svcname : "");
2494 return (VSFR_FOUND);
2497 /* look at 'default service' settings */
2498 svc_default = entity_svc_default(entity);
2499 switch (svc_default) {
2503 if (debug & DEBUG_AUTHOR_FLAG)
2505 "cfg_get_svc_node: svc=%s protocol=%s svcname=%s forced %s by default service",
2506 cfg_nodestring(param->svctype),
2507 param->protocol ? param->protocol : "",
2508 param->svcname ? param->svcname : "",
2509 (svc_default == ER_TRUE ? "permit" : "deny"));
2511 param->retval = (svc_default == ER_TRUE);
2512 return (VSFR_FOUND);
2514 default: /* shouldn't happen */
2516 return (VSFR_CONTINUE);
2521 int cfg_get_svc_node TAC_ARGS((const char *username, int svctype, const char *protocol, const char *svcname, int recurse, NODE **nodep));
2524 cfg_get_svc_node(username, svctype, protocol, svcname, recurse, nodep)
2525 const char *username;
2527 const char *protocol;
2528 const char *svcname;
2532 struct cfg_get_svc_node_param param;
2533 enum value_scan_func_result vsfr;
2535 param.svctype = svctype;
2536 param.protocol = protocol;
2537 param.svcname = svcname;
2541 if (debug & DEBUG_CONFIG_FLAG)
2543 "cfg_get_svc_node: username=%s %s proto=%s svcname=%s rec=%d",
2545 cfg_nodestring(svctype),
2546 protocol ? protocol : "",
2547 svcname ? svcname : "",
2550 vsfr = value_scan(S_user, username, recurse,
2551 (value_scan_func_t) cfg_get_svc_node_func, ¶m /* func_data */);
2553 *nodep = param.node;
2555 if (vsfr == VSFR_FOUND)
2556 return (param.retval);
2558 /* The service does not exist. Do the default */
2559 return (cfg_no_user_permitted() ? 1 : 0);
2562 /* Return a pointer to the node representing a set of command tac_regexp
2563 matches for a user and command, handling recursion issues correctly */
2565 struct cfg_authorize_cmd_param {
2568 enum eval_result result;
2571 static enum value_scan_func_result cfg_authorize_cmd_func TAC_ARGS((ENTITY *entity, struct cfg_authorize_cmd_param *param));
2573 static enum value_scan_func_result
2574 cfg_authorize_cmd_func(entity, param /* func_data */)
2576 struct cfg_authorize_cmd_param *param;
2580 for (svc = (NODE *) get_value(entity, S_svc).pval; svc; svc = svc->next) {
2583 if (svc->type != N_svc_cmd)
2585 if (!STREQ(svc->value, param->cmd))
2587 if (expr_eval(svc->when) != ER_TRUE) /* expensive */
2590 if (debug & DEBUG_CONFIG_FLAG)
2591 report(LOG_DEBUG, "cfg_authorize_cmd: found cmd %s %s node",
2592 param->cmd, cfg_nodestring(svc->type));
2594 /* we have 'cmd <openbra>' point, now traverse through its 'permit'/'deny' pairs: */
2596 for (node = svc->value1; node; node = node->next) {
2599 if (expr_eval(node->when) != ER_TRUE) /* expensive */
2602 #ifdef WITH_INCLUDED_REGEX
2604 match = tac_regexec((tac_regexp *) node->value1, param->args);
2606 #else /* WITH_INCLUDED_REGEX */
2608 match = !regexec((const regex_t *) node->value1, param->args /* string */,
2609 0 /* nmatch */, NULL /* pmatch */, 0 /* eflags */);
2611 #endif /* WITH_INCLUDED_REGEX */
2613 if (debug & DEBUG_AUTHOR_FLAG) {
2614 report(LOG_INFO, "line %d compare %s %s '%s' & '%s' %smatch",
2615 node->line, param->cmd,
2616 node->type == N_permit ? "permit" : "deny",
2617 (const char *) node->value, param->args, (match ? "" : "no "));
2623 switch (node->type) {
2625 if (debug & DEBUG_AUTHOR_FLAG) {
2626 report(LOG_DEBUG, "%s %s permitted by line %d",
2627 param->cmd, param->args, node->line);
2629 param->result = ER_TRUE;
2630 return (VSFR_FOUND);
2633 if (debug & DEBUG_AUTHOR_FLAG) {
2634 report(LOG_DEBUG, "%s %s denied by line %d",
2635 param->cmd, param->args, node->line);
2637 param->result = ER_FALSE;
2638 return (VSFR_FOUND);
2641 report(LOG_ERR, "INTERNAL: illegal configuration node: %s: %s %s",
2642 session.peer, param->cmd, param->args);
2643 param->result = ER_UNKNOWN; /* error */
2644 return (VSFR_FOUND);
2647 if (!algorithm_recursive) { /* compatibility mode: */
2648 if (debug & DEBUG_AUTHOR_FLAG)
2649 report(LOG_DEBUG, "cmd %s exists, but no args match, denied (as no 'authorization = recursive' found)",
2651 param->result = ER_FALSE; /* emulate last "deny .*" */
2652 return (VSFR_FOUND);
2656 /* look at 'default service' settings */
2657 param->result = entity_svc_default(entity);
2658 switch (param->result) {
2661 if (debug & DEBUG_AUTHOR_FLAG)
2662 report(LOG_DEBUG, "cmd %s does not exist, permitted by default", param->cmd);
2663 return (VSFR_FOUND);
2667 if (debug & DEBUG_AUTHOR_FLAG)
2668 report(LOG_DEBUG, "cmd %s does not exist, denied by default", param->cmd);
2669 return (VSFR_FOUND);
2671 default: /* shouldn't happen */
2673 return (VSFR_CONTINUE);
2678 enum eval_result cfg_authorize_cmd TAC_ARGS((const char *username, const char *cmd, const char *args));
2681 cfg_authorize_cmd(username, cmd, args)
2682 const char *username;
2686 struct cfg_authorize_cmd_param param;
2690 param.result = ER_UNKNOWN; /* error */
2692 if (debug & DEBUG_CONFIG_FLAG)
2693 report(LOG_DEBUG, "cfg_authorize_cmd: name=%s cmdname=%s args=%s",
2694 username, cmd, args);
2696 value_scan(S_user, username, TAC_PLUS_RECURSE,
2697 (value_scan_func_t) cfg_authorize_cmd_func, ¶m /* func_data */);
2699 if (param.result != ER_UNKNOWN)
2700 return (param.result);
2702 /* The command does not exist. Do the default */
2703 return (cfg_no_user_permitted() ? ER_TRUE : ER_FALSE);
2706 /* Return an array of character strings representing configured AV
2707 * pairs, given a username and a service node.
2709 * In the AV strings returned, manipulate the separator character to
2710 * indicate which args are optional and which are mandatory.
2712 * Lastly, indicate what default permission was configured by setting
2715 char **cfg_get_svc_attrs TAC_ARGS((NODE *svcnode, int *denyp));
2718 cfg_get_svc_attrs(svcnode, denyp)
2731 *denyp = (svcnode->dflt == S_deny);
2734 for (node = svcnode->value; node; node = node->next)
2737 args = (char **) tac_malloc(sizeof(char *) * (i + 1));
2740 for (node = svcnode->value; node; node = node->next) {
2744 if (expr_eval(node->when) != ER_TRUE) /* expensive */
2745 continue; /* ignore this node */
2747 arg = tac_strdup(node->value);
2748 p = index(arg, '=');
2749 if (p && node->type == N_optarg)
2758 static enum eval_result entity_svc_default TAC_ARGS((ENTITY *entity));
2760 static enum eval_result
2761 entity_svc_default(entity)
2764 switch (entity->svc_dflt) {
2770 case 0: /* not specified */
2771 return (ER_UNKNOWN);
2773 report(LOG_ERR, "INTERNAL: invalid entity svc_dflt (%d)", entity->svc_dflt);
2774 return (ER_UNKNOWN);
2778 int cfg_no_user_permitted TAC_ARGS((void));
2781 cfg_no_user_permitted()
2783 if (no_user_dflt == S_permit)
2789 const char *cfg_get_authen_default TAC_ARGS((void));
2792 cfg_get_authen_default()
2794 return (authen_default);
2797 int cfg_get_authen_default_method TAC_ARGS((void));
2799 /* For describe authentication method(pam,file,db..etc) */
2801 cfg_get_authen_default_method()
2803 return (authen_default_method);
2807 /* Host entity management:
2810 const char *cfg_get_host_key TAC_ARGS((const char *host));
2812 /* For getting host key */
2814 cfg_get_host_key(host)
2817 return (cfg_get_pvalue(S_host, host, S_key, algorithm_recursive /* recurse */));
2820 static ENTITY *force_belong_entity TAC_ARGS((int type, const char *name));
2823 force_belong_entity(type, name)
2827 ENTITY *entity = entity_lookup(type, name);
2830 eval_force_belong_entity(entity);
2835 /* assumed existing initialized "session.peer*" */
2837 static ENTITY *request_peer_addr;
2838 static ENTITY *request_peer;
2839 static ENTITY *request_DEFAULT_group;
2841 static void enlist_request_peer TAC_ARGS((const char *hostname, ENTITY **entityp));
2844 enlist_request_peer(hostname, entityp)
2845 const char *hostname;
2852 *entityp = force_belong_entity(S_host, hostname);
2853 if (*entityp && request_DEFAULT_group)
2854 virtual_enlist_entity_direct(request_DEFAULT_group /* parent */, *entityp /* child */);
2857 /* Try to build the following scenery:
2859 * host <session.peer_addr> [=ER_TRUE]
2861 * +-- group <DEFAULT_GROUPNAME>
2863 * host <session.peer > [=ER_TRUE]
2865 * +-- group <DEFAULT_GROUPNAME>
2868 void cfg_request_scan_begin TAC_ARGS((void));
2871 cfg_request_scan_begin()
2873 request_scan_begin();
2875 request_DEFAULT_group = entity_lookup(S_group, DEFAULT_GROUPNAME);
2877 if (session.peer_addr != session.peer)
2878 enlist_request_peer(session.peer_addr, &request_peer_addr);
2879 enlist_request_peer(session.peer, &request_peer);
2882 /* Try to build the following scenery:
2884 * ( user <identity->username> | user <DEFAULT_USERNAME> ) [=ER_TRUE]
2886 * +-- host <session.peer_addr> [=ER_TRUE]
2888 * | +- group <DEFAULT_GROUPNAME>
2890 * +-- host <session.peer > [=ER_TRUE]
2892 * | +-- group <DEFAULT_GROUPNAME>
2894 * +-- group <DEFAULT_GROUPNAME>
2897 void cfg_request_identity TAC_ARGS((const struct identity *identity));
2900 cfg_request_identity(identity)
2901 const struct identity *identity;
2903 ENTITY *user_entity,*request_DEFAULT_group;
2905 if (debug & DEBUG_CONFIG_FLAG)
2906 report(LOG_DEBUG, "cfg_request_identity: username=%s, NAS_name=%s, NAS_port=%s, NAC_address=%s, priv_lvl=%d",
2907 identity->username, identity->NAS_name, identity->NAS_port, identity->NAC_address, identity->priv_lvl);
2909 user_entity = force_belong_entity(S_user, identity->username);
2910 request_DEFAULT_group = entity_lookup(S_group, DEFAULT_GROUPNAME);
2913 user_entity = force_belong_entity(S_user, DEFAULT_USERNAME);
2915 request_scan_user_known = 1;
2920 if (request_peer_addr)
2921 virtual_enlist_entity_direct(request_peer_addr /* parent */, user_entity /* child */);
2923 virtual_enlist_entity_direct(request_peer /* parent */, user_entity /* child */);
2924 if (request_DEFAULT_group)
2925 virtual_enlist_entity_direct(request_DEFAULT_group /* parent */, user_entity /* child */);