From fabeb81842796838035b64734e53a28463df50f6 Mon Sep 17 00:00:00 2001 From: Walter de Jong Date: Fri, 29 Aug 2014 12:06:46 +0200 Subject: new parameter max_challenge limits number of Access-Challenges Force authentication failure when a certain amount of challenges has been reached. This is a workaround for buggy servers that keep issueing challenges, when they should really send Access-Reject. The limit is configurable through parameter "max_challenge". The default is 0, which means the workaround is disabled. An invalid or negative value also disables this workaround. --- USAGE | 4 ++++ src/pam_radius_auth.c | 17 +++++++++++++++++ src/pam_radius_auth.h | 1 + 3 files changed, 22 insertions(+) diff --git a/USAGE b/USAGE index 48f49b4..d2694f3 100644 --- a/USAGE +++ b/USAGE @@ -91,5 +91,9 @@ prompt=string - Specifies the prompt, without the ': ', that PAM should relevant string different from Password) in this situation. +max_challenge=# - configure maximum number of challenges that a server + may request. This is a workaround for broken servers + and disabled by default. + --------------------------------------------------------------------------- diff --git a/src/pam_radius_auth.c b/src/pam_radius_auth.c index 0d8c54b..5ee7ea9 100644 --- a/src/pam_radius_auth.c +++ b/src/pam_radius_auth.c @@ -163,6 +163,10 @@ static int _pam_parse(int argc, CONST char **argv, radius_conf_t *conf) memset(conf->prompt, 0, sizeof(conf->prompt)); snprintf(conf->prompt, MAXPROMPT, "%s: ", (char*)*argv+7); } + + } else if (!strncmp(*argv, "max_challenge=", 14)) { + conf->max_challenge = atoi(*argv+14); + } else { _pam_log(LOG_WARNING, "unrecognized option '%s'", *argv); } @@ -1067,6 +1071,7 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc,CONST c char *resp2challenge = NULL; int ctrl; int retval = PAM_AUTH_ERR; + int num_challenge = 0; char recv_buffer[4096]; char send_buffer[4096]; @@ -1225,6 +1230,18 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc,CONST c PAM_FAIL_CHECK; DPRINT(LOG_DEBUG, "Got response to challenge code %d", response->code); + + /* + * max_challenge limits the # of challenges a server can issue + * It's a workaround for buggy servers + */ + if (config.max_challenge > 0 && response->code == PW_ACCESS_CHALLENGE) { + num_challenge++; + if (num_challenge >= config.max_challenge) { + DPRINT(LOG_DEBUG, "maximum number of challenges (%d) reached, failing", num_challenge); + break; + } + } } /* Whew! Done the pasword checks, look for an authentication acknowledge */ diff --git a/src/pam_radius_auth.h b/src/pam_radius_auth.h index b1ade51..74450e2 100644 --- a/src/pam_radius_auth.h +++ b/src/pam_radius_auth.h @@ -70,6 +70,7 @@ typedef struct radius_conf_t { int localifdown; char *client_id; int accounting_bug; + int max_challenge; int sockfd; int debug; char prompt[MAXPROMPT]; -- cgit v1.2.3