[RFC][PATCH] Detect and handle PAM changing user name

James R. Leu jleu at inoc.com
Wed May 30 02:32:57 EST 2007


On Fri, May 25, 2007 at 08:24:13AM +1000, Darren Tucker wrote:
> James R. Leu wrote:
> > I've implemented a patch to openssh which allows the PAM auth layer
> > to detect if the PAM stack has changed the user name and then adjusts
> > its internal data structures accordingly.  (imagine a PAM stack that
> > uses individual credentials to authenticate, but assigns the user to
> > a role account).
> > 
> > First, is the openssh community interested in this patch?
> 
> Maybe.  I'm not convinced it's the right thing to do, though.

I'm re-posting an updated patch.  This one has a run-time option
to enable the patched behavior: PermitPAMUserChange

> > Second, if there is interest in the patch, how do I go about
> > submitting the patch for formal review?
> 
> Attach it to http://bugzilla.mindrot.org/show_bug.cgi?id=1215, but from
> a brief look it appears your patch is a subset of the one already there
> (which also handles the case where the user doesn't exist on the system,
> normally this would get the login marked as invalid).

I would agree that the functionality I've implemented is a subset
of one of these patches.

> > Third, regardless of interest by the openssh community, is there
> > anyone willing to review this code for me?
> > 
> > PS I've tested the code path going through sshpam_auth_passwd(),
> > but do know how to test the code path that goes through sshpam_thread().
> 
> Use ChallengeResponseAuthentication.

Thank you.  I tested with this and my code does not work in this mode.
I theorize it is because any changes made in sshpam_thread are not seen
by the rest of sshd.  I think I need some additional assistance from
someone with more knowledge of the monitor code.  First, I need to know
if my theory s correct.  If so, where and how would the correct change
be make (someplace in monitor_child_postauth or monitor_sync?)

For now I've attached my patch to bugzilla 1215

> -- 
> Darren Tucker (dtucker at zip.com.au)
> GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4  37C9 C982 80C7 8FF4 FA69
>     Good judgement comes with experience. Unfortunately, the experience
> usually comes from bad judgement.

-- 
James R. Leu
jleu at inoc.com
INOC -> http://inoc.com/
DELIVERING UPTIME
-------------- next part --------------
diff -uNr openssh-4.6p1/auth-pam.c openssh-4.6p1.jleu2/auth-pam.c
--- openssh-4.6p1/auth-pam.c	2006-09-16 20:57:47.000000000 -0500
+++ openssh-4.6p1.jleu2/auth-pam.c	2007-05-29 11:12:45.000000000 -0500
@@ -334,6 +334,40 @@
 #endif
 }
 
+static
+int sshpam_handle_user_change(pam_handle_t *sshpam_handle, Authctxt *authctxt)
+{
+	const char *pam_user;
+	const char **ptr_pam_user = &pam_user;
+
+	error("PAM: sshpam_handle_user_change enter");
+
+        if (pam_get_item(sshpam_handle, PAM_USER,
+                (sshpam_const void **)ptr_pam_user) != PAM_SUCCESS)
+                return PAM_AUTH_ERR;
+
+        if (strcmp(authctxt->user, pam_user)) {
+                char *user = strdup(pam_user);
+                struct passwd *pw;
+
+                if (!user)
+                	return PAM_AUTH_ERR;
+		
+                if (!(pw = getpwnamallow(user))) {
+                        free(user);
+                        return PAM_AUTH_ERR;
+		}
+
+                free(authctxt->pw);
+                authctxt->pw = pw;
+                free(authctxt->user);
+                authctxt->user = user;
+		error("PAM: sshpam_handle_user_change user changed to %s", user);
+        }
+	error("PAM: sshpam_handle_user_change exit");
+	return PAM_SUCCESS;
+}
+
 /*
  * Conversation function for authentication thread.
  */
@@ -469,6 +503,20 @@
 	if (sshpam_err != PAM_SUCCESS)
 		goto auth_fail;
 
