Goal: Retrieve the PAM username in case a module changed the PAM_USER item. According to Linux-PAM_ADG: * Note, modules can change the values of PAM_USER and PAM_RUSER during any of the pam_*() library calls. For this reason, the application should take care to use the pam_get_item() every time it wishes to establish who the authenticated user is (or will currently be). PAM_USER description: The username of the entity under whose identity service will be given. That is, following authentication, PAM_USER identifies the local entity that gets to use the service. Note, this value can be mapped from something (eg., "anonymous") to something else (eg. "guest119") by any module in the PAM stack. As such an application should consult the value of PAM_USER after each call to a PAM function. See also: https://www.redhat.com/archives/pam-list/2008-May/msg00009.html Index: shadow-4.1.0/src/su.c =================================================================== --- shadow-4.1.0.orig/src/su.c +++ shadow-4.1.0/src/su.c @@ -309,6 +309,8 @@ char **envp = environ; char *shellstr = NULL; char *command = NULL; + char *tmp_name; + char **ptr_tmp_name = &tmp_name; #ifdef USE_PAM char **envcp; @@ -674,6 +676,14 @@ su_failure (tty); } } + ret = pam_get_item(pamh, PAM_USER, (const void **) ptr_tmp_name); + if (ret != PAM_SUCCESS) { + SYSLOG((LOG_ERR, "pam_get_item: internal PAM error\n")); + fprintf(stderr, "%s: Internal PAM error retrieving username\n", Prog); + (void) pam_end(pamh, ret); + su_failure(tty); + } + strncpy(name, tmp_name, sizeof(name) - 1); #else /* !USE_PAM */ /* * Set up a signal handler in case the user types QUIT.