I am trying to get data into a process invoked via ssh by adding it the supplied username, e.g.
ssh user@smuggledata@host
I've written a PAM module, however
- sshd has already decided the user is bad before invoking PAM
- although I have changed the PAM_USER, subsequent modules are still authenticating against the submitted username.
I first tried running the code with auth requisite mymodule.so and the code in pam_sm_authenticate(). Although the code fired - it did not work:
May 1 22:40:30 animal sshd[3827]: Invalid user colin@example from 127.0.0.1
May 1 22:40:30 animal sshd[3827]: input_userauth_request: invalid user colin@example [preauth]
May 1 22:40:35 animal pam_pat[3827]: Retrieved username colin@example
May 1 22:40:35 animal pam_pat[3827]: checking char c against 3 dividers
May 1 22:40:35 animal pam_pat[3827]: checking char o against 3 dividers
May 1 22:40:35 animal pam_pat[3827]: checking char l against 3 dividers
May 1 22:40:35 animal pam_pat[3827]: checking char i against 3 dividers
May 1 22:40:35 animal pam_pat[3827]: checking char n against 3 dividers
May 1 22:40:35 animal pam_pat[3827]: checking char @ against 3 dividers
May 1 22:40:35 animal pam_pat[3827]: Found divider @
May 1 22:40:35 animal pam_pat[3827]: user=colin, data=example
May 1 22:40:35 animal sshd[3827]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=127.0.0.1 user=colin
May 1 22:40:37 animal sshd[3827]: Failed password for invalid user colin@example from 127.0.0.1 port 43998 ssh2
May 1 22:41:28 animal sshd[3827]: Connection closed by 127.0.0.1 port 43998 [preauth]
Note that when execution reaches pam_unix authentication fails but the user is reported as the transformed value in PAM_USER. The password was correct, hence pam_unix was presumably not authenticating against PAM_USER.
I also tried with account requisite mymodule.so and the code in pam_sm_acct_mgmt() - but the code was not invoked:
May 1 22:57:10 animal sshd[4105]: Invalid user colin@exmple from 127.0.0.1
May 1 22:57:10 animal sshd[4105]: input_userauth_request: invalid user colin@exmple [preauth]
May 1 22:57:16 animal sshd[4105]: pam_unix(sshd:auth): check pass; user unknown
May 1 22:57:16 animal sshd[4105]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=127.0.0.1
May 1 22:57:18 animal sshd[4105]: Failed password for invalid user colin@exmple from 127.0.0.1 port 44118 ssh2
May 1 22:57:27 animal sshd[4105]: Connection closed by 127.0.0.1 port 44118 [preauth]
Looking at the source code for pam_unix it retrieves the username from pam_get_user() which apparently points to something other than PAM_USER.
How do I change the value which is subsequently user for authentication?
- how do I ensure this happens before any other processing of the username occurs?
- is there a better way to do it than to write back to the pointer returned by pam_get_user() ?
update The code (with added pam_get_user()):
char *submitted_name;
char work_bufr[PAT_BUFR];
char log_entry[PAT_BUFR];
int an_int;
char dividers[]="@%+";
int num_dividers;
char *cursor;
char divider_found[]="0";
const char *debug_user;
openlog("pam_pat", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_AUTH);
/* retrieve a copy of the submitted username */
if (PAM_SUCCESS != pam_get_item(pamh, PAM_USER, (void *) &submitted_name) || !(submitted_name)) {
syslog (LOG_ERR, "Failed to retrieve username from pam");
closelog();
return(PAM_IGNORE);
}
syslog (LOG_ERR, "Retrieved username %s", submitted_name);
strncpy(work_bufr, submitted_name, PAT_BUFR);
submitted_name=work_bufr;
/* search for dividers and split string */
cursor=submitted_name;
an_int=PAT_BUFR;
num_dividers=(int)strlen(dividers);
while (--an_int && '\0'!=*cursor) {
syslog(LOG_ERR, "checking char %c against %d dividers", (int)*cursor, num_dividers);
for (int x=0; x<num_dividers; x++) {
if (*cursor==dividers[x]) {
syslog(LOG_ERR, "Found divider %c", *cursor);
an_int=0;
*divider_found=*cursor;
*cursor='\0';
if (PAM_SUCCESS==pam_set_item(pamh, PAM_USER, submitted_name)) {
++cursor;
syslog (LOG_ERR, "user=%s, data=%s",submitted_name,cursor);
setenv("PAM_PAT_DIVDR", divider_found, 1);
setenv("PAM_PAT_DATA", cursor, 1);
if (PAM_SUCCESS == pam_get_user(pamh, &debug_user, NULL)) {
syslog (LOG_ERR, "pam_get_user() found %s", debug_user);
}
closelog();
return(PAM_IGNORE);
} else {
syslog (LOG_ERR, "Failed to update username");
}
}
}
cursor++;
}
syslog (LOG_ERR, "Extended username not found.");
closelog();
return(PAM_IGNORE);
}