-/*
+/*
Copyright (c) 1995-1998 by Cisco systems, Inc.
Permission to use, copy, modify, and distribute this software for
FITNESS FOR A PARTICULAR PURPOSE.
*/
+
#include "tac_plus.h"
-#include "regexp.h"
-static int get_nas_svc();
-static int authorize_cmd();
-static int authorize_exec();
-static int authorize_svc();
-static void post_authorization();
-static int pre_authorization();
+#include <stdlib.h>
+#include <string.h>
+
+#include "do_author.h"
+#include "tac_regexp.h"
+#include "cfgfile.h"
+#include "report.h"
+#include "utils.h"
+#include "programs.h"
+#include "main.h"
+#include "parse.h"
+#include "cfgeval.h"
+
+#ifdef MAXSESS
+#include "maxsess.h"
+#endif
+#ifdef USE_PAM
+#include "tac_pam.h"
+#endif
+
+
+static int pre_authorization TAC_ARGS((const char *username, struct author_data *data));
+static int get_nas_svc TAC_ARGS((struct author_data *data, char **cmdname, char **protocol, char **svcname));
+static int authorize_cmd TAC_ARGS((const char *user, const char *cmd, struct author_data *data));
+static int authorize_exec TAC_ARGS((const char *user, struct author_data *data));
+static int authorize_svc TAC_ARGS((const char *user, int svc, const char *protocol, const char *svcname, struct author_data *data));
+static void post_authorization TAC_ARGS((const char *username, struct author_data *data));
+
+
+int do_author TAC_ARGS((struct author_data *data));
/* Return 0 is data->status is valid */
int
int svc;
char *cmd, *protocol, *svcname;
#ifdef USE_PAM
- char *pam_service= NULL;
+ const char *pam_service= NULL;
#endif
protocol = NULL;
/* If this user doesn't exist in our configs, do the default */
- if (!cfg_user_exists(username) && !cfg_user_exists(DEFAULT_USERNAME)) {
-
- if (cfg_no_user_permitted()) {
+ if (!cfg_user_exists(username)) {
+ if (!cfg_user_exists(DEFAULT_USERNAME)) {
+
+ if (cfg_no_user_permitted()) {
+ if (debug & DEBUG_AUTHOR_FLAG)
+ report(LOG_DEBUG,
+ "user '%s' or '%s' not found, permitted by default",
+ username, DEFAULT_USERNAME);
+
+ data->status = AUTHOR_STATUS_PASS_ADD;
+ data->output_args = NULL;
+ data->num_out_args = 0;
+ return (0);
+ }
+
if (debug & DEBUG_AUTHOR_FLAG)
- report(LOG_DEBUG,
- "user '%s' or '%s' not found, permitted by default",
+ report(LOG_DEBUG,
+ "user '%s' or '%s' not found, denied by default",
username, DEFAULT_USERNAME);
-
- data->status = AUTHOR_STATUS_PASS_ADD;
- data->output_args = NULL;
- data->num_out_args = 0;
+ data->status = AUTHOR_STATUS_FAIL;
return (0);
}
- if (debug & DEBUG_AUTHOR_FLAG)
- report(LOG_DEBUG,
- "user '%s' or '%s' not found, denied by default",
- username, DEFAULT_USERNAME);
- data->status = AUTHOR_STATUS_FAIL;
- return (0);
- }
+ /* assumed (cfg_user_exists(DEFAULT_USERNAME)): */
- if (!cfg_user_exists(username) && cfg_user_exists(DEFAULT_USERNAME)) {
if (debug & DEBUG_AUTHOR_FLAG) {
- report(LOG_DEBUG, "Authorizing user '%s' instead of '%s'",
+ report(LOG_DEBUG, "Authorizing user '%s' instead of '%s'",
DEFAULT_USERNAME, username);
}
username = DEFAULT_USERNAME;
}
/* See if there's a program defined which will do authorization for us */
- if (pre_authorization(username, data))
+ if (pre_authorization(username, data))
return(0);
-
- /*
+
+ /*
* Decide what kind of authorization request this is. Currently
* one of: exec, cmd, slip, arap, ppp or <string>
- *
+ *
* If it's a command typed to the exec, return its text in cmd.
- *
+ *
* If it's a ppp request, return the protocol name in protocol.
*/
#endif /* MAXSESS */
#ifdef USE_PAM
- /* Check PAM Authorization */
- switch (svc) {
+ /* Check PAM Authorization */
+ switch (svc) {
+
case N_svc_ppp:
case N_svc_exec:
-if (pam_service=cfg_get_pam_service(data->id->username,TAC_PLUS_RECURSE) ) {
+ if ((pam_service = cfg_get_pam_service(data->id->username, TAC_PLUS_RECURSE) )) {
- if (debug & DEBUG_AUTHOR_FLAG)
+ if (debug & DEBUG_AUTHOR_FLAG)
report(LOG_DEBUG, "PAM Authorization begin for user %s",data->id->username);
- if(tac_pam_authorization(data->id->username,data,pam_service))
- {
- if (debug & DEBUG_AUTHOR_FLAG)
- report(LOG_DEBUG, "PAM Authorization Fail");
+ if (tac_pam_authorization(data->id->username, data, pam_service)) {
+ if (debug & DEBUG_AUTHOR_FLAG)
+ report(LOG_DEBUG, "PAM Authorization Fail");
return(0);
- }
-} /* Pam_service */
+ }
+ } /* Pam_service */
+
default:
break;
}
-#endif
+#endif
switch(svc) {
default:
/* A command authorisation request */
status = authorize_cmd(username, cmd, data);
break;
-
+
case N_svc_exec:
- if (authorize_exec(username, data))
+ if (authorize_exec(username, data))
return(0);
/* FALLTHRU */
}
post_authorization(username, data);
- return(status);
+ return(status);
}
-/* If an before-authorization program has been specified, call it.
+/* If an before-authorization program has been specified, call it.
A return value of 1 means no further authorization is required
*/
+static int pre_authorization TAC_ARGS((const char *username, struct author_data *data));
+
static int
-pre_authorization(username, data)
-char *username;
+pre_authorization(username, data)
+const char *username;
struct author_data *data;
{
int status;
char **out_args;
int out_cnt, i;
- char *cmd;
+ const char *cmd;
char error_str[255];
int error_len = 255;
/* If a before-authorization program exists, call it to see how to
proceed */
- cmd = cfg_get_pvalue(username, TAC_IS_USER,
+ cmd = cfg_get_pvalue(S_user, username,
S_before, TAC_PLUS_RECURSE);
- if (!cmd)
+ if (!cmd)
return(0);
if (debug & DEBUG_AUTHOR_FLAG)
switch (status) {
default:
if (debug & DEBUG_AUTHOR_FLAG)
- report(LOG_DEBUG, "cmd %s returns %d (unrecognised value)",
+ report(LOG_DEBUG, "cmd %s returns %d (unrecognised value)",
cmd, status);
data->status = AUTHOR_STATUS_ERROR;
- data->admin_msg =
+ data->admin_msg =
tac_strdup("Illegal return status from pre-authorization command");
data->msg = tac_strdup(error_str);
data->num_out_args = 0;
free(out_args);
}
return(1);
-
+
case 1: /* Deny */
if (debug & DEBUG_AUTHOR_FLAG)
- report(LOG_DEBUG, "cmd %s returns %d (unconditional deny)",
+ report(LOG_DEBUG, "cmd %s returns %d (unconditional deny)",
cmd, status);
data->status = AUTHOR_STATUS_FAIL;
case 2: /* Use replacement AV pairs from program as final result */
if (debug & DEBUG_AUTHOR_FLAG) {
- report(LOG_DEBUG, "cmd %s returns %d (permitted, args replaced)",
+ report(LOG_DEBUG, "cmd %s returns %d (permitted, args replaced)",
cmd, status);
for(i=0; i < out_cnt; i++)
- report(LOG_DEBUG, "%s", out_args[i]);
+ report(LOG_DEBUG, "%s", out_args[i]);
}
/* and install the new set of AV pairs as output */
case 3: /* deny, but return attributes and server-msg to NAS */
if (debug & DEBUG_AUTHOR_FLAG) {
- report(LOG_DEBUG, "cmd %s returns %d (deny, args replaced)",
+ report(LOG_DEBUG, "cmd %s returns %d (deny, args replaced)",
cmd, status);
for(i=0; i < out_cnt; i++)
- report(LOG_DEBUG, "%s", out_args[i]);
+ report(LOG_DEBUG, "%s", out_args[i]);
}
/* and install the new set of AV pairs as output */
change the authorization status by calling an external program.
*/
+static void post_authorization TAC_ARGS((const char *username, struct author_data *data));
+
static void
-post_authorization(username, data)
- char *username;
- struct author_data *data;
+post_authorization(username, data)
+const char *username;
+struct author_data *data;
{
char **out_args;
int out_cnt, i;
int status;
- char *after = cfg_get_pvalue(username, TAC_IS_USER,
- S_after, TAC_PLUS_RECURSE);
- if (!after)
+ const char *after = cfg_get_pvalue(S_user, username, S_after, TAC_PLUS_RECURSE);
+ if (!after)
return;
if (debug & DEBUG_AUTHOR_FLAG)
switch (status) {
default:
if (debug & DEBUG_AUTHOR_FLAG)
- report(LOG_DEBUG,
+ report(LOG_DEBUG,
"cmd %s returns %d (Error)", after, status);
data->status = AUTHOR_STATUS_ERROR;
if (debug & DEBUG_AUTHOR_FLAG)
report(LOG_DEBUG, "cmd %s returns 0 (no change)", after);
return;
-
+
case 1: /* Deny */
if (debug & DEBUG_AUTHOR_FLAG)
- report(LOG_DEBUG, "cmd %s returns %d (unconditional deny)",
+ report(LOG_DEBUG, "cmd %s returns %d (unconditional deny)",
after, status);
data->status = AUTHOR_STATUS_FAIL;
case 2:
/* Use replacement AV pairs from program */
if (debug & DEBUG_AUTHOR_FLAG)
- report(LOG_DEBUG, "cmd %s returns 2 (replace & continue)",
+ report(LOG_DEBUG, "cmd %s returns 2 (replace & continue)",
after);
/* Free any existing AV output pairs */
}
+static char *value TAC_ARGS((char *s));
+
/* Return a pointer to the value part of an attr=value string */
static char *
value(s)
/* Reassemble the command arguments as typed by the user, out of the
array of args we received. Return "" if there are no arguments */
+static char *assemble_args TAC_ARGS((struct author_data *data));
+
static char *
assemble_args(data)
struct author_data *data;
Otherwise, we return 1, indicating no further processing is
required for this request. */
+static int authorize_exec TAC_ARGS((const char *user, struct author_data *data));
+
static int
authorize_exec(user, data)
-char *user;
+const char *user;
struct author_data *data;
{
- NODE *svc;
-
- if (debug & DEBUG_AUTHOR_FLAG)
+ if (debug & DEBUG_AUTHOR_FLAG)
report(LOG_DEBUG, "exec authorization request for %s", user);
/* Is an exec explicitly configured? If so, return 0 so we know to
process its attributes */
- svc = cfg_get_svc_node(user, N_svc_exec, NULL, NULL, TAC_PLUS_RECURSE);
- if (svc) {
- if (debug & DEBUG_AUTHOR_FLAG)
- report(LOG_DEBUG, "exec is explicitly permitted by line %d",
- svc->line);
+ if (cfg_get_svc_node(user, N_svc_exec, NULL, NULL, TAC_PLUS_RECURSE, NULL /* nodep */)) {
+ if (debug & DEBUG_AUTHOR_FLAG)
+ report(LOG_DEBUG, "exec is explicitly permitted");
return (0);
}
/* No exec is configured. Are any commands configured? */
- svc = cfg_get_svc_node(user, N_svc_cmd, NULL, NULL, TAC_PLUS_RECURSE);
- if (svc) {
- if (debug & DEBUG_AUTHOR_FLAG)
+ if (cfg_get_svc_node(user, N_svc_cmd, NULL, NULL, TAC_PLUS_RECURSE, NULL /* nodep */)) {
+ if (debug & DEBUG_AUTHOR_FLAG)
report(LOG_DEBUG, "exec permitted because commands are configured");
data->status = AUTHOR_STATUS_PASS_ADD;
return (1);
}
- /* No exec or commands configured. What's the default? */
- if (cfg_user_svc_default_is_permit(user)) {
-
- if (debug & DEBUG_AUTHOR_FLAG)
- report(LOG_DEBUG, "exec permitted by default");
-
- data->status = AUTHOR_STATUS_PASS_ADD;
- data->output_args = NULL;
- data->num_out_args = 0;
- return (1);
- }
-
- if (debug & DEBUG_AUTHOR_FLAG)
+ if (debug & DEBUG_AUTHOR_FLAG)
report(LOG_DEBUG, "exec denied by default");
data->status = AUTHOR_STATUS_FAIL;
return(1);
}
-/* Is an exec command authorized per our database(s)?
+/* Is an exec command authorized per our database(s)?
Return 0 if status is valid */
+static int authorize_cmd TAC_ARGS((const char *user, const char *cmd, struct author_data *data));
+
static int
authorize_cmd(user, cmd, data)
-char *user, *cmd;
+const char *user;
+const char *cmd;
struct author_data *data;
{
- NODE *node;
char *args;
- int match;
-
- args = assemble_args(data);
if (!cmd) {
data->status = AUTHOR_STATUS_ERROR;
return (0);
}
- node = cfg_get_cmd_node(user, cmd, TAC_PLUS_RECURSE);
-
- /* The command does not exist. Do the default */
- if (!node) {
-
- if (cfg_user_svc_default_is_permit(user)) {
-
- if (debug & DEBUG_AUTHOR_FLAG)
- report(LOG_DEBUG, "cmd %s does not exist, permitted by default",
- cmd);
-
- data->status = AUTHOR_STATUS_PASS_ADD;
- data->num_out_args = 0;
- if (args)
- free(args);
- return(0);
- }
+ args = assemble_args(data);
+ switch (cfg_authorize_cmd(user, cmd, args)) {
- if (debug & DEBUG_AUTHOR_FLAG)
- report(LOG_DEBUG, "cmd %s does not exist, denied by default",
- cmd);
+ case ER_TRUE:
+ data->status = AUTHOR_STATUS_PASS_ADD;
+ data->num_out_args = 0;
+ break;
+ case ER_FALSE:
data->status = AUTHOR_STATUS_FAIL;
data->num_out_args = 0;
- if (args)
- free(args);
- return(0);
- }
-
- /* The command exists. The default if nothing matches is DENY */
- data->status = AUTHOR_STATUS_FAIL;
- data->num_out_args = 0;
-
- for (node=node->value1; node && args; node = node->next) {
- match = regexec((regexp *) node->value1, args);
-
- if (debug & DEBUG_AUTHOR_FLAG) {
- report(LOG_INFO, "line %d compare %s %s '%s' & '%s' %smatch",
- node->line, cmd,
- node->type == N_permit ? "permit" : "deny",
- node->value, args, (match ? "" : "no "));
- }
-
- if (!match)
- continue;
+ break;
- switch (node->type) {
- case N_permit:
- if (debug & DEBUG_AUTHOR_FLAG) {
- report(LOG_DEBUG, "%s %s permitted by line %d",
- cmd, args, node->line);
- }
- data->status = AUTHOR_STATUS_PASS_ADD;
- data->num_out_args = 0;
- break;
- case N_deny:
- if (debug & DEBUG_AUTHOR_FLAG) {
- report(LOG_DEBUG, "%s %s denied by line %d",
- cmd, args, node->line);
- }
- data->status = AUTHOR_STATUS_FAIL;
- data->num_out_args = 0;
- break;
- default:
- data->status = AUTHOR_STATUS_ERROR;
- data->admin_msg = tac_strdup("Server error illegal configuration node");
- report(LOG_ERR, "%s: %s %s %s",
- session.peer, cmd, args, data->admin_msg);
- break;
- }
- if (args)
- free(args);
- args = NULL;
- return (0);
+ case ER_UNKNOWN:
+ data->status = AUTHOR_STATUS_ERROR;
+ data->admin_msg = tac_strdup("Server error illegal configuration");
+ break;
}
+
if (args)
free(args);
- return (0);
+ return(0);
}
+static int is_separator TAC_ARGS((int ch));
+
static int
is_separator(ch)
-char ch;
+int ch; /* promoted "char" type */
{
return (ch == '=' || ch == '*');
}
+static int arg_ok TAC_ARGS((char *arg));
+
/* check an attr=value pair for well-formedness */
static int
arg_ok(arg)
}
+static int match_attrs TAC_ARGS((char *nas_arg, char *server_arg));
+
/* return 1 if attrs match, 0 otherwise */
static int
match_attrs(nas_arg, server_arg)
return (0);
}
+static int match_values TAC_ARGS((char *nas_arg, char *server_arg));
+
/* return 1 if values match, 0 otherwise */
static int
match_values(nas_arg, server_arg)
char *nas_arg, *server_arg;
{
- while (*nas_arg &&
+ while (*nas_arg &&
*server_arg &&
!is_separator(*nas_arg)) {
nas_arg++;
nas_arg++;
if (*server_arg)
server_arg++;
-
+
/* compare values */
return(STREQ(nas_arg, server_arg));
}
+static int mandatory TAC_ARGS((char *arg));
+
/* Return 1 if arg is mandatory, 0 otherwise */
static int
mandatory(arg)
/* if we're not at the end, this must be the separator */
if (*p && !is_separator(*p)) {
- report(LOG_ERR, "%s: Error on arg %s cannot find separator",
+ report(LOG_ERR, "%s: Error on arg %s cannot find separator",
session.peer, arg);
return (0);
}
return (*p == '=');
}
+static int optional TAC_ARGS((char *arg));
+
static int
optional(arg)
char *arg;
/* PPP-LCP requests are a special case. If they are not explicitly
configured, but there are other ppp services explicitly configured,
- we admit (return 0) any PPP-LCP request */
+ we admit (return 1) any PPP-LCP request */
-static int
-ppp_lcp_allowed(svc, protocol, user)
- int svc;
- char *user, *protocol;
-{
- /* This is not a ppp/lcp request. Just Say No */
- if (!(svc == N_svc_ppp &&
- protocol &&
- STREQ(protocol, "lcp")))
- return(0);
+static int ppp_lcp_allowed TAC_ARGS((const char *user));
- /* It is an LCP request. Are there PPP services configured */
- if (cfg_ppp_is_configured(user, TAC_PLUS_RECURSE)) {
+static int
+ppp_lcp_allowed(user)
+const char *user;
+{
+ /* It is an LCP request. Are there PPP services configured? */
+ if (cfg_get_svc_node(user, N_svc_ppp, NULL /* protocol */, NULL /* svcname */, TAC_PLUS_RECURSE, NULL /* nodep */)) {
if (debug & DEBUG_AUTHOR_FLAG) {
- report(LOG_DEBUG,
+ report(LOG_DEBUG,
"ppp/lcp request permitted (ppp is configured for %s)",
user);
}
return(1);
}
-
+
/* It is an LCP request but no PPP services are configured */
if (debug & DEBUG_AUTHOR_FLAG) {
report(LOG_DEBUG, "ppp/lcp request denied (ppp not configured for %s)",
return(0);
}
+static int authorize_svc TAC_ARGS((const char *user, int svc, const char *protocol, const char *svcname, struct author_data *data));
+
/* Return 0 means data->status is valid */
static int
authorize_svc(user, svc, protocol, svcname, data)
- char *user;
- int svc;
- char *svcname;
- struct author_data *data;
- char *protocol; /* valid only if svc == ppp */
+const char *user;
+int svc;
+const char *svcname;
+struct author_data *data;
+const char *protocol; /* valid only if svc == ppp */
{
int max_args;
char **out_args, **outp;
char **cfg_argp;
int deny_by_default;
NODE *node;
+ int service_permit;
int replaced = 0;
int added = 0;
int cfg_cnt;
/* Does this service exist? */
- node = cfg_get_svc_node(user, svc, protocol, svcname, TAC_PLUS_RECURSE);
+ service_permit = cfg_get_svc_node(user, svc, protocol, svcname, TAC_PLUS_RECURSE, &node);
- if (!node) {
- /* Service not found. If the default is permit, or this is an
- PPP/LCP request and other ppp services are configured,
- we'll allow it. */
+ /* Now we may have three cases:
+ * service_permit == 1 && node != NULL
+ * service_permit == 1 && node == NULL
+ * service_permit == 0 (BTW node == NULL)
+ */
- if (cfg_user_svc_default_is_permit(user)) {
+ if (service_permit && !node) {
+ /* Service not found and the default is permit, we'll allow it. */
- if (debug & DEBUG_AUTHOR_FLAG)
- report(LOG_DEBUG,
- "svc=%s protocol=%s svcname=%s not found, permitted by default",
- cfg_nodestring(svc),
- protocol ? protocol : "",
- svcname ? svcname : "");
+ if (debug & DEBUG_AUTHOR_FLAG)
+ report(LOG_DEBUG,
+ "svc=%s protocol=%s svcname=%s not found, permitted by default",
+ cfg_nodestring(svc),
+ protocol ? protocol : "",
+ svcname ? svcname : "");
- data->status = AUTHOR_STATUS_PASS_ADD;
- data->num_out_args = 0;
- data->output_args = NULL;
- return(0);
+ data->status = AUTHOR_STATUS_PASS_ADD;
+ data->num_out_args = 0;
+ data->output_args = NULL;
+ return(0);
}
- if (ppp_lcp_allowed(svc, protocol, user)) {
+ if (!service_permit) {
+ /* Service not found, if this is an
+ PPP/LCP request and other ppp services are configured,
+ we'll allow it. */
+
+ if (svc == N_svc_ppp && protocol && STREQ(protocol, "lcp")
+ && ppp_lcp_allowed(user)) {
data->status = AUTHOR_STATUS_PASS_ADD;
data->num_out_args = 0;
data->output_args = NULL;
data->output_args = NULL;
return(0);
}
-
+
/* Get server args configured in the config file. */
cfg_args = cfg_get_svc_attrs(node, &deny_by_default);
free(out_args[i]);
free(out_args);
}
-
+
data->num_out_args = 0;
data->output_args = NULL;
-
+
/* free the server arguments */
for(cfg_argp = cfg_args; *cfg_argp; cfg_argp++)
free(*cfg_argp);
the output */
if (debug & DEBUG_AUTHOR_FLAG) {
- report(LOG_DEBUG,
+ report(LOG_DEBUG,
"nas:%s, svr:absent, default=permit -> add %s (d)",
nas_arg, nas_arg);
}
/* f). If not found, look for the first attribute match in
the mandatory list. If found, add DAEMONS's AV pair to
output */
-
+
for (j = 0; j < cfg_cnt; j++) {
cfg_arg = cfg_args[j];
if (optional(cfg_arg))
cfg_arg = cfg_args[j];
if (!optional(cfg_arg))
continue;
-
- if (match_attrs(nas_arg, cfg_arg) &&
+
+ if (match_attrs(nas_arg, cfg_arg) &&
match_values(nas_arg, cfg_arg)) {
if (debug & DEBUG_AUTHOR_FLAG) {
report(LOG_DEBUG, "nas:%s svr:%s -> replace with %s (g)",
cfg_arg = cfg_args[j];
if (!optional(cfg_arg))
continue;
-
+
if (match_attrs(nas_arg, cfg_arg)) {
if (debug & DEBUG_AUTHOR_FLAG) {
report(LOG_DEBUG, "nas:%s svr:%s -> replace with %s (h)",
}
-
+
/* k). After all AV pairs have been processed, for each mandatory
DAEMON AV pair, if there is no attribute match already in the
output list, add the AV pair (add only one AV pair for each
cfg_arg = cfg_args[i];
if (!mandatory(cfg_arg))
- continue;
+ continue;
for (j = 0; j < data->num_out_args; j++) {
char *output_arg = out_args[j];
data->num_out_args++;
next_cfg_arg:;
-
+
}
-
+
/* If we replaced or deleted some pairs we must return the entire
list we've constructed */
if (added) {
- if (debug & DEBUG_AUTHOR_FLAG)
+ if (debug & DEBUG_AUTHOR_FLAG)
report(LOG_DEBUG, "added %d args", added);
/* throw away output args which are just copies of the input args */
for (i = 0; i < data->num_in_args; i++) {
if (debug & DEBUG_AUTHOR_FLAG) {
- report(LOG_DEBUG, "out_args[%d] = %s input copy discarded",
+ report(LOG_DEBUG, "out_args[%d] = %s input copy discarded",
i, out_args[i]);
}
free(out_args[i]);
j = 0;
for (i = data->num_in_args; i < data->num_out_args; i++) {
if (out_args[j]) /* we goofed */
- report(LOG_ERR, "%s: out_args[%d] should be NULL",
+ report(LOG_ERR, "%s: out_args[%d] should be NULL",
session.peer, j);
if (!out_args[i]) /* we goofed */
report(LOG_ERR, "%s: out_args[%d] should not be NULL",
session.peer, i);
if (debug & DEBUG_AUTHOR_FLAG) {
- report(LOG_DEBUG, "out_args[%d] = %s compacted to out_args[%d]",
+ report(LOG_DEBUG, "out_args[%d] = %s compacted to out_args[%d]",
i, out_args[i], j);
}
out_args[j++] = out_args[i];
}
/* Return an integer indicating which kind of service is being
- requested.
+ requested.
Conveniently this integer is one of our node types. If the service
is a command authorisation request, also return the command name in
- cmdname.
+ cmdname.
If this service is a ppp request, return the protocol name in
protocol.
name in svcname.
*/
+static int get_nas_svc TAC_ARGS((struct author_data *data, char **cmdname, char **protocol, char **svcname));
+
static int
get_nas_svc(data, cmdname, protocol, svcname)
struct author_data *data;
{
int i;
char *nas_arg;
-
+
*cmdname = NULL;
*protocol = NULL;
*svcname = NULL;