+	if (options.permit_pam_user_change) {
+		/*
+		 * this should work, but it doesn't. The monitor hands
+		 * us a copy of the authctx and never copies the results
+		 * back to the _real_ authctx.  So the following call
+		 * does all the right stuff to sshpam_authctxt, but no
+		 * one is ever going to see it.
+		 */
+		sshpam_err = sshpam_handle_user_change(sshpam_handle,
+		    sshpam_authctxt);
+		if (sshpam_err != PAM_SUCCESS)
+			goto auth_fail;
+	}
+
 	if (compat20) {
 		if (!do_pam_account()) {
 			sshpam_err = PAM_ACCT_EXPIRED;
@@ -1206,15 +1254,25 @@
 
 	sshpam_err = pam_authenticate(sshpam_handle, flags);
 	sshpam_password = NULL;
-	if (sshpam_err == PAM_SUCCESS && authctxt->valid) {
-		debug("PAM: password authentication accepted for %.100s",
-		    authctxt->user);
-		return 1;
-	} else {
+	if (!(sshpam_err == PAM_SUCCESS && authctxt->valid)) {
 		debug("PAM: password authentication failed for %.100s: %s",
 		    authctxt->valid ? authctxt->user : "an illegal user",
 		    pam_strerror(sshpam_handle, sshpam_err));
 		return 0;
 	}
+
+	if (options.permit_pam_user_change) {
+		sshpam_err = sshpam_handle_user_change(sshpam_handle,
+		    sshpam_authctxt);
+		if (sshpam_err != PAM_SUCCESS) {
+			debug("PAM: failure checking for user change: %s",
+			    pam_strerror(sshpam_handle, sshpam_err));
+			return 0;
+		}
+	}
+
+	debug("PAM: password authentication accepted for %.100s",
+	    authctxt->user);
+	return 1;
 }
 #endif /* USE_PAM */
diff -uNr openssh-4.6p1/servconf.c openssh-4.6p1.jleu2/servconf.c
--- openssh-4.6p1/servconf.c	2007-03-01 04:31:29.000000000 -0600
+++ openssh-4.6p1.jleu2/servconf.c	2007-05-29 11:13:45.000000000 -0500
@@ -56,6 +56,7 @@
 
 	/* Portable-specific options */
 	options->use_pam = -1;
+	options->permit_pam_user_change = -1;
 
 	/* Standard Options */
 	options->num_ports = 0;
@@ -130,6 +131,8 @@
 	/* Portable-specific options */
 	if (options->use_pam == -1)
 		options->use_pam = 0;
+	if (options->permit_pam_user_change == -1)
+		options->permit_pam_user_change = 0;
 
 	/* Standard Options */
 	if (options->protocol == SSH_PROTO_UNKNOWN)
@@ -269,7 +272,7 @@
 typedef enum {
 	sBadOption,		/* == unknown option */
 	/* Portable-specific options */
-	sUsePAM,
+	sUsePAM, sPermitPAMUserChange,
 	/* Standard Options */
 	sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
 	sPermitRootLogin, sLogFacility, sLogLevel,
@@ -309,8 +312,10 @@
 	/* Portable-specific options */
 #ifdef USE_PAM
 	{ "usepam", sUsePAM, SSHCFG_GLOBAL },
+	{ "permitpamuserchange", sPermitPAMUserChange, SSHCFG_GLOBAL }
 #else
 	{ "usepam", sUnsupported, SSHCFG_GLOBAL },
+	{ "permitpamuserchange", sUnsupported, SSHCFG_GLOBAL }
 #endif
 	{ "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
 	/* Standard Options */
@@ -662,6 +667,10 @@
 		intptr = &options->use_pam;
 		goto parse_flag;
 
+	case sPermitPAMUserChange:
+		intptr = &options->permit_pam_user_change;
+		goto parse_flag;
+
 	/* Standard Options */
 	case sBadOption:
 		return -1;
diff -uNr openssh-4.6p1/servconf.h openssh-4.6p1.jleu2/servconf.h
--- openssh-4.6p1/servconf.h	2007-02-19 05:25:38.000000000 -0600
+++ openssh-4.6p1.jleu2/servconf.h	2007-05-29 11:12:45.000000000 -0500
@@ -137,6 +137,7 @@
 	char   *adm_forced_command;
 
 	int	use_pam;		/* Enable auth via PAM */
+	int	permit_pam_user_change;	/* Allow PAM to change user name */
 
 	int	permit_tun;
 
diff -uNr openssh-4.6p1/sshd_config openssh-4.6p1.jleu2/sshd_config
--- openssh-4.6p1/sshd_config	2006-07-23 23:06:47.000000000 -0500
+++ openssh-4.6p1.jleu2/sshd_config	2007-05-29 11:14:36.000000000 -0500
@@ -80,6 +80,10 @@
 # and ChallengeResponseAuthentication to 'no'.
 #UsePAM no
 
+# Set to 'yes' to allow the PAM stack to change the user name during
+# calls to authentication
+#PermitPAMUserChange no
+
 #AllowTcpForwarding yes
 #GatewayPorts no
 #X11Forwarding no
diff -uNr openssh-4.6p1/sshd_config.5 openssh-4.6p1.jleu2/sshd_config.5
--- openssh-4.6p1/sshd_config.5	2007-03-06 04:21:18.000000000 -0600
+++ openssh-4.6p1.jleu2/sshd_config.5	2007-05-29 11:12:45.000000000 -0500
@@ -820,6 +820,12 @@
 as a non-root user.
 The default is
 .Dq no .
+.It Cm PermitPAMUserChange
+If set to
+.Dq yes
+this will enable PAM authentication to change the name of the user being
+authenticated.  The default is
+.Dq no .
 .It Cm UsePrivilegeSeparation
 Specifies whether
 .Xr sshd 8
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.mindrot.org/pipermail/openssh-unix-dev/attachments/20070529/9a371ed2/attachment-0001.bin 


More information about the openssh-unix-dev mailing list