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;
848 static void when_expr_root_init TAC_ARGS((void));
851 when_expr_root_init()
853 free_expr(when_expr_root);
854 when_expr_root = new_expr(S_and);
857 static struct expr *parse_expr_node TAC_ARGS((int single_item));
860 parse_expr_node(single_item)
863 struct expr *expr_root = NULL;
864 struct expr **succ_exprp = &expr_root;
871 expr = (struct expr *) tac_malloc(sizeof(struct expr));
872 expr->line = sym_line;
875 succ_exprp = &expr->next;
878 expr->u.not.child = parse_expr_node(1 /* single_item */);
879 if (!expr->u.not.child) {
880 free_expr(expr_root);
888 expr = (struct expr *) tac_malloc(sizeof(struct expr));
889 expr->line = sym_line;
892 succ_exprp = &expr->next;
893 expr->type = sym_code;
895 expr->u.entity.name = tac_strdup(sym_buf);
897 expr->u.entity.entity = NULL; /* not known yet */
902 expr = parse_expr_node(0 /* single_item */);
907 report(LOG_ERR, "Illegal filled next field of parsed parenthesed expr");
908 free_expr(expr_root);
911 succ_exprp = &expr->next;
915 parse_error("expecting 'not', 'user', 'host', 'group' or '(' but found '%s' on line %d",
917 free_expr(expr_root);
921 if (single_item) /* used by 'not' operator with high precedence */
928 if (expr_root->type == (sym_code==S_and ? S_or : S_and)) {
929 parse_error("ambiguous use of 'and' together with 'or', parentheses required on line %d",
931 free_expr(expr_root);
934 if (expr_root->type != sym_code) {
935 expr = (struct expr *) tac_malloc(sizeof(struct expr));
936 expr->line = sym_line;
938 expr->type = sym_code;
939 expr->u.and_or.child_first = expr_root;
950 static struct expr *parse_when_decl TAC_ARGS((void));
956 if (!algorithm_recursive) {
957 parse_error("'when' conditionals supported only if set top level 'authorization = recursive', on line %d",
962 return (parse_expr_node(0 /* single_item */));
965 static int push_parsed_when_decl TAC_ARGS((void));
968 push_parsed_when_decl()
970 struct expr *new_expr;
972 new_expr = parse_when_decl();
975 if (new_expr->next) {
976 report(LOG_ERR, "Illegal filled next field of parsed expr");
980 new_expr->next = when_expr_root->u.and_or.child_first;
981 when_expr_root->u.and_or.child_first = new_expr;
982 when_expr_root->line = new_expr->line;
986 static int pop_when_decl TAC_ARGS((void));
991 struct expr *first_expr;
993 first_expr = when_expr_root->u.and_or.child_first;
995 report(LOG_ERR, "No expr in stack and pop_when_decl() called");
998 when_expr_root->u.and_or.child_first = first_expr->next;
999 free_expr(first_expr);
1003 static struct expr *copy_current_when_decl TAC_ARGS((void));
1005 static struct expr *
1006 copy_current_when_decl()
1008 return (dupl_expr(when_expr_root));
1011 ENTITY *entity_lookup TAC_ARGS((int type, const char *name));
1014 entity_lookup(type, name)
1018 return (hash_lookup(entity_type_to_hashtable(type), name));
1021 static int enlist_entity_connect TAC_ARGS((void));
1024 enlist_entity_connect()
1026 struct enlist_entity_item *item;
1027 ENTITY *parent_entity, *child_entity;
1029 while ((item=enlist_entity_list)) {
1031 parent_entity = entity_lookup(item->parent_type, item->parent);
1032 if (!parent_entity) {
1033 parse_error("Entity %s %s not defined, referenced as parent on line %d",
1034 entity_type_to_string(item->parent_type), item->parent, item->line);
1037 child_entity = entity_lookup(item-> child_type, item-> child);
1038 if (!child_entity) {
1039 child_entity = new_entity(item->child_type, item->child, item->line);
1041 return (1); /* 'hash_add_entry()' conflict */
1042 item->child = NULL; /* don't free string ref'ed from 'child_entity'! */
1045 enlist_entity_direct(parent_entity, child_entity, item->when);
1047 enlist_entity_list = item->next;
1049 free_enlist_entity_item(item);
1052 enlist_entity_list_tailp = &enlist_entity_list;
1056 static void enlist_entity TAC_ARGS((int parent_type, const char *parent, int child_type, const char *child));
1059 enlist_entity(parent_type, parent, child_type, child)
1065 struct enlist_entity_item *item =
1066 (struct enlist_entity_item *) tac_malloc(sizeof(struct enlist_entity_item));
1069 *enlist_entity_list_tailp = item;
1070 enlist_entity_list_tailp = &item->next;
1072 item->parent_type = parent_type;
1073 item->parent = tac_strdup(parent);
1074 item-> child_type = child_type;
1075 item->child = tac_strdup(child);
1076 item->when = copy_current_when_decl();
1077 item->line = sym_line;
1080 static int parse_entity_spec TAC_ARGS((void));
1082 /* returns 0 for error, otherwise S_user, S_host or S_group; sym_buf filled */
1088 if (sym_code != S_user
1089 && sym_code != S_host
1090 && sym_code != S_group
1092 parse_error("Expecting 'user', 'host' or ' group' as entity specification, found %s on line %d",
1103 static int parse_conditional_block_item TAC_ARGS((ENTITY *entity));
1106 parse_conditional_block_item(entity)
1113 /* case S_closebra: not needed, handled by our caller parse_conditional_block() */
1116 parse_error("Unrecognised keyword %s for entity on line %d",
1123 enlist_entity(S_group, sym_buf, entity->type, entity->name);
1128 int parsed_entity_type;
1130 if (entity->type != S_group) {
1131 parse_error("'enlist' keyword allowed only in 'group' section on line %d",
1137 parsed_entity_type = parse_entity_spec();
1138 if (!parsed_entity_type)
1140 enlist_entity(entity->type, entity->name, parsed_entity_type, sym_buf);
1150 * Already parsed some services/commands. Thanks to Gabor Kiss
1151 * who found this bug.
1154 for (p=entity->svcs; p->next; p=p->next)
1156 p->next = parse_svcs();
1158 entity->svcs = parse_svcs();
1163 if (parse_conditional_block(entity))
1171 static int parse_conditional_block TAC_ARGS((ENTITY *entity));
1174 parse_conditional_block(entity)
1177 int retval = -1 /* GCC paranoia */;
1179 if (push_parsed_when_decl())
1184 if (sym_code == S_closebra) {
1186 retval = 0; /* success */
1190 if (parse_conditional_block_item(entity)) {
1191 retval = 1; /* failure */
1196 if (pop_when_decl())
1202 /* passed 'name' WILL be directly stored to returned ENTITY, don't touch it! */
1204 static ENTITY *new_entity TAC_ARGS((int type, char *name, int line));
1207 new_entity(type, name, line)
1212 ENTITY *entity = (ENTITY *) tac_malloc(sizeof(ENTITY));
1213 ENTITY *hash_conflict;
1215 bzero(entity, sizeof(ENTITY));
1216 tac_list_init(&entity->to_parent_membership_list);
1217 tac_list_init(&entity->to_child_membership_list );
1218 entity->to_child_membership_num = 0;
1219 scan_init_entity(entity);
1221 entity->type = type;
1222 entity->name = name;
1223 entity->line = line;
1225 hash_conflict = hash_add_entry(entity_type_to_hashtable(type), (void *) entity);
1226 if (hash_conflict) {
1227 parse_error("multiply defined %s %s on lines %d and %d",
1228 entity_type_to_string(type),
1229 entity->name, hash_conflict->line, sym_line);
1237 static int parse_entity TAC_ARGS((int entity_type));
1240 parse_entity(entity_type)
1245 char **fieldp = NULL /* GCC paranoia */;
1246 char buf[MAX_INPUT_LINE_LEN];
1251 entity = new_entity(entity_type, tac_strdup(sym_buf) /* name */, sym_line /* line */);
1253 return (1); /* 'hash_add_entry()' conflict, 'tac_strdup(sym_buf)' leaked! */
1258 /* Is the default deny for svcs or cmds to be overridden? */
1259 entity->svc_dflt = parse_opt_svc_default();
1262 if (entity_type != S_user)
1265 ASSIGN(entity->key);
1275 ASSIGN(entity->time);
1281 parse(S_authorization);
1282 if (entity->before_author)
1283 free(entity->before_author);
1284 entity->before_author = tac_strdup(sym_buf);
1290 parse(S_authorization);
1291 if (entity->after_author)
1292 free(entity->after_author);
1293 entity->after_author = tac_strdup(sym_buf);
1298 if (entity->login) {
1299 parse_error("Duplicate value for %s %s and %s on line %d",
1300 codestring(sym_code), entity->login,
1309 entity->login = tac_strdup(sym_buf);
1313 /* set to dummy string, so that we detect a duplicate
1314 * password definition attempt
1316 entity->login = tac_strdup(nopasswd_str);
1317 entity->nopasswd = 1;
1325 #endif /* USE_PAM */
1329 sprintf(buf, "%s ", sym_buf);
1331 strcat(buf, sym_buf);
1332 entity->login = tac_strdup(buf);
1338 "expecting 'file', 'cleartext', 'pam'.'nopassword', 'skey', or 'des' keyword after 'login =' on line %d",
1342 "expecting 'file', 'cleartext', 'nopassword', 'skey', or 'des' keyword after 'login =' on line %d",
1344 #endif /* USE_PAM */
1351 parse_error("Duplicate value for %s %s and %s on line %d",
1352 codestring(sym_code), entity->pap,
1365 sprintf(buf, "%s ", sym_buf);
1367 strcat(buf, sym_buf);
1368 entity->pap = tac_strdup(buf);
1371 sprintf(buf, "%s ", sym_buf);
1372 entity->pap = tac_strdup(buf);
1378 "expecting 'cleartext', 'pam', or 'des' keyword after 'pap =' on line %d",
1382 "expecting 'cleartext', or 'des' keyword after 'pap =' on line %d",
1390 ASSIGN(entity->full_name);
1395 ASSIGN(entity->expires);
1400 ASSIGN(entity->msg);
1411 save_sym = sym_code;
1414 sprintf(buf, "%s ", sym_buf);
1416 strcat(buf, sym_buf);
1420 fieldp = &entity->arap;
1423 fieldp = &entity->chap;
1427 fieldp = &entity->mschap;
1431 fieldp = &entity->pap;
1434 fieldp = &entity->opap;
1437 fieldp = &entity->global;
1440 report(LOG_ERR, "INTERNAL: fieldp not recognized (on line %d)",
1446 parse_error("Duplicate value for %s %s and %s on line %d",
1447 codestring(save_sym), *fieldp, sym_buf, sym_line);
1450 *fieldp = tac_strdup(buf);
1462 if (sscanf(sym_buf, "%d", &entity->maxsess) != 1) {
1463 parse_error("expecting integer, found '%s' on line %d",
1468 #endif /* MAXSESS */
1471 if (STREQ(sym_buf, "password")) {
1473 "\npassword = <string> is obsolete. Use login = des <string>\n");
1476 if (parse_conditional_block_item(entity))
1477 return (0); /* error message already printed */
1482 static NODE *parse_svcs TAC_ARGS((void));
1497 result = (NODE *) tac_malloc(sizeof(NODE));
1499 bzero(result, sizeof(NODE));
1500 result->line = sym_line;
1502 /* cmd declaration */
1503 if (sym_code == S_cmd) {
1506 result->value = tac_strdup(sym_buf);
1511 result->value1 = parse_cmd_matches();
1512 result->type = N_svc_cmd;
1513 result->when = copy_current_when_decl();
1514 expr_sink_register(result->when);
1518 result->next = parse_svcs();
1522 /* svc declaration */
1527 parse_error("expecting service type but found %s on line %d",
1532 result->type = N_svc;
1533 /* should perhaps check that this is an allowable service name */
1534 result->value1 = tac_strdup(sym_buf);
1537 result->type = N_svc_exec;
1540 result->type = N_svc_arap;
1543 result->type = N_svc_slip;
1546 result->type = N_svc_ppp;
1550 /* Should perhaps check that this is a known PPP protocol name */
1551 result->value1 = tac_strdup(sym_buf);
1557 result->dflt = parse_opt_attr_default();
1558 result->value = parse_attrs();
1559 result->when = copy_current_when_decl();
1560 expr_sink_register(result->when);
1564 result->next = parse_svcs();
1568 /* <cmd_match> := <permission> <string> */
1570 static NODE *parse_cmd_matches TAC_ARGS((void));
1575 NODE *retval = NULL, **succp = &retval;
1584 if (push_parsed_when_decl())
1585 tac_exit(1); /* no error return possibility */
1587 result = parse_cmd_matches();
1589 if (pop_when_decl())
1590 tac_exit(1); /* no error return possibility */
1596 result = (NODE *) tac_malloc(sizeof(NODE));
1598 bzero(result, sizeof(NODE));
1599 result->line = sym_line;
1601 result->type = (parse_permission() == S_permit) ? N_permit : N_deny;
1602 result->value = tac_strdup(sym_buf);
1604 #ifdef WITH_INCLUDED_REGEX
1606 result->value1 = (void *) tac_regcomp(result->value);
1608 #else /* WITH_INCLUDED_REGEX */
1610 result->value1 = tac_malloc(sizeof(regex_t));
1611 if (regcomp(result->value1, result->value /* regex */, REG_NOSUB /* cflags */)) {
1612 free(result->value1);
1613 result->value1 = NULL;
1616 #endif /* WITH_INCLUDED_REGEX */
1618 if (!result->value1) {
1619 report(LOG_ERR, "in regular expression %s on line %d",
1625 result->when = copy_current_when_decl();
1626 expr_sink_register(result->when);
1628 result->next = NULL;
1631 while (result->next)
1632 result = result->next; /* skip parsed chain from parse_cmd_matches() */
1633 succp = &result->next;
1638 static NODE *parse_attrs TAC_ARGS((void));
1643 NODE *retval = NULL, **succp = &retval;
1645 char buf[MAX_INPUT_LINE_LEN];
1656 if (push_parsed_when_decl())
1657 tac_exit(1); /* no error return possibility */
1659 result = parse_attrs();
1661 if (pop_when_decl())
1662 tac_exit(1); /* no error return possibility */
1670 result = (NODE *) tac_malloc(sizeof(NODE));
1672 bzero(result, sizeof(NODE));
1673 result->line = sym_line;
1675 result->type = optional ? N_optarg : N_arg;
1677 strcpy(buf, sym_buf);
1679 strcat(buf, sym_buf);
1681 strcat(buf, sym_buf);
1684 result->value = tac_strdup(buf);
1686 result->when = copy_current_when_decl();
1687 expr_sink_register(result->when);
1689 result->next = NULL;
1692 while (result->next)
1693 result = result->next; /* skip parsed chain from parse_attrs() */
1694 succp = &result->next;
1700 static void sym_get TAC_ARGS((void));
1707 if (debug & DEBUG_PARSE_FLAG) {
1708 report(LOG_DEBUG, "line=%d sym=%s code=%d buf='%s'",
1709 sym_line, codestring(sym_code), sym_code, sym_buf);
1713 static char *sym_buf_add TAC_ARGS((int c));
1717 int c; /* promoted "char" type */
1719 if (sym_pos >= MAX_INPUT_LINE_LEN) {
1720 sym_buf[MAX_INPUT_LINE_LEN-1] = '\0';
1721 if (debug & DEBUG_PARSE_FLAG) {
1722 report(LOG_DEBUG, "line too long: line=%d sym=%s code=%d buf='%s'",
1723 sym_line, codestring(sym_code), sym_code, sym_buf);
1728 sym_buf[sym_pos++] = c;
1732 static void getsym TAC_ARGS((void));
1752 while (sym_ch == ' ' || sym_ch == '\t')
1757 strcpy(sym_buf, "=");
1758 sym_code = S_separator;
1763 strcpy(sym_buf, "{");
1764 sym_code = S_openbra;
1769 strcpy(sym_buf, "}");
1770 sym_code = S_closebra;
1775 strcpy(sym_buf, "(");
1776 sym_code = S_openparen;
1781 strcpy(sym_buf, ")");
1782 sym_code = S_closeparen;
1787 while ((sym_ch != '\n') && (sym_ch != EOF))
1796 if (sym_ch == '"') {
1800 /* backslash-double-quote is supported inside strings */
1802 if (sym_ch == '\\') {
1806 /* preserve the slash for \n */
1807 if (!sym_buf_add('\\')) {
1808 sym_code = S_unknown;
1815 if (!sym_buf_add(sym_ch)) {
1816 sym_code = S_unknown;
1823 sym_code = S_unknown;
1828 if (!sym_buf_add(sym_ch)) {
1829 sym_code = S_unknown;
1837 if (!sym_buf_add('\0')) {
1838 sym_code = S_unknown;
1842 sym_code = S_string;
1847 while (sym_ch != '\t' && sym_ch != ' ' && sym_ch != '='
1848 && sym_ch != '\n') {
1850 if (!sym_buf_add(sym_ch)) {
1851 sym_code = S_unknown;
1858 if (!sym_buf_add('\0')) {
1859 sym_code = S_unknown;
1863 sym_code = keycode(sym_buf);
1864 if (sym_code == S_unknown)
1865 sym_code = S_string;
1870 static void rch TAC_ARGS((void));
1881 if (parse_only && sym_ch != EOF)
1882 fprintf(stderr, "%c", sym_ch);
1886 static VALUE get_value TAC_ARGS((ENTITY *entity, int field));
1888 /* Find the value of a field. Does not recurse. */
1890 get_value(entity, field)
1896 v.pval = NULL; /* do both just for sure... */
1900 parse_error("get_value: illegal entity");
1906 v.pval = entity->name;
1910 v.pval = entity->login;
1914 v.pval = entity->global;
1918 v.pval = entity->expires;
1922 v.pval = entity->arap;
1926 v.pval = entity->chap;
1931 v.pval = entity->mschap;
1936 v.pval = entity->pap;
1940 v.pval = entity->opap;
1944 v.pval = entity->msg;
1948 v.pval = entity->svcs;
1952 v.pval = entity->before_author;
1956 v.pval = entity->after_author;
1960 v.intval = entity->svc_dflt;
1965 v.intval = entity->maxsess;
1970 v.intval = entity->nopasswd;
1974 v.pval = entity->time;
1978 if (entity->type == S_user) {
1979 report(LOG_ERR, "get_value: S_key field not supported in %s %s",
1980 entity_type_to_string(entity->type), entity->name);
1984 v.pval = entity->key;
1988 report(LOG_ERR, "get_value: unknown field %d", field);
1995 /* Internal graph scanning routines */
1997 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));
1999 static enum value_scan_func_result
2000 value_scan(type, name, recurse, func, func_data)
2004 value_scan_func_t func;
2009 if (debug & DEBUG_CONFIG_FLAG)
2010 report(LOG_DEBUG, "value_scan: find %s %s, recurse=%d",
2011 entity_type_to_string(type), name, recurse);
2013 entity = entity_lookup(type, name);
2015 if (debug & DEBUG_CONFIG_FLAG)
2016 report(LOG_DEBUG, "value_scan: no %s named %s",
2017 entity_type_to_string(type), name);
2018 return (VSFR_CONTINUE);
2021 return (value_scan_entity(entity, recurse, func, func_data));
2024 /* For each user, check she doesn't circularly reference a
2025 group. Return 1 if it does */
2027 static int circularity_check_failed;
2029 static void circularity_check_fail TAC_ARGS((struct membership *membership));
2032 circularity_check_fail(membership)
2033 struct membership *membership;
2037 circularity_check_failed = 1;
2039 report(LOG_ERR, "recursively defined groups:");
2040 while (membership) {
2041 entity = MEMBERSHIP_TO_CHILD_ENTITY(membership);
2042 report(LOG_ERR, "%s %s",
2043 entity_type_to_string(entity->type), entity->name);
2044 membership = value_scan_backward(entity);
2048 static enum value_scan_func_result circularity_check_func TAC_ARGS((ENTITY *entity, void *func_data));
2050 static enum value_scan_func_result
2051 circularity_check_func(entity, func_data /* unused */)
2055 /* only useful to speedup case of failure */
2056 if (circularity_check_failed)
2057 return (VSFR_FOUND);
2059 return (VSFR_CONTINUE);
2062 static int circularity_check TAC_ARGS((void));
2068 ENTITY **users_base = (ENTITY **) hash_get_entries(usertable);
2072 for (users = users_base; *users; users++) {
2075 if (debug & DEBUG_PARSE_FLAG)
2076 report(LOG_DEBUG, "circularity_check: user=%s", entity->name);
2078 circularity_check_failed = 0;
2079 value_scan_forward_seen_hook = circularity_check_fail;
2080 value_scan_entity(entity, TAC_PLUS_RECURSE,
2081 (value_scan_func_t) circularity_check_func, NULL /* func_data-unused */);
2082 value_scan_forward_seen_hook = NULL;
2083 if (circularity_check_failed)
2087 return (circularity_check_failed);
2091 /* Return a value for a group or user (isuser says if
2092 this name is a group or a user name).
2094 If no value exists, and recurse is true, also check groups we are a
2095 member of, recursively.
2097 Returns void * because it can return a string or a node pointer
2098 (should really return a union pointer).
2101 static VALUE cfg_get_value_VALUE; /* private */
2103 static enum value_scan_func_result cfg_get_value_func TAC_ARGS((ENTITY *entity, int *attrp));
2105 static enum value_scan_func_result
2106 cfg_get_value_func(entity,attrp /* func_data */)
2110 /* found the entry. Lookup value from attr=value */
2111 cfg_get_value_VALUE = get_value(entity, *attrp);
2112 if (cfg_get_value_VALUE.pval)
2113 return (VSFR_FOUND);
2115 return (VSFR_CONTINUE);
2118 static VALUE cfg_get_value TAC_ARGS((int type, const char *name, int attr, int recurse));
2121 cfg_get_value(type, name, attr, recurse)
2126 if (debug & DEBUG_CONFIG_FLAG)
2127 report(LOG_DEBUG, "cfg_get_value: type=%s name=%s attr=%s recurse=%d",
2128 entity_type_to_string(type), name, codestring(attr), recurse);
2130 cfg_get_value_VALUE.pval = NULL;
2131 value_scan(type, name, recurse,
2132 (value_scan_func_t) cfg_get_value_func, &attr /* func_data */);
2133 return (cfg_get_value_VALUE);
2137 /* Wrappers for cfg_get_value:
2140 int cfg_get_intvalue TAC_ARGS((int type, const char *name, int attr, int recurse));
2143 cfg_get_intvalue(type, name, attr, recurse)
2148 int val = cfg_get_value(type, name, attr, recurse).intval;
2150 if (debug & DEBUG_CONFIG_FLAG)
2151 report(LOG_DEBUG, "cfg_get_intvalue: returns %d", val);
2155 const char *cfg_get_pvalue TAC_ARGS((int type, const char *name, int attr, int recurse));
2158 cfg_get_pvalue(type, name, attr, recurse)
2163 char *p = cfg_get_value(type, name, attr, recurse).pval;
2165 if (debug & DEBUG_CONFIG_FLAG)
2166 report(LOG_DEBUG, "cfg_get_pvalue: returns %s",
2171 /* Read the config file and do some basic sanity checking on
2172 * it. Return 1 if we find any errors.
2174 int cfg_read_config TAC_ARGS((const char *cfile));
2177 cfg_read_config(cfile)
2182 if ((cf = fopen(cfile, "r")) == NULL) {
2183 report(LOG_ERR, "read_config: fopen() error for file %s %s, exiting",
2184 cfile, sys_errlist[errno]);
2187 if (parse_decls() || sym_error) {
2193 || enlist_entity_connect()
2194 || expr_sink_commit()
2195 /* circularity is allowed in the new fully-recursive algorithm */
2196 || (!algorithm_recursive && circularity_check())
2201 if (!when_expr_root || when_expr_root->type!=S_and || when_expr_root->u.and_or.child_first) {
2202 report(LOG_ERR, "Some 'when' expression found still pushed on stack");
2211 /* return 1 if user exists, 0 otherwise
2213 int cfg_user_exists TAC_ARGS((const char *username));
2216 cfg_user_exists(username)
2217 const char *username;
2219 return (NULL != hash_lookup(usertable, username));
2222 /* return expiry string of user. If none, try groups she is a member
2223 * on, and so on, recursively if recurse is non-zero
2225 const char *cfg_get_expires TAC_ARGS((const char *username, int recurse));
2228 cfg_get_expires(username, recurse)
2229 const char *username;
2232 return (cfg_get_pvalue(S_user, username, S_expires, recurse));
2235 /* return time string of user. If none, try groups she is a member
2236 * on, and so on, recursively if recurse is non-zero
2238 const char *cfg_get_timestamp TAC_ARGS((const char *username, int recurse));
2241 cfg_get_timestamp(username, recurse)
2242 const char *username;
2245 return (cfg_get_pvalue(S_user, username, S_time, recurse));
2248 /* return password string of user. If none, try groups she is a member
2249 * on, and so on, recursively if recurse is non-zero
2251 const char *cfg_get_login_secret TAC_ARGS((const char *user, int recurse));
2254 cfg_get_login_secret(user, recurse)
2258 return (cfg_get_pvalue(S_user, user, S_login, recurse));
2261 /* return value of the nopasswd field. If none, try groups she is a member
2262 * on, and so on, recursively if recurse is non-zero
2264 int cfg_get_user_nopasswd TAC_ARGS((const char *user, int recurse));
2267 cfg_get_user_nopasswd(user, recurse)
2271 return (cfg_get_intvalue(S_user, user, S_nopasswd, recurse));
2274 /* return user's secret. If none, try groups she is a member
2275 * on, and so on, recursively if recurse is non-zero
2277 const char *cfg_get_arap_secret TAC_ARGS((const char *user, int recurse));
2280 cfg_get_arap_secret(user, recurse)
2284 return (cfg_get_pvalue(S_user, user, S_arap, recurse));
2287 const char *cfg_get_chap_secret TAC_ARGS((const char *user, int recurse));
2290 cfg_get_chap_secret(user, recurse)
2294 return (cfg_get_pvalue(S_user, user, S_chap, recurse));
2299 const char *cfg_get_mschap_secret TAC_ARGS((const char *user, int recurse));
2302 cfg_get_mschap_secret(user, recurse)
2306 return (cfg_get_pvalue(S_user, user, S_mschap, recurse));
2311 const char *cfg_get_pap_secret TAC_ARGS((const char *user, int recurse));
2314 cfg_get_pap_secret(user, recurse)
2318 return (cfg_get_pvalue(S_user, user, S_pap, recurse));
2321 const char *cfg_get_opap_secret TAC_ARGS((const char *user, int recurse));
2324 cfg_get_opap_secret(user, recurse)
2328 return (cfg_get_pvalue(S_user, user, S_opap, recurse));
2331 /* return the global password for the user (or the group, etc.) */
2333 const char *cfg_get_global_secret TAC_ARGS((const char *user, int recurse));
2336 cfg_get_global_secret(user, recurse)
2340 return (cfg_get_pvalue(S_user, user, S_global, recurse));
2345 /* Return a pointer to a node representing a PAM Service name */
2347 const char *cfg_get_pam_service TAC_ARGS((const char *user, int recurse));
2350 cfg_get_pam_service(user, recurse)
2354 const char *cfg_passwd;
2357 cfg_passwd = cfg_get_pap_secret(user, recurse);
2360 cfg_passwd = cfg_get_global_secret(user, recurse);
2362 if (!cfg_passwd && !cfg_user_exists(user)) {
2363 cfg_passwd = cfg_get_authen_default();
2364 switch (cfg_get_authen_default_method()) {
2367 if (debug & DEBUG_AUTHOR_FLAG)
2368 report(LOG_DEBUG, "Get Default PAM Service :%s",cfg_passwd);
2373 if (debug & DEBUG_AUTHOR_FLAG)
2374 report(LOG_DEBUG, "I havent find any PAM Service!!");
2375 return(NULL);/* Haven't any PAM Service!! */
2379 p = tac_find_substring("pam ", cfg_passwd);
2381 if(p) { /* We find PAM services */
2382 if (debug & DEBUG_AUTHOR_FLAG)
2383 report(LOG_DEBUG, "I get PAM sevice:%s",p);
2387 if (debug & DEBUG_AUTHOR_FLAG)
2388 report(LOG_DEBUG, "No any PAM Sevice");
2393 #endif /* For PAM */
2396 /* Return a pointer to a node representing a given service
2397 authorization, taking care of recursion issues correctly. Protocol
2398 is only read if the svctype is N_svc_ppp. svcname is only read if type
2402 struct cfg_get_svc_node_param {
2404 const char *protocol, *svcname;
2409 static enum value_scan_func_result cfg_get_svc_node_func TAC_ARGS((ENTITY *entity, struct cfg_get_svc_node_param *param));
2411 static enum value_scan_func_result
2412 cfg_get_svc_node_func(entity, param /* func_data */)
2414 struct cfg_get_svc_node_param *param;
2417 enum eval_result svc_default;
2419 for (svc = (NODE *) get_value(entity, S_svc).pval; svc; svc = svc->next) {
2420 if (svc->type != param->svctype)
2422 if (param->svctype == N_svc_ppp && param->protocol && !STREQ(svc->value1, param->protocol))
2424 if (param->svctype == N_svc && param->svcname && !STREQ(svc->value1, param->svcname ))
2426 if (expr_eval(svc->when) != ER_TRUE) /* expensive */
2429 if (debug & DEBUG_CONFIG_FLAG)
2431 "cfg_get_svc_node: found %s proto=%s svcname=%s",
2432 cfg_nodestring(param->svctype),
2433 param->protocol ? param->protocol : "",
2434 param->svcname ? param->svcname : "");
2438 return (VSFR_FOUND);
2441 /* look at 'default service' settings */
2442 svc_default = entity_svc_default(entity);
2443 switch (svc_default) {
2447 if (debug & DEBUG_AUTHOR_FLAG)
2449 "cfg_get_svc_node: svc=%s protocol=%s svcname=%s forced %s by default service",
2450 cfg_nodestring(param->svctype),
2451 param->protocol ? param->protocol : "",
2452 param->svcname ? param->svcname : "",
2453 (svc_default == ER_TRUE ? "permit" : "deny"));
2455 param->retval = (svc_default == ER_TRUE);
2456 return (VSFR_FOUND);
2458 default: /* shouldn't happen */
2460 return (VSFR_CONTINUE);
2465 int cfg_get_svc_node TAC_ARGS((const char *username, int svctype, const char *protocol, const char *svcname, int recurse, NODE **nodep));
2468 cfg_get_svc_node(username, svctype, protocol, svcname, recurse, nodep)
2469 const char *username;
2471 const char *protocol;
2472 const char *svcname;
2476 struct cfg_get_svc_node_param param;
2477 enum value_scan_func_result vsfr;
2479 param.svctype = svctype;
2480 param.protocol = protocol;
2481 param.svcname = svcname;
2485 if (debug & DEBUG_CONFIG_FLAG)
2487 "cfg_get_svc_node: username=%s %s proto=%s svcname=%s rec=%d",
2489 cfg_nodestring(svctype),
2490 protocol ? protocol : "",
2491 svcname ? svcname : "",
2494 vsfr = value_scan(S_user, username, recurse,
2495 (value_scan_func_t) cfg_get_svc_node_func, ¶m /* func_data */);
2497 *nodep = param.node;
2499 if (vsfr == VSFR_FOUND)
2500 return (param.retval);
2502 /* The service does not exist. Do the default */
2503 return (cfg_no_user_permitted() ? 1 : 0);
2506 /* Return a pointer to the node representing a set of command tac_regexp
2507 matches for a user and command, handling recursion issues correctly */
2509 struct cfg_authorize_cmd_param {
2512 enum eval_result result;
2515 static enum value_scan_func_result cfg_authorize_cmd_func TAC_ARGS((ENTITY *entity, struct cfg_authorize_cmd_param *param));
2517 static enum value_scan_func_result
2518 cfg_authorize_cmd_func(entity, param /* func_data */)
2520 struct cfg_authorize_cmd_param *param;
2524 for (svc = (NODE *) get_value(entity, S_svc).pval; svc; svc = svc->next) {
2527 if (svc->type != N_svc_cmd)
2529 if (!STREQ(svc->value, param->cmd))
2531 if (expr_eval(svc->when) != ER_TRUE) /* expensive */
2534 if (debug & DEBUG_CONFIG_FLAG)
2535 report(LOG_DEBUG, "cfg_authorize_cmd: found cmd %s %s node",
2536 param->cmd, cfg_nodestring(svc->type));
2538 /* we have 'cmd <openbra>' point, now traverse through its 'permit'/'deny' pairs: */
2540 for (node = svc->value1; node; node = node->next) {
2543 if (expr_eval(node->when) != ER_TRUE) /* expensive */
2546 #ifdef WITH_INCLUDED_REGEX
2548 match = tac_regexec((tac_regexp *) node->value1, param->args);
2550 #else /* WITH_INCLUDED_REGEX */
2552 match = !regexec((const regex_t *) node->value1, param->args /* string */,
2553 0 /* nmatch */, NULL /* pmatch */, 0 /* eflags */);
2555 #endif /* WITH_INCLUDED_REGEX */
2557 if (debug & DEBUG_AUTHOR_FLAG) {
2558 report(LOG_INFO, "line %d compare %s %s '%s' & '%s' %smatch",
2559 node->line, param->cmd,
2560 node->type == N_permit ? "permit" : "deny",
2561 (const char *) node->value, param->args, (match ? "" : "no "));
2567 switch (node->type) {
2569 if (debug & DEBUG_AUTHOR_FLAG) {
2570 report(LOG_DEBUG, "%s %s permitted by line %d",
2571 param->cmd, param->args, node->line);
2573 param->result = ER_TRUE;
2574 return (VSFR_FOUND);
2577 if (debug & DEBUG_AUTHOR_FLAG) {
2578 report(LOG_DEBUG, "%s %s denied by line %d",
2579 param->cmd, param->args, node->line);
2581 param->result = ER_FALSE;
2582 return (VSFR_FOUND);
2585 report(LOG_ERR, "INTERNAL: illegal configuration node: %s: %s %s",
2586 session.peer, param->cmd, param->args);
2587 param->result = ER_UNKNOWN; /* error */
2588 return (VSFR_FOUND);
2591 if (!algorithm_recursive) { /* compatibility mode: */
2592 if (debug & DEBUG_AUTHOR_FLAG)
2593 report(LOG_DEBUG, "cmd %s exists, but no args match, denied (as no 'authorization = recursive' found)",
2595 param->result = ER_FALSE; /* emulate last "deny .*" */
2596 return (VSFR_FOUND);
2600 /* look at 'default service' settings */
2601 param->result = entity_svc_default(entity);
2602 switch (param->result) {
2605 if (debug & DEBUG_AUTHOR_FLAG)
2606 report(LOG_DEBUG, "cmd %s does not exist, permitted by default", param->cmd);
2607 return (VSFR_FOUND);
2611 if (debug & DEBUG_AUTHOR_FLAG)
2612 report(LOG_DEBUG, "cmd %s does not exist, denied by default", param->cmd);
2613 return (VSFR_FOUND);
2615 default: /* shouldn't happen */
2617 return (VSFR_CONTINUE);
2622 enum eval_result cfg_authorize_cmd TAC_ARGS((const char *username, const char *cmd, const char *args));
2625 cfg_authorize_cmd(username, cmd, args)
2626 const char *username;
2630 struct cfg_authorize_cmd_param param;
2634 param.result = ER_UNKNOWN; /* error */
2636 if (debug & DEBUG_CONFIG_FLAG)
2637 report(LOG_DEBUG, "cfg_authorize_cmd: name=%s cmdname=%s args=%s",
2638 username, cmd, args);
2640 value_scan(S_user, username, TAC_PLUS_RECURSE,
2641 (value_scan_func_t) cfg_authorize_cmd_func, ¶m /* func_data */);
2643 if (param.result != ER_UNKNOWN)
2644 return (param.result);
2646 /* The command does not exist. Do the default */
2647 return (cfg_no_user_permitted() ? ER_TRUE : ER_FALSE);
2650 /* Return an array of character strings representing configured AV
2651 * pairs, given a username and a service node.
2653 * In the AV strings returned, manipulate the separator character to
2654 * indicate which args are optional and which are mandatory.
2656 * Lastly, indicate what default permission was configured by setting
2659 char **cfg_get_svc_attrs TAC_ARGS((NODE *svcnode, int *denyp));
2662 cfg_get_svc_attrs(svcnode, denyp)
2675 *denyp = (svcnode->dflt == S_deny);
2678 for (node = svcnode->value; node; node = node->next)
2681 args = (char **) tac_malloc(sizeof(char *) * (i + 1));
2684 for (node = svcnode->value; node; node = node->next) {
2688 if (expr_eval(node->when) != ER_TRUE) /* expensive */
2689 continue; /* ignore this node */
2691 arg = tac_strdup(node->value);
2692 p = index(arg, '=');
2693 if (p && node->type == N_optarg)
2702 static enum eval_result entity_svc_default TAC_ARGS((ENTITY *entity));
2704 static enum eval_result
2705 entity_svc_default(entity)
2708 switch (entity->svc_dflt) {
2714 case 0: /* not specified */
2715 return (ER_UNKNOWN);
2717 report(LOG_ERR, "INTERNAL: invalid entity svc_dflt (%d)", entity->svc_dflt);
2718 return (ER_UNKNOWN);
2722 int cfg_no_user_permitted TAC_ARGS((void));
2725 cfg_no_user_permitted()
2727 if (no_user_dflt == S_permit)
2733 const char *cfg_get_authen_default TAC_ARGS((void));
2736 cfg_get_authen_default()
2738 return (authen_default);
2741 int cfg_get_authen_default_method TAC_ARGS((void));
2743 /* For describe authentication method(pam,file,db..etc) */
2745 cfg_get_authen_default_method()
2747 return (authen_default_method);
2751 /* Host entity management:
2754 const char *cfg_get_host_key TAC_ARGS((const char *host));
2756 /* For getting host key */
2758 cfg_get_host_key(host)
2761 return (cfg_get_pvalue(S_host, host, S_key, algorithm_recursive /* recurse */));
2764 static ENTITY *force_belong_entity TAC_ARGS((int type, const char *name));
2767 force_belong_entity(type, name)
2771 ENTITY *entity = entity_lookup(type, name);
2774 eval_force_belong_entity(entity);
2779 /* assumed existing initialized "session.peer*" */
2781 static ENTITY *request_peer_addr;
2782 static ENTITY *request_peer;
2783 static ENTITY *request_DEFAULT_group;
2785 static void enlist_request_peer TAC_ARGS((const char *hostname, ENTITY **entityp));
2788 enlist_request_peer(hostname, entityp)
2789 const char *hostname;
2796 *entityp = force_belong_entity(S_host, hostname);
2797 if (*entityp && request_DEFAULT_group)
2798 virtual_enlist_entity_direct(request_DEFAULT_group /* parent */, *entityp /* child */);
2801 /* Try to build the following scenery:
2803 * host <session.peer_addr> [=ER_TRUE]
2805 * +-- group <DEFAULT_GROUPNAME>
2807 * host <session.peer > [=ER_TRUE]
2809 * +-- group <DEFAULT_GROUPNAME>
2812 void cfg_request_scan_begin TAC_ARGS((void));
2815 cfg_request_scan_begin()
2817 request_scan_begin();
2819 request_DEFAULT_group = entity_lookup(S_group, DEFAULT_GROUPNAME);
2821 if (session.peer_addr != session.peer)
2822 enlist_request_peer(session.peer_addr, &request_peer_addr);
2823 enlist_request_peer(session.peer, &request_peer);
2826 /* Try to build the following scenery:
2828 * ( user <identity->username> | user <DEFAULT_USERNAME> ) [=ER_TRUE]
2830 * +-- host <session.peer_addr> [=ER_TRUE]
2832 * | +- group <DEFAULT_GROUPNAME>
2834 * +-- host <session.peer > [=ER_TRUE]
2836 * | +-- group <DEFAULT_GROUPNAME>
2838 * +-- group <DEFAULT_GROUPNAME>
2841 void cfg_request_identity TAC_ARGS((const struct identity *identity));
2844 cfg_request_identity(identity)
2845 const struct identity *identity;
2847 ENTITY *user_entity,*request_DEFAULT_group;
2849 if (debug & DEBUG_CONFIG_FLAG)
2850 report(LOG_DEBUG, "cfg_request_identity: username=%s, NAS_name=%s, NAS_port=%s, NAC_address=%s, priv_lvl=%d",
2851 identity->username, identity->NAS_name, identity->NAS_port, identity->NAC_address, identity->priv_lvl);
2853 user_entity = force_belong_entity(S_user, identity->username);
2854 request_DEFAULT_group = entity_lookup(S_group, DEFAULT_GROUPNAME);
2857 user_entity = force_belong_entity(S_user, DEFAULT_USERNAME);
2859 request_scan_user_known = 1;
2864 if (request_peer_addr)
2865 virtual_enlist_entity_direct(request_peer_addr /* parent */, user_entity /* child */);
2867 virtual_enlist_entity_direct(request_peer /* parent */, user_entity /* child */);
2868 if (request_DEFAULT_group)
2869 virtual_enlist_entity_direct(request_DEFAULT_group /* parent */, user_entity /* child */);