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.
26 #include "do_author.h"
27 #include "tac_regexp.h"
44 static int pre_authorization TAC_ARGS((const char *username, struct author_data *data));
45 static int get_nas_svc TAC_ARGS((struct author_data *data, char **cmdname, char **protocol, char **svcname));
46 static int authorize_cmd TAC_ARGS((const char *user, const char *cmd, struct author_data *data));
47 static int authorize_exec TAC_ARGS((const char *user, struct author_data *data));
48 static int authorize_svc TAC_ARGS((const char *user, int svc, const char *protocol, const char *svcname, struct author_data *data));
49 static void post_authorization TAC_ARGS((const char *username, struct author_data *data));
52 int do_author TAC_ARGS((struct author_data *data));
54 /* Return 0 is data->status is valid */
57 struct author_data *data;
59 char *username = data->id->username;
62 char *cmd, *protocol, *svcname;
64 const char *pam_service= NULL;
68 data->status = AUTHOR_STATUS_FAIL; /* for safety */
70 data->output_args = NULL;
71 data->num_out_args = 0;
73 /* If this user doesn't exist in our configs, do the default */
75 if (!cfg_user_exists(username)) {
76 if (!cfg_user_exists(DEFAULT_USERNAME)) {
78 if (cfg_no_user_permitted()) {
79 if (debug & DEBUG_AUTHOR_FLAG)
81 "user '%s' or '%s' not found, permitted by default",
82 username, DEFAULT_USERNAME);
84 data->status = AUTHOR_STATUS_PASS_ADD;
85 data->output_args = NULL;
86 data->num_out_args = 0;
90 if (debug & DEBUG_AUTHOR_FLAG)
92 "user '%s' or '%s' not found, denied by default",
93 username, DEFAULT_USERNAME);
94 data->status = AUTHOR_STATUS_FAIL;
98 /* assumed (cfg_user_exists(DEFAULT_USERNAME)): */
100 if (debug & DEBUG_AUTHOR_FLAG) {
101 report(LOG_DEBUG, "Authorizing user '%s' instead of '%s'",
102 DEFAULT_USERNAME, username);
104 username = DEFAULT_USERNAME;
107 /* See if there's a program defined which will do authorization for us */
108 if (pre_authorization(username, data))
112 * Decide what kind of authorization request this is. Currently
113 * one of: exec, cmd, slip, arap, ppp or <string>
115 * If it's a command typed to the exec, return its text in cmd.
117 * If it's a ppp request, return the protocol name in protocol.
120 svc = get_nas_svc(data, &cmd, &protocol, &svcname);
123 /* if we can't identify the service in the request it's an error */
124 data->status = AUTHOR_STATUS_ERROR;
126 tac_strdup("No identifiable service/protocol in authorization request");
127 if (debug & DEBUG_AUTHOR_FLAG) {
128 report(LOG_DEBUG, "user %s %s", username, data->admin_msg);
133 if (debug & DEBUG_AUTHOR_FLAG)
134 report(LOG_DEBUG, "user '%s' found", username);
137 /* Never permit if they're going over their session limit */
144 if (maxsess_check_count(username, data)) {
154 /* Check PAM Authorization */
159 if ((pam_service = cfg_get_pam_service(data->id->username, TAC_PLUS_RECURSE) )) {
161 if (debug & DEBUG_AUTHOR_FLAG)
162 report(LOG_DEBUG, "PAM Authorization begin for user %s",data->id->username);
163 if (tac_pam_authorization(data->id->username, data, pam_service)) {
164 if (debug & DEBUG_AUTHOR_FLAG)
165 report(LOG_DEBUG, "PAM Authorization Fail");
177 report(LOG_ERR, "%s: Bad service type %d", session.peer, svc);
178 data->status = AUTHOR_STATUS_FAIL;
182 /* A command authorisation request */
183 status = authorize_cmd(username, cmd, data);
187 if (authorize_exec(username, data))
194 status = authorize_svc(username, svc, protocol, NULL, data);
198 status = authorize_svc(username, svc, protocol, svcname, data);
202 post_authorization(username, data);
206 /* If an before-authorization program has been specified, call it.
208 A return value of 1 means no further authorization is required
211 static int pre_authorization TAC_ARGS((const char *username, struct author_data *data));
214 pre_authorization(username, data)
215 const char *username;
216 struct author_data *data;
228 /* If a before-authorization program exists, call it to see how to
231 cmd = cfg_get_pvalue(S_user, username,
232 S_before, TAC_PLUS_RECURSE);
236 if (debug & DEBUG_AUTHOR_FLAG)
237 report(LOG_DEBUG, "Before authorization call: %s", cmd);
239 status = call_pre_process(cmd, data, &out_args, &out_cnt, error_str,
244 if (debug & DEBUG_AUTHOR_FLAG)
245 report(LOG_DEBUG, "cmd %s returns %d (unrecognised value)",
248 data->status = AUTHOR_STATUS_ERROR;
250 tac_strdup("Illegal return status from pre-authorization command");
251 data->msg = tac_strdup(error_str);
252 data->num_out_args = 0;
253 data->output_args = NULL;
254 /* throw away out_args */
255 for(i=0; i < out_cnt; i++) {
264 if (debug & DEBUG_AUTHOR_FLAG)
265 report(LOG_DEBUG, "cmd %s returns 0 (unconditional permit)", cmd);
267 data->status = AUTHOR_STATUS_PASS_ADD;
268 data->num_out_args = 0;
269 data->output_args = NULL;
271 /* throw away out_args */
272 for(i=0; i < out_cnt; i++) {
281 if (debug & DEBUG_AUTHOR_FLAG)
282 report(LOG_DEBUG, "cmd %s returns %d (unconditional deny)",
285 data->status = AUTHOR_STATUS_FAIL;
286 data->msg = tac_strdup(error_str);
287 data->num_out_args = 0;
288 data->output_args = NULL;
290 /* throw away out_args */
291 for(i=0; i < out_cnt; i++) {
299 case 2: /* Use replacement AV pairs from program as final result */
300 if (debug & DEBUG_AUTHOR_FLAG) {
301 report(LOG_DEBUG, "cmd %s returns %d (permitted, args replaced)",
303 for(i=0; i < out_cnt; i++)
304 report(LOG_DEBUG, "%s", out_args[i]);
307 /* and install the new set of AV pairs as output */
308 data->output_args = out_args;
309 data->num_out_args = out_cnt;
310 data->status = AUTHOR_STATUS_PASS_REPL;
311 return(1); /* no more processing required */
313 case 3: /* deny, but return attributes and server-msg to NAS */
314 if (debug & DEBUG_AUTHOR_FLAG) {
315 report(LOG_DEBUG, "cmd %s returns %d (deny, args replaced)",
317 for(i=0; i < out_cnt; i++)
318 report(LOG_DEBUG, "%s", out_args[i]);
321 /* and install the new set of AV pairs as output */
322 data->output_args = out_args;
323 data->num_out_args = out_cnt;
324 data->msg = tac_strdup(error_str);
325 data->status = AUTHOR_STATUS_FAIL;
326 return(1); /* no more processing required */
330 /* If an after-authorization program has been specified, call it. It
331 can rewrite the output arguments in the authorization data, or
332 change the authorization status by calling an external program.
335 static void post_authorization TAC_ARGS((const char *username, struct author_data *data));
338 post_authorization(username, data)
339 const char *username;
340 struct author_data *data;
345 const char *after = cfg_get_pvalue(S_user, username, S_after, TAC_PLUS_RECURSE);
349 if (debug & DEBUG_AUTHOR_FLAG)
350 report(LOG_DEBUG, "After authorization call: %s", after);
352 status = call_post_process(after, data, &out_args, &out_cnt);
355 /* throw away out_args */
356 for(i=0; i < out_cnt; i++) {
364 if (debug & DEBUG_AUTHOR_FLAG)
366 "cmd %s returns %d (Error)", after, status);
368 data->status = AUTHOR_STATUS_ERROR;
372 if (debug & DEBUG_AUTHOR_FLAG)
373 report(LOG_DEBUG, "cmd %s returns 0 (no change)", after);
377 if (debug & DEBUG_AUTHOR_FLAG)
378 report(LOG_DEBUG, "cmd %s returns %d (unconditional deny)",
381 data->status = AUTHOR_STATUS_FAIL;
385 /* Use replacement AV pairs from program */
386 if (debug & DEBUG_AUTHOR_FLAG)
387 report(LOG_DEBUG, "cmd %s returns 2 (replace & continue)",
390 /* Free any existing AV output pairs */
391 if (data->num_out_args) {
392 for(i=0; i < data->num_out_args; i++) {
393 free(data->output_args[i]);
395 free(data->output_args);
396 data->output_args = NULL;
399 if (debug & DEBUG_AUTHOR_FLAG) {
400 report(LOG_DEBUG, "status is now AUTHOR_STATUS_PASS_REPL");
403 data->status = AUTHOR_STATUS_PASS_REPL;
404 data->output_args = out_args;
405 data->num_out_args = out_cnt;
411 static char *value TAC_ARGS((char *s));
413 /* Return a pointer to the value part of an attr=value string */
418 while (*s && *s != '=' && *s != '*')
425 /* Reassemble the command arguments as typed by the user, out of the
426 array of args we received. Return "" if there are no arguments */
428 static char *assemble_args TAC_ARGS((struct author_data *data));
432 struct author_data *data;
440 for (i = 0; i < data->num_in_args; i++) {
441 nas_arg = data->input_args[i];
442 if (strncmp(nas_arg, "cmd-arg", strlen("cmd-arg"))==0)
443 len += strlen(value(nas_arg)) + 1;
447 return(tac_strdup(""));
450 buf = tac_malloc(len);
453 for (i = 0; i < data->num_in_args; i++) {
454 nas_arg = data->input_args[i];
455 if (strncmp(nas_arg, "cmd-arg", strlen("cmd-arg")))
464 if (i < (data->num_in_args - 1))
471 /* See if an exec is authorized. Either the user has explicitly
472 authorized the exec, or she has authorized some commands (which
473 implicitly authorizes an exec), or the default is permit.
475 If she has explicitly authorized an exec, we need to process its
476 attribute=value pairs. We indicate this by returning zero to the
479 Otherwise, we return 1, indicating no further processing is
480 required for this request. */
482 static int authorize_exec TAC_ARGS((const char *user, struct author_data *data));
485 authorize_exec(user, data)
487 struct author_data *data;
489 if (debug & DEBUG_AUTHOR_FLAG)
490 report(LOG_DEBUG, "exec authorization request for %s", user);
492 /* Is an exec explicitly configured? If so, return 0 so we know to
493 process its attributes */
495 if (cfg_get_svc_node(user, N_svc_exec, NULL, NULL, TAC_PLUS_RECURSE, NULL /* nodep */)) {
496 if (debug & DEBUG_AUTHOR_FLAG)
497 report(LOG_DEBUG, "exec is explicitly permitted");
501 /* No exec is configured. Are any commands configured? */
502 if (cfg_get_svc_node(user, N_svc_cmd, NULL, NULL, TAC_PLUS_RECURSE, NULL /* nodep */)) {
503 if (debug & DEBUG_AUTHOR_FLAG)
504 report(LOG_DEBUG, "exec permitted because commands are configured");
506 data->status = AUTHOR_STATUS_PASS_ADD;
507 data->output_args = NULL;
508 data->num_out_args = 0;
512 if (debug & DEBUG_AUTHOR_FLAG)
513 report(LOG_DEBUG, "exec denied by default");
515 data->status = AUTHOR_STATUS_FAIL;
516 data->num_out_args = 0;
520 /* Is an exec command authorized per our database(s)?
521 Return 0 if status is valid */
523 static int authorize_cmd TAC_ARGS((const char *user, const char *cmd, struct author_data *data));
526 authorize_cmd(user, cmd, data)
529 struct author_data *data;
534 data->status = AUTHOR_STATUS_ERROR;
535 data->admin_msg = tac_strdup("No command found");
536 report(LOG_ERR, "%s: %s %s", session.peer, cmd, data->admin_msg);
537 data->num_out_args = 0;
541 args = assemble_args(data);
542 switch (cfg_authorize_cmd(user, cmd, args)) {
545 data->status = AUTHOR_STATUS_PASS_ADD;
546 data->num_out_args = 0;
550 data->status = AUTHOR_STATUS_FAIL;
551 data->num_out_args = 0;
555 data->status = AUTHOR_STATUS_ERROR;
556 data->admin_msg = tac_strdup("Server error illegal configuration");
565 static int is_separator TAC_ARGS((int ch));
569 int ch; /* promoted "char" type */
571 return (ch == '=' || ch == '*');
574 static int arg_ok TAC_ARGS((char *arg));
576 /* check an attr=value pair for well-formedness */
583 /* It must contain an attribute */
587 for(p=arg; *p; p++) {
588 if (is_separator(*p)) {
589 if (p == arg) /* no attribute */
599 static int match_attrs TAC_ARGS((char *nas_arg, char *server_arg));
601 /* return 1 if attrs match, 0 otherwise */
603 match_attrs(nas_arg, server_arg)
604 char *nas_arg, *server_arg;
606 while (*nas_arg && *server_arg) {
607 if (is_separator(*nas_arg) && is_separator(*server_arg)) {
610 if (*nas_arg != *server_arg)
618 static int match_values TAC_ARGS((char *nas_arg, char *server_arg));
620 /* return 1 if values match, 0 otherwise */
622 match_values(nas_arg, server_arg)
623 char *nas_arg, *server_arg;
627 !is_separator(*nas_arg)) {
641 return(STREQ(nas_arg, server_arg));
644 static int mandatory TAC_ARGS((char *arg));
646 /* Return 1 if arg is mandatory, 0 otherwise */
653 while (*p && !is_separator(*p))
656 /* if we're not at the end, this must be the separator */
657 if (*p && !is_separator(*p)) {
658 report(LOG_ERR, "%s: Error on arg %s cannot find separator",
665 static int optional TAC_ARGS((char *arg));
671 return (!mandatory(arg));
674 /* PPP-LCP requests are a special case. If they are not explicitly
675 configured, but there are other ppp services explicitly configured,
676 we admit (return 1) any PPP-LCP request */
678 static int ppp_lcp_allowed TAC_ARGS((const char *user));
681 ppp_lcp_allowed(user)
684 /* It is an LCP request. Are there PPP services configured? */
685 if (cfg_get_svc_node(user, N_svc_ppp, NULL /* protocol */, NULL /* svcname */, TAC_PLUS_RECURSE, NULL /* nodep */)) {
686 if (debug & DEBUG_AUTHOR_FLAG) {
688 "ppp/lcp request permitted (ppp is configured for %s)",
694 /* It is an LCP request but no PPP services are configured */
695 if (debug & DEBUG_AUTHOR_FLAG) {
696 report(LOG_DEBUG, "ppp/lcp request denied (ppp not configured for %s)",
702 static int authorize_svc TAC_ARGS((const char *user, int svc, const char *protocol, const char *svcname, struct author_data *data));
704 /* Return 0 means data->status is valid */
706 authorize_svc(user, svc, protocol, svcname, data)
710 struct author_data *data;
711 const char *protocol; /* valid only if svc == ppp */
714 char **out_args, **outp;
715 char *nas_arg, *cfg_arg;
727 /* Does this service exist? */
728 service_permit = cfg_get_svc_node(user, svc, protocol, svcname, TAC_PLUS_RECURSE, &node);
730 /* Now we may have three cases:
731 * service_permit == 1 && node != NULL
732 * service_permit == 1 && node == NULL
733 * service_permit == 0 (BTW node == NULL)
736 if (service_permit && !node) {
737 /* Service not found and the default is permit, we'll allow it. */
739 if (debug & DEBUG_AUTHOR_FLAG)
741 "svc=%s protocol=%s svcname=%s not found, permitted by default",
743 protocol ? protocol : "",
744 svcname ? svcname : "");
746 data->status = AUTHOR_STATUS_PASS_ADD;
747 data->num_out_args = 0;
748 data->output_args = NULL;
752 if (!service_permit) {
753 /* Service not found, if this is an
754 PPP/LCP request and other ppp services are configured,
757 if (svc == N_svc_ppp && protocol && STREQ(protocol, "lcp")
758 && ppp_lcp_allowed(user)) {
759 data->status = AUTHOR_STATUS_PASS_ADD;
760 data->num_out_args = 0;
761 data->output_args = NULL;
765 if (debug & DEBUG_AUTHOR_FLAG)
766 report(LOG_DEBUG, "svc=%s protocol=%s not found, denied by default",
767 cfg_nodestring(svc), protocol ? protocol : "");
769 data->status = AUTHOR_STATUS_FAIL;
770 data->num_out_args = 0;
771 data->output_args = NULL;
775 /* Get server args configured in the config file. */
776 cfg_args = cfg_get_svc_attrs(node, &deny_by_default);
778 /* Check the nas args for well-formedness */
779 for (i = 0; i < data->num_in_args; i++) {
780 if (!arg_ok(data->input_args[i])) {
781 char buf[MAX_INPUT_LINE_LEN+50];
782 sprintf(buf, "Illegal arg %s from NAS", data->input_args[i]);
783 data->status = AUTHOR_STATUS_ERROR;
784 data->admin_msg = tac_strdup(buf);
785 report(LOG_ERR, "%s: Error %s", session.peer, buf);
787 /* free any server arguments */
788 for(cfg_argp = cfg_args; cfg_args && *cfg_argp; cfg_argp++)
795 /* How many configured AV pairs are there ? */
796 for (cfg_cnt = 0; cfg_args && cfg_args[cfg_cnt];)
799 /* Allocate space for in + out args */
800 max_args = cfg_cnt + data->num_in_args;
801 out_args = (char **) tac_malloc((max_args + 1) * sizeof(char *));
803 data->num_out_args = 0;
805 bzero(out_args, (max_args + 1) * sizeof(char *));
807 for (i = 0; i < data->num_in_args; i++) {
808 nas_arg = data->input_args[i];
810 /* always pass these pairs through unchanged */
811 if (match_attrs(nas_arg, "service=") ||
812 match_attrs(nas_arg, "protocol=") ||
813 match_attrs(nas_arg, "cmd=")) {
815 if (debug & DEBUG_AUTHOR_FLAG) {
816 report(LOG_DEBUG, "nas:%s (passed thru)", nas_arg);
818 *outp++ = tac_strdup(nas_arg);
819 data->num_out_args++;
823 /* NAS AV pair is mandatory */
824 if (mandatory(nas_arg)) {
826 /* a). look for an exact attribute,value match in the daemon's
827 mandatory list. If found, add the AV pair to the output */
829 for (j = 0; j < cfg_cnt; j++) {
830 cfg_arg = cfg_args[j];
831 if (optional(cfg_arg))
834 if (STREQ(nas_arg, cfg_arg)) {
835 if (debug & DEBUG_AUTHOR_FLAG) {
836 report(LOG_DEBUG, "nas:%s, svr:%s -> add %s (a)",
837 nas_arg, cfg_arg, nas_arg);
839 *outp++ = tac_strdup(nas_arg);
840 data->num_out_args++;
845 /* b). If an exact match doesn't exist, look in the
846 daemon's optional list for the first attribute
847 match. If found, add the NAS AV pair to the output */
849 for (j = 0; j < cfg_cnt; j++) {
850 cfg_arg = cfg_args[j];
851 if (mandatory(cfg_arg))
854 if (match_attrs(nas_arg, cfg_arg)) {
855 if (debug & DEBUG_AUTHOR_FLAG) {
856 report(LOG_DEBUG, "nas:%s, svr:%s -> add %s (b)",
857 nas_arg, cfg_arg, nas_arg);
859 *outp++ = tac_strdup(nas_arg);
860 data->num_out_args++;
865 /* c). If no attribute match exists, deny the command if the
866 default is to deny */
868 if (deny_by_default) {
869 data->status = AUTHOR_STATUS_FAIL;
870 if (debug & DEBUG_AUTHOR_FLAG) {
871 report(LOG_DEBUG, "nas:%s svr:absent, default=deny -> denied (c)",
875 for (i = 0; i < data->num_out_args; i++)
880 data->num_out_args = 0;
881 data->output_args = NULL;
883 /* free the server arguments */
884 for(cfg_argp = cfg_args; *cfg_argp; cfg_argp++)
890 /* d). If the default is permit, add the NAS AV pair to
893 if (debug & DEBUG_AUTHOR_FLAG) {
895 "nas:%s, svr:absent, default=permit -> add %s (d)",
898 *outp++ = tac_strdup(nas_arg);
899 data->num_out_args++;
904 /* NAS AV pair is Optional */
906 /* e). look for an exact attribute,value match in the mandatory
907 list. If found, add DAEMON's AV pair to output */
909 for (j = 0; j < cfg_cnt; j++) {
910 cfg_arg = cfg_args[j];
911 if (optional(cfg_arg))
914 if (match_attrs(nas_arg, cfg_arg) &&
915 match_values(nas_arg, cfg_arg)) {
917 if (debug & DEBUG_AUTHOR_FLAG) {
918 report(LOG_DEBUG, "nas:%s svr:%s -> replace with %s (e)",
919 nas_arg, cfg_arg, cfg_arg);
921 *outp++ = tac_strdup(cfg_arg);
922 data->num_out_args++;
928 /* f). If not found, look for the first attribute match in
929 the mandatory list. If found, add DAEMONS's AV pair to
932 for (j = 0; j < cfg_cnt; j++) {
933 cfg_arg = cfg_args[j];
934 if (optional(cfg_arg))
937 if (match_attrs(nas_arg, cfg_arg)) {
938 if (debug & DEBUG_AUTHOR_FLAG) {
939 report(LOG_DEBUG, "nas:%s svr:%s -> replace with %s (f)",
940 nas_arg, cfg_arg, cfg_arg);
942 *outp++ = tac_strdup(cfg_arg);
943 data->num_out_args++;
949 /* g). If no mandatory match exists, look for an exact
950 attribute,value pair match among the daemon's optional AV
951 pairs. If found add the DAEMON's matching AV pair to the
955 for (j = 0; j < cfg_cnt; j++) {
956 cfg_arg = cfg_args[j];
957 if (!optional(cfg_arg))
960 if (match_attrs(nas_arg, cfg_arg) &&
961 match_values(nas_arg, cfg_arg)) {
962 if (debug & DEBUG_AUTHOR_FLAG) {
963 report(LOG_DEBUG, "nas:%s svr:%s -> replace with %s (g)",
964 nas_arg, cfg_arg, cfg_arg);
966 *outp++ = tac_strdup(cfg_arg);
967 data->num_out_args++;
973 /* h). If no exact match exists, locate the first
974 attribute match among the daemon's optional AV
975 pairs. If found add the DAEMON's matching AV pair to
978 for (j = 0; j < cfg_cnt; j++) {
979 cfg_arg = cfg_args[j];
980 if (!optional(cfg_arg))
983 if (match_attrs(nas_arg, cfg_arg)) {
984 if (debug & DEBUG_AUTHOR_FLAG) {
985 report(LOG_DEBUG, "nas:%s svr:%s -> replace with %s (h)",
986 nas_arg, cfg_arg, cfg_arg);
988 *outp++ = tac_strdup(cfg_arg);
989 data->num_out_args++;
996 /* i). If no match is found, delete the AV pair if default is
999 if (deny_by_default) {
1000 if (debug & DEBUG_AUTHOR_FLAG) {
1001 report(LOG_DEBUG, "nas:%s svr:absent/deny -> delete %s (i)",
1008 /* j). If the default is permit add the NAS AV pair to the output */
1010 if (debug & DEBUG_AUTHOR_FLAG) {
1011 report(LOG_DEBUG, "nas:%s svr:absent/permit -> add %s (j)",
1014 *outp++ = tac_strdup(nas_arg);
1015 data->num_out_args++;
1023 /* k). After all AV pairs have been processed, for each mandatory
1024 DAEMON AV pair, if there is no attribute match already in the
1025 output list, add the AV pair (add only one AV pair for each
1026 mandatory attribute) */
1028 for (i = 0; i < cfg_cnt; i++) {
1029 cfg_arg = cfg_args[i];
1031 if (!mandatory(cfg_arg))
1034 for (j = 0; j < data->num_out_args; j++) {
1035 char *output_arg = out_args[j];
1037 if (match_attrs(cfg_arg, output_arg)) {
1042 /* Attr is required by daemon but not present in
1045 if (debug & DEBUG_AUTHOR_FLAG) {
1046 report(LOG_DEBUG, "nas:absent, server:%s -> add %s (k)",
1050 *outp++ = tac_strdup(cfg_arg);
1051 data->num_out_args++;
1057 /* If we replaced or deleted some pairs we must return the entire
1058 list we've constructed */
1061 if (debug & DEBUG_AUTHOR_FLAG) {
1062 report(LOG_DEBUG, "replaced %d args", replaced);
1064 data->status = AUTHOR_STATUS_PASS_REPL;
1065 data->output_args = out_args;
1067 /* free the server arguments */
1068 for(cfg_argp = cfg_args; *cfg_argp; cfg_argp++)
1075 /* We added something not on the original nas list, but didn't
1076 replace or delete anything. We should return only the
1081 if (debug & DEBUG_AUTHOR_FLAG)
1082 report(LOG_DEBUG, "added %d args", added);
1084 /* throw away output args which are just copies of the input args */
1085 for (i = 0; i < data->num_in_args; i++) {
1086 if (debug & DEBUG_AUTHOR_FLAG) {
1087 report(LOG_DEBUG, "out_args[%d] = %s input copy discarded",
1094 /* Now compact the new args added to the end of the array down
1098 for (i = data->num_in_args; i < data->num_out_args; i++) {
1099 if (out_args[j]) /* we goofed */
1100 report(LOG_ERR, "%s: out_args[%d] should be NULL",
1102 if (!out_args[i]) /* we goofed */
1103 report(LOG_ERR, "%s: out_args[%d] should not be NULL",
1106 if (debug & DEBUG_AUTHOR_FLAG) {
1107 report(LOG_DEBUG, "out_args[%d] = %s compacted to out_args[%d]",
1110 out_args[j++] = out_args[i];
1113 data->num_out_args = j;
1114 if (debug & DEBUG_AUTHOR_FLAG) {
1115 report(LOG_DEBUG, "%d output args", data->num_out_args);
1118 /* should/could do a realloc here but it won't matter */
1119 data->status = AUTHOR_STATUS_PASS_ADD;
1120 data->output_args = out_args;
1122 /* free the server arguments */
1123 for(cfg_argp = cfg_args; *cfg_argp; cfg_argp++)
1130 /* no additions or replacements. Input and output are
1131 identical. Don't need to return anything */
1133 if (debug & DEBUG_AUTHOR_FLAG) {
1134 report(LOG_DEBUG, "added %d", added);
1136 data->status = AUTHOR_STATUS_PASS_ADD;
1138 for (i = 0; i < data->num_out_args; i++) {
1144 /* Final sanity check */
1145 if (data->num_out_args != data->num_in_args) {
1146 data->status = AUTHOR_STATUS_ERROR;
1147 data->admin_msg = tac_strdup("Bad output arg cnt from do_author");
1148 report(LOG_ERR, "%s: Error %s", session.peer, data->admin_msg);
1150 /* free the server arguments */
1151 for(cfg_argp = cfg_args; *cfg_argp; cfg_argp++)
1158 data->num_out_args = 0;
1159 data->output_args = NULL;
1161 /* free the server arguments */
1162 for(cfg_argp = cfg_args; *cfg_argp; cfg_argp++)
1169 /* Return an integer indicating which kind of service is being
1172 Conveniently this integer is one of our node types. If the service
1173 is a command authorisation request, also return the command name in
1176 If this service is a ppp request, return the protocol name in
1179 If this service is not one of the standard, known ones, return its
1183 static int get_nas_svc TAC_ARGS((struct author_data *data, char **cmdname, char **protocol, char **svcname));
1186 get_nas_svc(data, cmdname, protocol, svcname)
1187 struct author_data *data;
1188 char **cmdname, **protocol, **svcname;
1197 for (i = 0; i < data->num_in_args; i++) {
1198 nas_arg = data->input_args[i];
1200 if (STREQ(nas_arg, "service=shell")) {
1201 for (i = 0; i < data->num_in_args; i++) {
1202 nas_arg = data->input_args[i];
1203 if (strncmp(nas_arg, "cmd", strlen("cmd")) == 0) {
1204 /* A cmd=<nothing> means we are authorising exec startup */
1205 if ((int)strlen(nas_arg) <= 4)
1206 return (N_svc_exec);
1208 /* A non-null command means we are authorising a command */
1209 *cmdname = nas_arg + strlen("cmd") + 1;
1216 if (STREQ(nas_arg, "service=slip")) {
1217 return (N_svc_slip);
1219 if (STREQ(nas_arg, "service=arap")) {
1220 return (N_svc_arap);
1222 if (STREQ(nas_arg, "service=ppp")) {
1223 for (i = 0; i < data->num_in_args; i++) {
1224 nas_arg = data->input_args[i];
1225 if (strncmp(nas_arg, "protocol", strlen("protocol")) == 0) {
1226 *protocol = nas_arg + strlen("protocol") + 1;
1232 if (strncmp(nas_arg, "service=", strlen("service=")) ==0 ) {
1233 *svcname = nas_arg + strlen("service=");