Mailing List Archive

grace logins on solaris
We just started using NDS for Solaris to authenticate users on our SOlaris
2.6 boxes. Works great with OpenSSH except for one thing. When a user's
password is expired, sshd won't allow them access, while telnetd reports
the number of grace logins left, and asks to change the user's password.
Seems to be an interaction with the PAM account module, but I'm not
familiar enough with any of the code/APIs to say much more. Any ideas on
getting this implemented?

-Chip
Re: grace logins on solaris [ In reply to ]
When I run sshd -d and connect using an expired login, this is what I get:

debug: Server will not fork when running in debugging mode.
Connection from 192.168.12.2 port 901
debug: Client protocol version 1.5; client software version OpenSSH-2.1
debug: Local version string SSH-1.99-OpenSSH-2.1
debug: Sent 768 bit public key and 1024 bit host key.
debug: Encryption type: 3des
debug: Received session key; encryption turned on.
debug: Installing crc compensation attack detector.
debug: Starting up PAM with username "chip"
debug: Attempting authentication for chip.
Failed rsa for chip from 192.168.12.2 port 901
debug: Adding PAM message: Your password has expired and you have 4 grace login(s).
debug: PAM Password authentication accepted for user "chip"
Accepted password for chip from 192.168.12.2 port 901
debug: PAM setting rhost to "fleck.princetonecom.com"
May 26 12:39:38 piglet.princetonecom.com sshd[8029]: PAM_NDS : Password expired.
PAM rejected by account configuration: Get new authentication token
Faking authloop for illegal user chip from 192.168.12.2 port 901

pam_acct_mgmt is returning PAM_NEW_AUTHTOK_REQD. Is there BSD licensed
code out there already to deal with asking users to change an expired
password?

> We just started using NDS for Solaris to authenticate users on our SOlaris
> 2.6 boxes. Works great with OpenSSH except for one thing. When a user's
> password is expired, sshd won't allow them access, while telnetd reports
> the number of grace logins left, and asks to change the user's password.
> Seems to be an interaction with the PAM account module, but I'm not
> familiar enough with any of the code/APIs to say much more. Any ideas on
> getting this implemented?
Re: grace logins on solaris [ In reply to ]
On Fri, 26 May 2000, Chip Christian wrote:

> May 26 12:39:38 piglet.princetonecom.com sshd[8029]: PAM_NDS : Password
> expired.
> PAM rejected by account configuration: Get new authentication token
> Faking authloop for illegal user chip from 192.168.12.2 port 901
>
> pam_acct_mgmt is returning PAM_NEW_AUTHTOK_REQD. Is there BSD
> licensed code out there already to deal with asking users to change
> an expired password?

In the absence of this, would allowing access (and displaying a
suitable warning) when PAM returns PAM_NEW_AUTHTOK_REQD be acceptable?

At least the users could change their passwords themselves.

-d

--
| "Bombay is 250ms from New York in the new world order" - Alan Cox
| Damien Miller - http://www.mindrot.org/
| Email: djm@mindrot.org (home) -or- djm@ibs.com.au (work)
Re: grace logins on solaris [ In reply to ]
That's a step in the right direction, sure. I'll test, but I assume when
grace logins are exhausted, pam_acct_mgmt returns something else.

Can this string (found from a -d invocation) also be displayed in this case?

debug: Adding PAM message: \
Your password has expired and you have 4 grace login(s).

At some point I might find the free time to craft up the code for the
other case...

> On Fri, 26 May 2000, Chip Christian wrote:
>
> > May 26 12:39:38 piglet.princetonecom.com sshd[8029]: PAM_NDS : Password
> > expired.
> > PAM rejected by account configuration: Get new authentication token
> > Faking authloop for illegal user chip from 192.168.12.2 port 901
> >
> > pam_acct_mgmt is returning PAM_NEW_AUTHTOK_REQD. Is there BSD
> > licensed code out there already to deal with asking users to change
> > an expired password?
>
> In the absence of this, would allowing access (and displaying a
> suitable warning) when PAM returns PAM_NEW_AUTHTOK_REQD be acceptable?
>
> At least the users could change their passwords themselves.
>
> -d
>
> --
> | "Bombay is 250ms from New York in the new world order" - Alan Cox
> | Damien Miller - http://www.mindrot.org/
> | Email: djm@mindrot.org (home) -or- djm@ibs.com.au (work)
>
>
>
>
>
Re: grace logins on solaris [ In reply to ]
On Tue, 30 May 2000, Chip Christian wrote:

