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 <decl> := <top_level_decl> | <user_decl>
30 <top_level_decl> := <authen_default> |
31 accounting file = <string>
32 default authorization = permit |
35 <authen_default> := default authentication = file <filename>
40 <permission> := permit | deny
42 <filename> := <string>
44 <password> := <string>
46 <user_decl> := user = <string> {
47 [ default service = [ permit | deny ] ]
52 <password_spec> := file <filename> |
54 cleartext <password> |
65 <user_attr> := name = <string> |
66 login = <password_spec> |
69 arap = cleartext <string> |
70 chap = cleartext <string> |
72 ms-chap = cleartext <string> |
74 pap = cleartext <string> |
77 pap = pam <pam_service> |
79 opap = cleartext <string> |
80 global = cleartext <string> |
82 before authorization = <string> |
83 after authorization = <string>
85 <svc> := <svc_auth> | <cmd_auth>
87 <cmd_auth> := cmd = <string> {
91 <cmd-match> := <permission> <string>
93 <svc_auth> := service = ( exec | arap | slip | ppp protocol = <string> {
94 [ default attribute = permit ]
98 <attr_value_pair> := [ optional ] <string> = <string>
102 static char sym_buf[MAX_INPUT_LINE_LEN]; /* parse buffer */
103 static int sym_pos=0; /* current place in sym_buf */
104 static int sym_ch; /* current parse character */
105 static int sym_code; /* parser output */
106 static int sym_line = 1; /* current line number for parsing */
107 static FILE *cf = NULL; /* config file pointer */
108 static int sym_error = 0; /* a parsing error has occurred */
109 static int no_user_dflt = 0; /* default if user doesn't exist */
110 static char *authen_default = NULL; /* top level authentication default */
111 static int authen_default_method = 0; /*For method check */
112 static char *nopasswd_str = "nopassword";
114 /* A host definition structure. Currently unused, but when we start
115 configuring host-specific information e.g. per-host keys, this is
116 where it should be kept.
118 The first 2 fields (name and hash) are used by the hash table
119 routines to hash this structure into a table. Do not (re)move them */
122 char *name; /* host name */
123 void *hash; /* hash table next pointer */
124 int line; /* line number defined on */
125 char *key; /* host spesific key */
126 char *type; /* host type */
129 /* A user or group definition
131 The first 2 fields (name and hash) are used by the hash table
132 routines to hash this structure into a table. Move them at your
136 char *name; /* username */
137 void *hash; /* hash table next pointer */
138 int line; /* line number defined on */
139 long flags; /* flags field */
141 #define FLAG_ISUSER 1 /* this structure represents a user */
142 #define FLAG_ISGROUP 2 /* this structure represents a group */
143 #define FLAG_SEEN 4 /* for circular definition detection */
145 char *full_name; /* users full name */
146 char *login; /* Login password */
147 int nopasswd; /* user requires no password */
148 char *global; /* password to use if none set */
149 char *member; /* group we are a member of */
150 char *expires; /* expiration date */
151 char *arap; /* our arap secret */
152 char *pap; /* our pap secret */
153 char *opap; /* our outbound pap secret */
154 char *chap; /* our chap secret */
156 char *mschap; /* our mschap secret */
158 char *msg; /* a message for this user */
159 char *before_author; /* command to run before authorization */
160 char *after_author; /* command to run after authorization */
161 int svc_dflt; /* default authorization behaviour for svc or
163 NODE *svcs; /* pointer to svc nodes */
165 int maxsess; /* Max sessions/user */
167 char *time; /* Timestamp */
170 typedef struct host HOST;
171 typedef struct user USER;
173 /* Only the first 2 fields (name and hash) are used by the hash table
174 routines to hashh structures into a table.
182 typedef union hash HASH;
184 void *grouptable[HASH_TAB_SIZE];/* Table of group declarations */
185 void *usertable[HASH_TAB_SIZE]; /* Table of user declarations */
186 void *hosttable[HASH_TAB_SIZE]; /* Table of host declarations */
194 #include <stdarg.h> /* ANSI C, variable length args */
196 parse_error(char *fmt,...)
198 #include <varargs.h> /* has 'vararg' definitions */
201 parse_error(fmt, va_alist)
204 va_dcl /* no terminating semi-colon */
207 char msg[256]; /* temporary string */
215 vsprintf(msg, fmt, ap);
218 report(LOG_ERR, "%s", msg);
219 fprintf(stderr, "Error: %s\n", msg);
229 return ("unknown node type");
237 return ("N_svc_exec");
239 return ("N_svc_slip");
241 return ("N_svc_ppp");
243 return ("N_svc_arap");
245 return ("N_svc_cmd");
260 switch (node->type) {
263 if (debug & DEBUG_CLEAN_FLAG)
264 report(LOG_DEBUG, "free_cmd_match %s %s",
265 cfg_nodestring(node->type),
269 report(LOG_ERR, "Illegal node type %s for free_attrs",
270 cfg_nodestring(node->type));
282 free_cmd_matches(node)
288 if (debug & DEBUG_CLEAN_FLAG)
289 report(LOG_DEBUG, "free_cmd_match %s %s",
290 cfg_nodestring(node->type),
293 free(node->value); /* text */
294 free(node->value1); /* regexp compiled text */
309 switch (node->type) {
311 if (debug & DEBUG_CLEAN_FLAG)
312 report(LOG_DEBUG, "free %s %s",
313 cfg_nodestring(node->type), node->value);
314 free(node->value); /* cmd name */
315 free_cmd_matches(node->value1);
328 if (debug & DEBUG_CLEAN_FLAG)
329 report(LOG_DEBUG, "free %s", cfg_nodestring(node->type));
330 free_attrs(node->value);
337 report(LOG_ERR, "Illegal node type %d for free_svcs", node->type);
344 free_userstruct(user)
347 if (debug & DEBUG_CLEAN_FLAG)
348 report(LOG_DEBUG, "free %s %s",
349 (user->flags & FLAG_ISUSER) ? "user" : "group",
355 free(user->full_name);
380 if (user->before_author)
381 free(user->before_author);
382 if (user->after_author)
383 free(user->after_author);
384 free_svcs(user->svcs);
388 free_hoststruct(host)
391 if (debug & DEBUG_CLEAN_FLAG)
392 report(LOG_DEBUG, "free %s",
409 /* Free all allocated structures preparatory to re-reading the config file */
415 HOST *host_entry,*hn;
417 if (authen_default) {
418 free(authen_default);
419 authen_default = NULL;
422 if (authen_default_method) {
423 authen_default_method = 0;
431 if (session.acctfile) {
432 free(session.acctfile);
433 session.acctfile = NULL;
436 if (session.db_acct) {
437 free(session.db_acct);
438 session.db_acct = NULL;
441 /* clean the hosttable */
442 for (i = 0; i < HASH_TAB_SIZE; i++) {
443 host_entry = (HOST *) hosttable[i];
445 hn = host_entry->hash;
446 free_hoststruct(host_entry);
454 for (i = 0; i < HASH_TAB_SIZE; i++) {
455 entry = (USER *) grouptable[i];
458 free_userstruct(entry);
462 grouptable[i] = NULL;
466 for (i = 0; i < HASH_TAB_SIZE; i++) {
467 entry = (USER *) usertable[i];
470 free_userstruct(entry);
481 int symbol = sym_code;
483 if (sym_code != S_permit && sym_code != S_deny) {
484 parse_error("expecting permit or deny but found '%s' on line %d",
498 if (sym_code != symbol) {
499 parse_error("expecting '%s' but found '%s' on line %d",
500 (symbol == S_string ? "string" : codestring(symbol)),
509 parse_opt_svc_default()
511 if (sym_code != S_default) {
518 if (sym_code == S_permit) {
527 parse_opt_attr_default()
529 if (sym_code != S_default)
539 static int parse_user();
540 static int parse_host();
546 Parse lines in the config file, creating data structures
547 Return 1 on error, otherwise 0 */
552 no_user_dflt = 0; /* default if user doesn't exist */
557 bzero(grouptable, sizeof(grouptable));
558 bzero(usertable, sizeof(usertable));
559 bzero(hosttable, sizeof(hosttable));
563 /* Top level of parser */
574 if (session.acctfile)
575 free(session.acctfile);
576 session.acctfile = tac_strdup(sym_buf);
581 case S_db_accounting:
585 free(session.db_acct);
586 session.db_acct = tac_strdup(sym_buf);
596 "Expecting default authorization/authentication on lines %d",
600 case S_authentication:
601 if (authen_default) {
603 "Multiply defined authentication default on line %d",
607 parse(S_authentication);
622 authen_default_method = sym_code;
626 parse_error("expecting default_method keyword after 'default authentication = ' on line %d",sym_line);
631 authen_default = tac_strdup(sym_buf);
635 case S_authorization:
636 parse(S_authorization);
639 no_user_dflt = S_permit;
641 "default authorization = permit is now deprecated. Please use user = DEFAULT instead");
646 /* Process a key declaration. */
650 parse_error("multiply defined key on lines %d and %d",
651 session.keyline, sym_line);
654 session.key = tac_strdup(sym_buf);
655 session.keyline = sym_line;
668 /* case S_host: parse_host(); continue; */
671 parse_error("Unrecognised token %s on line %d", sym_buf, sym_line);
677 static NODE *parse_svcs();
679 /* Assign a value to a field. Issue an error message and return 1 if
680 it's already been assigned. This is a macro because I was sick of
681 repeating the same code fragment over and over */
683 #define ASSIGN(field) \
684 sym_get(); parse(S_separator); if (field) { \
685 parse_error("Duplicate value for %s %s and %s on line %d", \
686 codestring(sym_code), field, sym_buf, sym_line); \
689 field = tac_strdup(sym_buf);
695 HOST *host = (HOST *) tac_malloc(sizeof(HOST));
697 char buf[MAX_INPUT_LINE_LEN];
699 bzero(host, sizeof(HOST));
703 host->name = tac_strdup(sym_buf);
704 host->line = sym_line;
706 h = hash_add_entry(hosttable, (void *) host);
709 parse_error("multiply defined %s on lines %d and %d",
710 host->name, h->line, sym_line);
735 parse_error("Unrecognised keyword %s for host %s on line %d",
736 sym_buf, host->name,sym_line);
741 } /* finish parse_host */
749 USER *user = (USER *) tac_malloc(sizeof(USER));
752 char buf[MAX_INPUT_LINE_LEN];
754 bzero(user, sizeof(USER));
756 isuser = (sym_code == S_user);
760 user->name = tac_strdup(sym_buf);
761 user->line = sym_line;
764 user->flags |= FLAG_ISUSER;
765 n = hash_add_entry(usertable, (void *) user);
767 user->flags |= FLAG_ISGROUP;
768 n = hash_add_entry(grouptable, (void *) user);
772 parse_error("multiply defined %s %s on lines %d and %d",
773 isuser ? "user" : "group",
774 user->name, n->line, sym_line);
780 /* Is the default deny for svcs or cmds to be overridden? */
781 user->svc_dflt = parse_opt_svc_default();
795 parse(S_authorization);
796 if (user->before_author)
797 free(user->before_author);
798 user->before_author = tac_strdup(sym_buf);
804 parse(S_authorization);
805 if (user->after_author)
806 free(user->after_author);
807 user->after_author = tac_strdup(sym_buf);
816 * Already parsed some services/commands. Thanks to Gabor Kiss
817 * who found this bug.
820 for (p=user->svcs; p->next; p=p->next)
822 p->next = parse_svcs();
824 user->svcs = parse_svcs();
830 parse_error("Duplicate value for %s %s and %s on line %d",
831 codestring(sym_code), user->login,
840 user->login = tac_strdup(sym_buf);
844 /* set to dummy string, so that we detect a duplicate
845 * password definition attempt
847 user->login = tac_strdup(nopasswd_str);
860 sprintf(buf, "%s ", sym_buf);
862 strcat(buf, sym_buf);
863 user->login = tac_strdup(buf);
869 "expecting 'file', 'cleartext', 'pam'.'nopassword', 'skey', or 'des' keyword after 'login =' on line %d",
873 "expecting 'file', 'cleartext', 'nopassword', 'skey', or 'des' keyword after 'login =' on line %d",
882 parse_error("Duplicate value for %s %s and %s on line %d",
883 codestring(sym_code), user->pap,
896 sprintf(buf, "%s ", sym_buf);
898 strcat(buf, sym_buf);
899 user->pap = tac_strdup(buf);
902 sprintf(buf, "%s ", sym_buf);
903 user->pap = tac_strdup(buf);
909 "expecting 'cleartext', 'pam', or 'des' keyword after 'pap =' on line %d",
913 "expecting 'cleartext', or 'des' keyword after 'pap =' on line %d",
921 ASSIGN(user->full_name);
926 ASSIGN(user->member);
932 ASSIGN(user->expires);
951 sprintf(buf, "%s ", sym_buf);
953 strcat(buf, sym_buf);
955 if (save_sym == S_arap)
956 fieldp = &user->arap;
957 if (save_sym == S_chap)
958 fieldp = &user->chap;
960 if (save_sym == S_mschap)
961 fieldp = &user->mschap;
963 if (save_sym == S_pap)
965 if (save_sym == S_opap)
966 fieldp = &user->opap;
967 if (save_sym == S_global)
968 fieldp = &user->global;
971 parse_error("Duplicate value for %s %s and %s on line %d",
972 codestring(save_sym), *fieldp, sym_buf, sym_line);
975 *fieldp = tac_strdup(buf);
987 if (sscanf(sym_buf, "%d", &user->maxsess) != 1) {
988 parse_error("expecting integer, found '%s' on line %d",
996 if (STREQ(sym_buf, "password")) {
998 "\npassword = <string> is obsolete. Use login = des <string>\n");
1000 parse_error("Unrecognised keyword %s for user on line %d",
1008 static NODE *parse_attrs();
1009 static NODE *parse_cmd_matches();
1024 result = (NODE *) tac_malloc(sizeof(NODE));
1026 bzero(result, sizeof(NODE));
1027 result->line = sym_line;
1029 /* cmd declaration */
1030 if (sym_code == S_cmd) {
1033 result->value = tac_strdup(sym_buf);
1038 result->value1 = parse_cmd_matches();
1039 result->type = N_svc_cmd;
1042 result->next = parse_svcs();
1046 /* svc declaration */
1051 parse_error("expecting service type but found %s on line %d",
1056 result->type = N_svc;
1057 /* should perhaps check that this is an allowable service name */
1058 result->value1 = tac_strdup(sym_buf);
1061 result->type = N_svc_exec;
1064 result->type = N_svc_arap;
1067 result->type = N_svc_slip;
1070 result->type = N_svc_ppp;
1074 /* Should perhaps check that this is a known PPP protocol name */
1075 result->value1 = tac_strdup(sym_buf);
1080 result->dflt = parse_opt_attr_default();
1081 result->value = parse_attrs();
1083 result->next = parse_svcs();
1087 /* <cmd-match> := <permission> <string> */
1094 if (sym_code != S_permit && sym_code != S_deny) {
1097 result = (NODE *) tac_malloc(sizeof(NODE));
1099 bzero(result, sizeof(NODE));
1100 result->line = sym_line;
1102 result->type = (parse_permission() == S_permit) ? N_permit : N_deny;
1103 result->value = tac_strdup(sym_buf);
1105 result->value1 = (void *) regcomp(result->value);
1106 if (!result->value1) {
1107 report(LOG_ERR, "in regular expression %s on line %d",
1113 result->next = parse_cmd_matches();
1122 char buf[MAX_INPUT_LINE_LEN];
1125 if (sym_code == S_closebra) {
1128 result = (NODE *) tac_malloc(sizeof(NODE));
1130 bzero(result, sizeof(NODE));
1131 result->line = sym_line;
1133 if (sym_code == S_optional) {
1137 result->type = optional ? N_optarg : N_arg;
1139 strcpy(buf, sym_buf);
1141 strcat(buf, sym_buf);
1143 strcat(buf, sym_buf);
1146 result->value = tac_strdup(buf);
1147 result->next = parse_attrs();
1160 if (debug & DEBUG_PARSE_FLAG) {
1161 report(LOG_DEBUG, "line=%d sym=%s code=%d buf='%s'",
1162 sym_line, codestring(sym_code), sym_code, sym_buf);
1170 if (sym_pos >= MAX_INPUT_LINE_LEN) {
1171 sym_buf[MAX_INPUT_LINE_LEN-1] = '\0';
1172 if (debug & DEBUG_PARSE_FLAG) {
1173 report(LOG_DEBUG, "line too long: line=%d sym=%s code=%d buf='%s'",
1174 sym_line, codestring(sym_code), sym_code, sym_buf);
1179 sym_buf[sym_pos++] = c;
1201 while (sym_ch == ' ' || sym_ch == '\t')
1206 strcpy(sym_buf, "=");
1207 sym_code = S_separator;
1212 strcpy(sym_buf, "{");
1213 sym_code = S_openbra;
1218 strcpy(sym_buf, "}");
1219 sym_code = S_closebra;
1224 while ((sym_ch != '\n') && (sym_ch != EOF))
1233 if (sym_ch == '"') {
1237 /* backslash-double-quote is supported inside strings */
1239 if (sym_ch == '\\') {
1243 /* preserve the slash for \n */
1244 if (!sym_buf_add('\\')) {
1245 sym_code = S_unknown;
1252 if (!sym_buf_add(sym_ch)) {
1253 sym_code = S_unknown;
1260 sym_code = S_unknown;
1265 if (!sym_buf_add(sym_ch)) {
1266 sym_code = S_unknown;
1274 if (!sym_buf_add('\0')) {
1275 sym_code = S_unknown;
1279 sym_code = S_string;
1284 while (sym_ch != '\t' && sym_ch != ' ' && sym_ch != '='
1285 && sym_ch != '\n') {
1287 if (!sym_buf_add(sym_ch)) {
1288 sym_code = S_unknown;
1295 if (!sym_buf_add('\0')) {
1296 sym_code = S_unknown;
1300 sym_code = keycode(sym_buf);
1301 if (sym_code == S_unknown)
1302 sym_code = S_string;
1316 if (parse_only && sym_ch != EOF)
1317 fprintf(stderr, "%c", sym_ch);
1321 /* For a user or group, find the value of a field. Does not recurse. */
1323 get_value(user, field)
1332 parse_error("get_value: illegal user");
1338 v.pval = user->name;
1342 v.pval = user->login;
1346 v.pval = user->global;
1350 v.pval = user->member;
1354 v.pval = user->expires;
1358 v.pval = user->arap;
1362 v.pval = user->chap;
1367 v.pval = user->mschap;
1376 v.pval = user->opap;
1384 v.pval = user->svcs;
1388 v.pval = user->before_author;
1392 v.pval = user->after_author;
1396 v.intval = user->svc_dflt;
1401 v.intval = user->maxsess;
1406 v.intval = user->nopasswd;
1410 v.pval = user->time;
1414 report(LOG_ERR, "get_value: unknown field %d", field);
1420 /* For host , find value of field. Doesn't recursive */
1422 get_hvalue(host, field)
1429 parse_error("get_hvalue: illegal host");
1434 v.pval = host->name;
1442 report(LOG_ERR, "get_value: unknown field %d", field);
1449 /* For each user, check she doesn't circularly reference a
1450 group. Return 1 if it does */
1454 USER *user, *entry, *group;
1455 USER **users = (USER **) hash_get_entries(usertable);
1456 USER **groups = (USER **) hash_get_entries(grouptable);
1460 for (p = users; *p; p++) {
1463 if (debug & DEBUG_PARSE_FLAG)
1464 report(LOG_DEBUG, "circularity_check: user=%s", user->name);
1466 /* Initialise all groups "seen" flags to zero */
1467 for (q = groups; *q; q++) {
1469 group->flags &= ~FLAG_SEEN;
1475 /* check groups we are a member of */
1476 char *groupname = entry->member;
1478 if (debug & DEBUG_PARSE_FLAG)
1479 report(LOG_DEBUG, "\tmember of group %s",
1480 groupname ? groupname : "<none>");
1483 /* if not a member of any groups, go on to next user */
1487 group = (USER *) hash_lookup(grouptable, groupname);
1489 report(LOG_ERR, "%s=%s, group %s does not exist",
1490 (entry->flags & FLAG_ISUSER) ? "user" : "group",
1491 entry->name, groupname);
1496 if (group->flags & FLAG_SEEN) {
1497 report(LOG_ERR, "recursively defined groups");
1499 /* print all seen "groups" */
1500 for (q = groups; *q; q++) {
1502 if (group->flags & FLAG_SEEN)
1503 report(LOG_ERR, "%s", group->name);
1509 group->flags |= FLAG_SEEN; /* mark group as seen */
1519 /* Return a value for a group or user (isuser says if
1520 this name is a group or a user name).
1522 If no value exists, and recurse is true, also check groups we are a
1523 member of, recursively.
1525 Returns void * because it can return a string or a node pointer
1526 (should really return a union pointer).
1529 cfg_get_value(name, isuser, attr, recurse)
1531 int isuser, attr, recurse;
1538 if (debug & DEBUG_CONFIG_FLAG)
1539 report(LOG_DEBUG, "cfg_get_value: name=%s isuser=%d attr=%s rec=%d",
1540 name, isuser, codestring(attr), recurse);
1542 /* find the user/group entry */
1544 user = (USER *) hash_lookup(isuser ? usertable : grouptable, name);
1547 if (debug & DEBUG_CONFIG_FLAG)
1548 report(LOG_DEBUG, "cfg_get_value: no user/group named %s", name);
1552 /* found the entry. Lookup value from attr=value */
1553 value = get_value(user, attr);
1555 if (value.pval || !recurse) {
1558 /* no value. Check containing group */
1560 group = (USER *) hash_lookup(grouptable, user->member);
1565 if (debug & DEBUG_CONFIG_FLAG)
1566 report(LOG_DEBUG, "cfg_get_value: recurse group = %s",
1569 value = get_value(group, attr);
1574 /* still nothing. Check containing group and so on */
1577 group = (USER *) hash_lookup(grouptable, group->member);
1582 /* no value for this user or her containing groups */
1588 /* Wrappers for cfg_get_value */
1590 cfg_get_intvalue(name, isuser, attr, recurse)
1592 int isuser, attr, recurse;
1594 int val = cfg_get_value(name, isuser, attr, recurse).intval;
1596 if (debug & DEBUG_CONFIG_FLAG)
1597 report(LOG_DEBUG, "cfg_get_intvalue: returns %d", val);
1602 cfg_get_pvalue(name, isuser, attr, recurse)
1604 int isuser, attr, recurse;
1606 char *p = cfg_get_value(name, isuser, attr, recurse).pval;
1608 if (debug & DEBUG_CONFIG_FLAG)
1609 report(LOG_DEBUG, "cfg_get_pvalue: returns %s",
1614 /* For getting host values */
1616 cfg_get_hvalue(name, attr)
1624 if (debug & DEBUG_CONFIG_FLAG)
1625 report(LOG_DEBUG, "cfg_get_hvalue: name=%s attr=%s ",
1626 name, codestring(attr));
1628 /* find the host entry in hash table */
1630 host = (HOST *) hash_lookup( hosttable, name);
1633 if (debug & DEBUG_CONFIG_FLAG)
1634 report(LOG_DEBUG, "cfg_get_hvalue: no host named %s", name);
1638 /* found the entry. Lookup value from attr=value */
1639 value = get_hvalue(host, attr);
1644 /* No any value for this host */
1649 /* Wrappers for cfg_get_hvalue */
1651 cfg_get_phvalue(name, attr)
1655 char *p = cfg_get_hvalue(name, attr).pval;
1657 if (debug & DEBUG_CONFIG_FLAG)
1658 report(LOG_DEBUG, "cfg_get_phvalue: returns %s",
1664 Read the config file and do some basic sanity checking on
1665 it. Return 1 if we find any errors. */
1667 cfg_read_config(cfile)
1672 if ((cf = fopen(cfile, "r")) == NULL) {
1673 report(LOG_ERR, "read_config: fopen() error for file %s %s, exiting",
1674 cfile, sys_errlist[errno]);
1677 if (parse_decls() || sym_error) {
1682 if (circularity_check()) {
1691 /* return 1 if user exists, 0 otherwise */
1693 cfg_user_exists(username)
1696 USER *user = (USER *) hash_lookup(usertable, username);
1698 return (user != NULL);
1701 /* return expiry string of user. If none, try groups she is a member
1702 on, and so on, recursively if recurse is non-zero */
1704 cfg_get_expires(username, recurse)
1708 return (cfg_get_pvalue(username, TAC_IS_USER, S_expires, recurse));
1711 /* return time string of user. If none, try groups she is a member
1712 on, and so on, recursively if recurse is non-zero */
1714 cfg_get_timestamp(username, recurse)
1717 return (cfg_get_pvalue(username, TAC_IS_USER, S_time, recurse));
1721 /* return password string of user. If none, try groups she is a member
1722 on, and so on, recursively if recurse is non-zero */
1724 cfg_get_login_secret(user, recurse)
1728 return (cfg_get_pvalue(user, TAC_IS_USER, S_login, recurse));
1731 /* return value of the nopasswd field. If none, try groups she is a member
1732 on, and so on, recursively if recurse is non-zero */
1734 cfg_get_user_nopasswd(user, recurse)
1737 return (cfg_get_intvalue(user, TAC_IS_USER, S_nopasswd, recurse));
1740 /* return user's secret. If none, try groups she is a member
1741 on, and so on, recursively if recurse is non-zero */
1743 cfg_get_arap_secret(user, recurse)
1747 return (cfg_get_pvalue(user, TAC_IS_USER, S_arap, recurse));
1751 cfg_get_chap_secret(user, recurse)
1755 return (cfg_get_pvalue(user, TAC_IS_USER, S_chap, recurse));
1760 cfg_get_mschap_secret(user, recurse)
1764 return (cfg_get_pvalue(user, TAC_IS_USER, S_mschap, recurse));
1769 cfg_get_pap_secret(user, recurse)
1772 return (cfg_get_pvalue(user, TAC_IS_USER, S_pap, recurse));
1776 cfg_get_opap_secret(user, recurse)
1779 return (cfg_get_pvalue(user, TAC_IS_USER, S_opap, recurse));
1782 /* return the global password for the user (or the group, etc.) */
1785 cfg_get_global_secret(user, recurse)
1789 return (cfg_get_pvalue(user, TAC_IS_USER, S_global, recurse));
1793 /* Return a pointer to a node representing a PAM Service name */
1795 cfg_get_pam_service(user,recurse)
1802 cfg_passwd = cfg_get_pap_secret(user, recurse);
1805 cfg_passwd = cfg_get_global_secret(user, recurse);
1808 if (!cfg_passwd && !cfg_user_exists(user)) {
1809 cfg_passwd = cfg_get_authen_default();
1810 switch (cfg_get_authen_default_method()) {
1812 if (debug & DEBUG_AUTHOR_FLAG)
1813 report(LOG_DEBUG, "Get Default PAM Service :%s",cfg_passwd);
1817 if (debug & DEBUG_AUTHOR_FLAG)
1818 report(LOG_DEBUG, "I havent find any PAM Service!!");
1819 return(NULL);/* Haven't any PAM Service!! */
1823 p=tac_find_substring("pam ", cfg_passwd);
1825 if(p) { /* We find PAM services */
1826 if (debug & DEBUG_AUTHOR_FLAG)
1827 report(LOG_DEBUG, "I get PAM sevice:%s",p);
1831 if (debug & DEBUG_AUTHOR_FLAG)
1832 report(LOG_DEBUG, "No any PAM Sevice");
1837 #endif /* For PAM */
1841 /* Return a pointer to a node representing a given service
1842 authorization, taking care of recursion issues correctly. Protocol
1843 is only read if the type is N_svc_ppp. svcname is only read if type
1848 cfg_get_svc_node(username, type, protocol, svcname, recurse)
1851 char *protocol, *svcname;
1857 if (debug & DEBUG_CONFIG_FLAG)
1859 "cfg_get_svc_node: username=%s %s proto=%s svcname=%s rec=%d",
1861 cfg_nodestring(type),
1862 protocol ? protocol : "",
1863 svcname ? svcname : "",
1866 /* find the user/group entry */
1867 user = (USER *) hash_lookup(usertable, username);
1870 if (debug & DEBUG_CONFIG_FLAG)
1871 report(LOG_DEBUG, "cfg_get_svc_node: no user named %s", username);
1875 /* found the user entry. Find svc node */
1876 for(svc = (NODE *) get_value(user, S_svc).pval; svc; svc = svc->next) {
1878 if (svc->type != type)
1881 if (type == N_svc_ppp && !STREQ(svc->value1, protocol)) {
1885 if (type == N_svc && !STREQ(svc->value1, svcname)) {
1889 if (debug & DEBUG_CONFIG_FLAG)
1891 "cfg_get_svc_node: found %s proto=%s svcname=%s",
1892 cfg_nodestring(type),
1893 protocol ? protocol : "",
1894 svcname ? svcname : "");
1900 if (debug & DEBUG_CONFIG_FLAG)
1901 report(LOG_DEBUG, "cfg_get_svc_node: returns NULL");
1905 /* no matching node. Check containing group */
1907 group = (USER *) hash_lookup(grouptable, user->member);
1912 if (debug & DEBUG_CONFIG_FLAG)
1913 report(LOG_DEBUG, "cfg_get_svc_node: recurse group = %s",
1916 for(svc = (NODE *) get_value(group, S_svc).pval; svc; svc = svc->next) {
1918 if (svc->type != type)
1921 if (type == N_svc_ppp && !STREQ(svc->value1, protocol)) {
1925 if (type == N_svc && !STREQ(svc->value1, svcname)) {
1929 if (debug & DEBUG_CONFIG_FLAG)
1931 "cfg_get_svc_node: found %s proto=%s svcname=%s",
1932 cfg_nodestring(type),
1933 protocol ? protocol : "",
1934 svcname ? svcname : "");
1939 /* still nothing. Check containing group and so on */
1942 group = (USER *) hash_lookup(grouptable, group->member);
1947 if (debug & DEBUG_CONFIG_FLAG)
1948 report(LOG_DEBUG, "cfg_get_svc_node: returns NULL");
1950 /* no matching svc node for this user or her containing groups */
1954 /* Return a pointer to the node representing a set of command regexp
1955 matches for a user and command, handling recursion issues correctly */
1957 cfg_get_cmd_node(name, cmdname, recurse)
1958 char *name, *cmdname;
1965 if (debug & DEBUG_CONFIG_FLAG)
1966 report(LOG_DEBUG, "cfg_get_cmd_node: name=%s cmdname=%s rec=%d",
1967 name, cmdname, recurse);
1969 /* find the user/group entry */
1970 user = (USER *) hash_lookup(usertable, name);
1973 if (debug & DEBUG_CONFIG_FLAG)
1974 report(LOG_DEBUG, "cfg_get_cmd_node: no user named %s", name);
1977 /* found the user entry. Find svc node */
1978 svc = (NODE *) get_value(user, S_svc).pval;
1981 if (svc->type == N_svc_cmd && STREQ(svc->value, cmdname)) {
1982 if (debug & DEBUG_CONFIG_FLAG)
1983 report(LOG_DEBUG, "cfg_get_cmd_node: found cmd %s %s node",
1984 cmdname, cfg_nodestring(svc->type));
1991 if (debug & DEBUG_CONFIG_FLAG)
1992 report(LOG_DEBUG, "cfg_get_cmd_node: returns NULL");
1995 /* no matching node. Check containing group */
1997 group = (USER *) hash_lookup(grouptable, user->member);
2002 if (debug & DEBUG_CONFIG_FLAG)
2003 report(LOG_DEBUG, "cfg_get_cmd_node: recurse group = %s",
2006 svc = get_value(group, S_svc).pval;
2009 if (svc->type == N_svc_cmd && STREQ(svc->value, cmdname)) {
2010 if (debug & DEBUG_CONFIG_FLAG)
2011 report(LOG_DEBUG, "cfg_get_cmd_node: found cmd %s node %s",
2012 cmdname, cfg_nodestring(svc->type));
2018 /* still nothing. Check containing group and so on */
2021 group = (USER *) hash_lookup(grouptable, group->member);
2026 if (debug & DEBUG_CONFIG_FLAG)
2027 report(LOG_DEBUG, "cfg_get_cmd_node: returns NULL");
2029 /* no matching cmd node for this user or her containing groups */
2033 /* Return an array of character strings representing configured AV
2034 * pairs, given a username and a service node.
2036 * In the AV strings returned, manipulate the separator character to
2037 * indicate which args are optional and which are mandatory.
2039 * Lastly, indicate what default permission was configured by setting
2043 cfg_get_svc_attrs(svcnode, denyp)
2056 *denyp = (svcnode->dflt == S_deny);
2059 for (node = svcnode->value; node; node = node->next)
2062 args = (char **) tac_malloc(sizeof(char *) * (i + 1));
2065 for (node = svcnode->value; node; node = node->next) {
2066 char *arg = tac_strdup(node->value);
2067 char *p = index(arg, '=');
2069 if (p && node->type == N_optarg)
2079 cfg_user_svc_default_is_permit(user)
2083 int permit = cfg_get_intvalue(user, TAC_IS_USER, S_svc_dflt,
2087 default: /* default is deny */
2096 cfg_no_user_permitted()
2098 if (no_user_dflt == S_permit)
2105 cfg_get_authen_default()
2107 return (authen_default);
2110 /* For describe authentication method(pam,file,db..etc) */
2112 cfg_get_authen_default_method()
2114 return (authen_default_method);
2118 /* Return 1 if this user has any ppp services configured. Used for
2119 authorizing ppp/lcp requests */
2121 cfg_ppp_is_configured(username, recurse)
2128 if (debug & DEBUG_CONFIG_FLAG)
2129 report(LOG_DEBUG, "cfg_ppp_is_configured: username=%s rec=%d",
2132 /* find the user/group entry */
2133 user = (USER *) hash_lookup(usertable, username);
2136 if (debug & DEBUG_CONFIG_FLAG)
2137 report(LOG_DEBUG, "cfg_ppp_is_configured: no user named %s",
2142 /* found the user entry. Find svc node */
2143 for(svc = (NODE *) get_value(user, S_svc).pval; svc; svc = svc->next) {
2145 if (svc->type != N_svc_ppp)
2148 if (debug & DEBUG_CONFIG_FLAG)
2149 report(LOG_DEBUG, "cfg_ppp_is_configured: found svc ppp %s node",
2156 if (debug & DEBUG_CONFIG_FLAG)
2157 report(LOG_DEBUG, "cfg_ppp_is_configured: returns 0");
2161 /* no matching node. Check containing group */
2163 group = (USER *) hash_lookup(grouptable, user->member);
2168 if (debug & DEBUG_CONFIG_FLAG)
2169 report(LOG_DEBUG, "cfg_ppp_is_configured: recurse group = %s",
2172 for(svc = (NODE *) get_value(group, S_svc).pval; svc; svc = svc->next) {
2174 if (svc->type != N_svc_ppp)
2177 if (debug & DEBUG_CONFIG_FLAG)
2178 report(LOG_DEBUG, "cfg_ppp_is_configured: found svc ppp %s node",
2184 /* still nothing. Check containing group and so on */
2187 group = (USER *) hash_lookup(grouptable, group->member);
2192 if (debug & DEBUG_CONFIG_FLAG)
2193 report(LOG_DEBUG, "cfg_ppp_is_configured: returns 0");
2195 /* no PPP svc nodes for this user or her containing groups */
2199 /* For getting host key */
2201 cfg_get_host_key(host)
2204 return (cfg_get_phvalue(host, S_key));