Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding challenge customization option #69

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions USAGE
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ force_prompt - Request a new password and not using the previously entered
password. This useful for multi-factor authentication
when used with a Token.

challenge=string - Specifies a custom challenge prompt. This will substitute
any challenge prompt inside the Reply-Message attribute of a
Access-Challenge request to a custom prompt. Use
challenge="Enter your TOTP: " (or some other relevant string)
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.
Expand Down
33 changes: 29 additions & 4 deletions src/pam_radius_auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,20 @@ static int _pam_parse(int argc, CONST char **argv, radius_conf_t *conf)
snprintf(conf->prompt, MAXPROMPT, "%s: ", (arg+7));
}

} else if (!strncmp(arg, "challenge=", 10)) {
if (!strncmp(conf->challenge, (arg+10), MAXCHALLENGE)) {
_pam_log(LOG_WARNING, "ignoring duplicate '%s'", arg);
} else {
/* truncate excessive challenge prompts to (MAXCHALLENGE - 3) length */
if (strlen((arg+10)) >= (MAXCHALLENGE - 3)) {
*((arg + 10) + (MAXCHALLENGE - 3)) = '\0';
}

/* set the new challenge prompt */
memset(conf->challenge, 0, sizeof(conf->challenge));
snprintf(conf->challenge, MAXCHALLENGE, "%s: ", (arg+10));
}

} else if (!strcmp(arg, "force_prompt")) {
conf->force_prompt = TRUE;

Expand All @@ -196,13 +210,14 @@ static int _pam_parse(int argc, CONST char **argv, radius_conf_t *conf)
}
}


if (conf->debug) {
#define print_bool(cond) (cond) ? "yes" : "no"
#define print_string(cond) (cond) ? cond : ""

_pam_log(LOG_DEBUG, "DEBUG: conf='%s' use_first_pass=%s try_first_pass=%s skip_passwd=%s retry=%d " \
"localifdown=%s client_id='%s' accounting_bug=%s ruser=%s prompt='%s' force_prompt=%s "\
"prompt_attribute=%s max_challenge=%d privilege_level=%s",
"prompt_attribute=%s challenge=%s max_challenge=%d privilege_level=%s",
conf->conf_file,
print_bool(ctrl & PAM_USE_FIRST_PASS),
print_bool(ctrl & PAM_TRY_FIRST_PASS),
Expand All @@ -215,6 +230,7 @@ static int _pam_parse(int argc, CONST char **argv, radius_conf_t *conf)
conf->prompt,
print_bool(conf->force_prompt),
print_bool(conf->prompt_attribute),
conf->challenge,
conf->max_challenge,
print_bool(conf->privilege_level)
);
Expand Down Expand Up @@ -1282,6 +1298,8 @@ static int rad_converse(pam_handle_t *pamh, int msg_style, const char *message,
return retval; \
}



PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, UNUSED int flags, int argc, CONST char **argv)
{
CONST char *user = NULL;
Expand Down Expand Up @@ -1323,6 +1341,7 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, UNUSED int flags, int arg
return PAM_USER_UNKNOWN;
}


DPRINT(LOG_DEBUG, "Got user name: '%s'", user);

if (ctrl & PAM_RUSER_ARG) {
Expand Down Expand Up @@ -1358,6 +1377,8 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, UNUSED int flags, int arg
#undef PAM_FAIL_CHECK
#define PAM_FAIL_CHECK if (retval != PAM_SUCCESS) { goto do_next; }



/* build and initialize the RADIUS packet */
request->code = PW_AUTHENTICATION_REQUEST;
get_random_vector(request->vector);
Expand Down Expand Up @@ -1444,9 +1465,13 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, UNUSED int flags, int arg
retval = PAM_AUTHINFO_UNAVAIL;
goto do_next;
}

memcpy(challenge, a_reply->data, a_reply->length - 2);
challenge[a_reply->length - 2] = 0;
if (strlen(config.challenge) != 0){
memcpy(challenge,config.challenge,sizeof(config.challenge));
challenge[strlen(config.challenge)] = 0;
} else {
memcpy(challenge, a_reply->data, a_reply->length - 2);
challenge[a_reply->length - 2] = 0;
}

/* It's full challenge-response, default to echo on, unless the server wants it off */
prompt = PAM_PROMPT_ECHO_ON;
Expand Down
5 changes: 5 additions & 0 deletions src/pam_radius_auth.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@
#define MAXPROMPT 33 /* max prompt length, including '\0' */
#define DEFAULT_PROMPT "Password" /* default prompt, without the ': ' */

/* Custom challenge length */
#define MAXCHALLENGE 90


/*************************************************************************
* Platform specific defines
Expand Down Expand Up @@ -100,6 +103,7 @@
#define PAM_RUSER_ARG 16



/* buffer size for IP address in string form */
#define MAX_IP_LEN 16

Expand Down Expand Up @@ -185,6 +189,7 @@ typedef struct radius_conf_t {
int debug;
CONST char *conf_file;
char prompt[MAXPROMPT];
char challenge[MAXCHALLENGE];
int prompt_attribute;
int privilege_level;
} radius_conf_t;
Expand Down