> That's a step in the right direction, sure. I'll test, but I assume when
> grace logins are exhausted, pam_acct_mgmt returns something else.
>
> Can this string (found from a -d invocation) also be displayed in this case?
>
> debug: Adding PAM message: \
> Your password has expired and you have 4 grace login(s).
>
> At some point I might find the free time to craft up the code for the
> other case...

Hmmm, that message should have been displayed.

Can you try this patch:

Index: auth-pam.c
===================================================================
RCS file: /var/cvs/openssh/auth-pam.c,v
retrieving revision 1.4
diff -u -r1.4 auth-pam.c
--- auth-pam.c 2000/04/29 14:47:29 1.4
+++ auth-pam.c 2000/05/30 23:52:46
@@ -15,10 +15,14 @@

RCSID("$Id: auth-pam.c,v 1.4 2000/04/29 14:47:29 damien Exp $");

+#define NEW_AUTHTOK_MSG \
+ "Warning: You password has expired, please change it now"
+
/* Callbacks */
static int pamconv(int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr);
void pam_cleanup_proc(void *context);
+void pam_msg_cat(const char *msg);

/* module-local variables */
static struct pam_conv conv = {
@@ -27,7 +31,7 @@
};
static struct pam_handle_t *pamh = NULL;
static const char *pampasswd = NULL;
-static char *pamconv_msg = NULL;
+static char *pam_msg = NULL;

