Greetings, I am working on using FreeRadius with token authentication and ran into a small snag. Under Linux, attempts to authenticate 'su' result in a query to the Radius server for the user 'root'. What we would like to happen is for the query to be for the requesting user. This is how the 'sudo' application handles it's PAM requests. I of course do not want to change the default behavior of the module, so I added an option. I named it 'ruser' since it works by causing the PAM module to authenticate using the value of PAM_RUSER (requesting user). The 'su' application provides this value, so that's an easy place to grab it from. I expect that this patch may need more work. It doesn't do much sanity checking on the values of PAM_RUSER. There may be applications which don't fill it in properly. I haven't checked extensively. Also, I worked from the Debian source version which includes a patch for CVE-2005-0108: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2005-0108 I'm not sure who maintains the PAM portion of FreeRadius, so I'm throwing this out for discussion. Does this seem like something which could be included in the distribution? Or should I plan on using a locally patched version for the foreseeable future? -- ----------------------------------------------------------------- | David Mitchell (mitchell@ucar.edu) Network Engineer IV | | Tel: (303) 497-1845 National Center for | | FAX: (303) 497-1818 Atmospheric Research | ----------------------------------------------------------------- --- ./pam_radius_auth.c 2007-03-12 10:18:18.000000000 -0600 +++ ./libpam-radius-auth-1.3.16/pam_radius_auth.c 2007-03-15 13:43:45.000000000 -0600 @@ -134,6 +134,9 @@ } else if (!strcmp(*argv, "accounting_bug")) { conf->accounting_bug = TRUE; + } else if (!strcmp(*argv, "ruser")) { + ctrl |= PAM_RUSER_ARG; + conf->ruser = 1; } else if (!strcmp(*argv, "debug")) { ctrl |= PAM_DEBUG_ARG; conf->debug = 1; @@ -1051,6 +1054,7 @@ pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc,CONST char **argv) { CONST char *user; + CONST char **userinfo; char *password = NULL; CONST char *rhost; char *resp2challenge = NULL; @@ -1084,6 +1088,24 @@ DPRINT(LOG_DEBUG, "Got user name %s", user); + + retval = pam_get_item(pamh, PAM_USER, (CONST void **) &userinfo); + PAM_FAIL_CHECK; + DPRINT(LOG_DEBUG, "Got PAM_USER name %s", userinfo); + retval = pam_get_item(pamh, PAM_RUSER, (CONST void **) &userinfo); + PAM_FAIL_CHECK; + DPRINT(LOG_DEBUG, "Got PAM_RUSER name %s", userinfo); + if (ctrl & PAM_RUSER_ARG) { + if (!strncmp("root",user,5)) { + user = userinfo; + DPRINT(LOG_DEBUG, "Username now %s from ruser", user); + } else { + DPRINT(LOG_DEBUG, "Skipping ruser for non-root auth"); + }; + }; + + + /* * Get the IP address of the authentication server * Then, open a socket, and bind it to a port @@ -1176,6 +1198,9 @@ goto error; } + if (a_reply->length < 2 || a_state->length < 2) + goto error; + memcpy(challenge, a_reply->data, a_reply->length - 2); challenge[a_reply->length - 2] = 0; --- ./pam_radius_auth.h 2007-03-12 10:18:11.000000000 -0600 +++ ./libpam-radius-auth-1.3.16/pam_radius_auth.h 2007-03-13 13:44:09.000000000 -0600 @@ -51,6 +51,7 @@ int accounting_bug; int sockfd; int debug; + int ruser; } radius_conf_t; @@ -82,6 +83,7 @@ #define PAM_SKIP_PASSWD 2 #define PAM_USE_FIRST_PASS 4 #define PAM_TRY_FIRST_PASS 8 +#define PAM_RUSER_ARG 16 #define PAM_RETRY 0x30