[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