/* PAM conversation function. This is really a kludge to get the password */
/* into PAM and to pick up any messages generated by PAM into pamconv_msg */
@@ -36,8 +40,6 @@
{
struct pam_response *reply;
int count;
- size_t msg_len;
- char *p;

/* PAM will free this later */
reply = malloc(num_msg * sizeof(*reply));
@@ -54,31 +56,14 @@
reply[count].resp_retcode = PAM_SUCCESS;
reply[count].resp = xstrdup(pampasswd);
break;
-
case PAM_TEXT_INFO:
reply[count].resp_retcode = PAM_SUCCESS;
reply[count].resp = xstrdup("");

- if (msg[count]->msg == NULL)
- break;
+ if (msg[count]->msg != NULL)
+ pam_msg_cat(msg[count]->msg);

- debug("Adding PAM message: %s", msg[count]->msg);
-
- msg_len = strlen(msg[count]->msg);
- if (pamconv_msg) {
- size_t n = strlen(pamconv_msg);
- pamconv_msg = xrealloc(pamconv_msg, n + msg_len + 2);
- p = pamconv_msg + n;
- } else {
- pamconv_msg = p = xmalloc(msg_len + 2);
- }
- memcpy(p, msg[count]->msg, msg_len);
- p[msg_len] = '\n';
- p[msg_len + 1] = '\0';
break;
-
- case PAM_PROMPT_ECHO_ON:
- case PAM_ERROR_MSG:
default:
free(reply);
return PAM_CONV_ERR;
@@ -100,19 +85,19 @@
pam_retval = pam_close_session((pam_handle_t *)pamh, 0);
if (pam_retval != PAM_SUCCESS) {
log("Cannot close PAM session: %.200s",
- PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
+ PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
}

pam_retval = pam_setcred((pam_handle_t *)pamh, PAM_DELETE_CRED);
if (pam_retval != PAM_SUCCESS) {
log("Cannot delete credentials: %.200s",
- PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
+ PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
}

pam_retval = pam_end((pam_handle_t *)pamh, pam_retval);
if (pam_retval != PAM_SUCCESS) {
log("Cannot release PAM authentication: %.200s",
- PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
+ PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
}
}
}
@@ -135,7 +120,8 @@

pam_retval = pam_authenticate((pam_handle_t *)pamh, 0);
if (pam_retval == PAM_SUCCESS) {
- debug("PAM Password authentication accepted for user \"%.100s\"", pw->pw_name);
+ debug("PAM Password authentication accepted for user \"%.100s\"",
+ pw->pw_name);
return 1;
} else {
debug("PAM Password authentication for \"%.100s\" failed: %s",
@@ -148,26 +134,36 @@
int do_pam_account(char *username, char *remote_user)
{
int pam_retval;
-
+
debug("PAM setting rhost to \"%.200s\"", get_canonical_hostname());
pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_RHOST,
get_canonical_hostname());
if (pam_retval != PAM_SUCCESS) {
- fatal("PAM set rhost failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
+ fatal("PAM set rhost failed: %.200s",
+ PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
}

if (remote_user != NULL) {
debug("PAM setting ruser to \"%.200s\"", remote_user);
pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_RUSER, remote_user);
if (pam_retval != PAM_SUCCESS) {
- fatal("PAM set ruser failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
+ fatal("PAM set ruser failed: %.200s",
+ PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
}
}

pam_retval = pam_acct_mgmt((pam_handle_t *)pamh, 0);
- if (pam_retval != PAM_SUCCESS) {
- log("PAM rejected by account configuration: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
- return(0);
+ switch (pam_retval) {
+ case PAM_SUCCESS:
+ /* This is what we want */
+ break;
+ case PAM_NEW_AUTHTOK_REQD:
+ pam_msg_cat(NEW_AUTHTOK_MSG);
+ break;
+ default:
+ log("PAM rejected by account configuration: %.200s",
+ PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
+ return(0);
}

return(1);
@@ -181,13 +177,17 @@
if (ttyname != NULL) {
debug("PAM setting tty to \"%.200s\"", ttyname);
pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_TTY, ttyname);
- if (pam_retval != PAM_SUCCESS)
- fatal("PAM set tty failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
+ if (pam_retval != PAM_SUCCESS) {
+ fatal("PAM set tty failed: %.200s",
+ PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
+ }
}

pam_retval = pam_open_session((pam_handle_t *)pamh, 0);
- if (pam_retval != PAM_SUCCESS)
- fatal("PAM session setup failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
+ if (pam_retval != PAM_SUCCESS) {
+ fatal("PAM session setup failed: %.200s",
+ PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
+ }
}

/* Set PAM credentials */
@@ -197,8 +197,10 @@

debug("PAM establishing creds");
pam_retval = pam_setcred((pam_handle_t *)pamh, PAM_ESTABLISH_CRED);
- if (pam_retval != PAM_SUCCESS)
- fatal("PAM setcred failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
+ if (pam_retval != PAM_SUCCESS) {
+ fatal("PAM setcred failed: %.200s",
+ PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
+ }
}

/* Cleanly shutdown PAM */
@@ -217,9 +219,12 @@

pam_retval = pam_start(SSHD_PAM_SERVICE, pw->pw_name, &conv,
(pam_handle_t**)&pamh);
- if (pam_retval != PAM_SUCCESS)
- fatal("PAM initialisation failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));

+ if (pam_retval != PAM_SUCCESS) {
+ fatal("PAM initialisation failed: %.200s",
+ PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
+ }
+
fatal_add_cleanup(&pam_cleanup_proc, NULL);
}

@@ -237,8 +242,30 @@
/* or account checking to stderr */
void print_pam_messages(void)
{
- if (pamconv_msg != NULL)
- fprintf(stderr, pamconv_msg);
+ if (pam_msg != NULL)
+ fprintf(stderr, pam_msg);
+}
+
+/* Append a message to the PAM message buffer */
+void pam_msg_cat(const char *msg)
+{
+ char *p;
+ size_t new_msg_len;
+ size_t pam_msg_len;
+
+ new_msg_len = strlen(msg);
+
+ if (pam_msg) {
+ pam_msg_len = strlen(pam_msg);
+ pam_msg = xrealloc(pam_msg, new_msg_len + pam_msg_len + 2);
+ p = pam_msg + pam_msg_len;
+ } else {
+ pam_msg = p = xmalloc(new_msg_len + 2);
+ }
+
+ memcpy(p, msg, new_msg_len);
+ p[new_msg_len] = '\n';
+ p[new_msg_len + 1] = '\0';
}

#endif /* USE_PAM */

--
| "Bombay is 250ms from New York in the new world order" - Alan Cox
| Damien Miller - http://www.mindrot.org/
| Email: djm@mindrot.org (home) -or- djm@ibs.com.au (work)
Re: grace logins on solaris [ In reply to ]
Now that do_pam_account() returns 1 when pam_acct_mgmt() returns
PAM_NEW_AUTH_TOK_REQD, the message *is* properly displayed.
So sorry to make you add the NEW_AUTHTOK_MSG crud.

The patch does work fine, of course.

djm@mindrot.org said:
> That's a step in the right direction, sure. I'll test, but I assume
> when
> grace logins are exhausted, pam_acct_mgmt returns something else.
>
> Can this string (found from a -d invocation) also be displayed in this
> case?
>
> debug: Adding PAM message: \
> Your password has expired and you have 4 grace login(s).
>
> At some point I might find the free time to craft up the code for the
> other case...

> Hmmm, that message should have been displayed.

> Can you try this patch: