Lightdm does not allow to change an expired password with pam_winbind

Bug #869501 reported by renbag
30
This bug affects 6 people
Affects Status Importance Assigned to Milestone
Light Display Manager
New
Medium
Unassigned
lightdm (Debian)
Fix Released
Unknown

Bug Description

Using oneiric in a workstation joined to an AD domain, I have found that when the password of domain user is expired, lightdm does not present the correct steps to change the password.
Here is what happens (lightdm messages are inside ""):

1 - ******** (first enter expired password);
2 - "(current) NT password" --> ******** (expired password)
3 - "Retype new NT password" --> ******** (new password)
4 - "Invalid password, please try again"

There is a step missing between 2 and 3, and it should be "Enter new NT password".
Also lightdm should display, before step 2, a message saying that the password is expired and need to be changed.

Using su in a text console to login, the correct password changing dialog is presented:

renzo@vmo-amb20:~$ su rbag
Password:
You need to change your password now
Changing password for rbag
(current) NT password:
Enter new NT password:
Retype new NT password:
rbag@vmo-amb20:/home/renzo$

Also reported in comments #5 of Bug #856269, but had no feedback...

Revision history for this message
renbag (renbag) wrote :
Changed in lightdm:
importance: Undecided → Medium
Revision history for this message
renbag (renbag) wrote :

I tried to reproduce the bug in precise, with latest updates (lightdm 1.1.9-0ubuntu1) and found this:

First of all, the unity-greeter does not have anymore an entry to allow login for "other" users than local ones. Since winbind domain users are not listed in /etc/passwd, the only possibility to login for such users is to manually add them to this file, after having obtained the data with "getent passwd".

Then, if I try to login as a domain user with the default PAM configuration set up by the various PAM modules, I obtain this:

1 - ******** (first enter expired password);
2 - "You need to change your password now"
    "Enter new Unix password" --> ******** (new password)
3 - "Retype new Unix password" --> ******** (new password)
4 - (login performed, but NT password is not changed)
5 - Subsequent logins are allowed with old NT expired password
    (without asking to change it) or with new Unix password

[In this case the content of /etc/pam.d/common-password is this:
password [success=2 default=ignore] pam_unix.so obscure sha512
password [success=1 default=ignore] pam_winbind.so use_authtok try_first_pass
... ]

If I reverse the order of pam_unix.so and pam_winbind.so, I obtain this:

1 - ******** (first enter expired password);
2 - "You need to change your password now"
    "(current) NT password" --> ******** (expired password)
3 - "Enter new Unix password" --> ******** (new password)
4 - "Retype new Unix password" --> ******** (new password)
5 - "Invalid password, please try again"

[ In this case the content of /etc/pam.d/common-password is this:
password [success=2 default=ignore] pam_winbind.so use_authtok
password [success=1 default=ignore] pam_unix.so obscure sha512 try_first_pass
... ]

Revision history for this message
renbag (renbag) wrote :

To complete the previous post: the GDM logins of previous versions of ubuntu never asked for Unix passwords (with the described pam, samba and winbind configurations), as they are not needed for domain users.

Revision history for this message
Yves-Alexis Perez (corsac) wrote :

It seems that a Debian user has the same issue with LDAP passwords. Adding PAM_CHANGE_EXPIRED_AUTHTOK to the pam_chauthtok() calls seems to fix the issue for him, although I'm not sure about the side effects.

Renzo: could you try?

Robert, could you comment on that?

Changed in lightdm (Debian):
status: Unknown → Confirmed
Revision history for this message
renbag (renbag) wrote :
Download full text (4.7 KiB)

I don't see anymore this bug in ubuntu 14.04.
I tried, in an up to date virtual machine running trusty and joined to an active directory domain, to change an expired password and I was able to do it correctly, either with the original lightdm package (lightdm 1.9.5-0ubuntu1) and either with a recompiled lightdm with PAM_CHANGE_EXPIRED_AUTHTOK in the pam_chauthtok().

auth.log

Jan 20 14:39:08 vmt-amb20 lightdm: pam_succeed_if(lightdm:auth): requirement "user ingroup nopasswdlogin" not met by user "domainuser1"
Jan 20 14:39:14 vmt-amb20 lightdm: pam_krb5(lightdm:auth): authentication failure; logname=domainuser1 uid=0 euid=0 tty=:0 ruser= rhost=
Jan 20 14:39:14 vmt-amb20 lightdm: pam_unix(lightdm:auth): authentication failure; logname= uid=0 euid=0 tty=:0 ruser= rhost= user=domainuser1
Jan 20 14:39:14 vmt-amb20 lightdm: pam_winbind(lightdm:auth): getting password (0x00000388)
Jan 20 14:39:14 vmt-amb20 lightdm: pam_winbind(lightdm:auth): pam_get_item returned a password
Jan 20 14:39:14 vmt-amb20 lightdm: pam_winbind(lightdm:auth): request wbcLogonUser failed: WBC_ERR_AUTH_ERROR, PAM error: PAM_AUTH_ERR (7), NTSTATUS: NT_STATUS_LOGON_FAILURE, Error message was: Logon failure
Jan 20 14:39:14 vmt-amb20 lightdm: pam_winbind(lightdm:auth): user 'domainuser1' denied access (incorrect password or invalid membership)
Jan 20 14:39:25 vmt-amb20 lightdm: pam_succeed_if(lightdm:auth): requirement "user ingroup nopasswdlogin" not met by user "domainuser1"
Jan 20 14:39:45 vmt-amb20 lightdm: pam_krb5(lightdm:auth): user domainuser1 authenticated as <email address hidden>
Jan 20 14:39:46 vmt-amb20 lightdm: pam_unix(lightdm-greeter:session): session closed for user lightdm
Jan 20 14:39:46 vmt-amb20 lightdm: pam_unix(lightdm:session): session opened for user domainuser1 by (uid=0)
Jan 20 14:39:46 vmt-amb20 systemd-logind[524]: New session c6 of user domainuser1.

lightdm.log

[+52.51s] DEBUG: Session: Setting XDG_VTNR=7
[+52.52s] DEBUG: Session pid=2962: Started with service 'lightdm', username '(null)'
[+52.52s] DEBUG: Session pid=2960: Terminated with signal 15
[+52.52s] DEBUG: Session: Failed during authentication
[+52.52s] DEBUG: Seat: Session stopped
[+52.54s] DEBUG: Session pid=2962: Got 1 message(s) from PAM
[+52.54s] DEBUG: Session pid=2887: Prompt greeter with 1 message(s)
[+212.49s] DEBUG: Session pid=2887: Continue authentication
[+212.50s] DEBUG: Session pid=2962: Got 1 message(s) from PAM
[+212.50s] DEBUG: Session pid=2887: Prompt greeter with 1 message(s)
[+218.44s] DEBUG: Session pid=2887: Continue authentication
[+220.74s] DEBUG: Session pid=2962: Authentication complete with return value 7: Authentication failure
[+220.74s] DEBUG: Session pid=2887: Authenticate result for user domainuser1: Authentication failure
[+220.75s] DEBUG: Session pid=2962: Exited with return value 1
[+220.75s] DEBUG: Seat: Session stopped
[+220.75s] DEBUG: Session pid=2887: Greeter start authentication
[+220.75s] CRITICAL: Source ID 42 was not found when attempting to remove it
[+220.75s] DEBUG: Seat: Setting XDG_SEAT=seat0
[+220.75s] DEBUG: Session: Setting XDG_VTNR=7
[+220.75s] DEBUG: Session pid=4122: Started with service 'lightdm', username '(null)'
[+220.77s] DEBU...

Read more...

Revision history for this message
Giulio Turetta (giulio-9) wrote :
Download full text (3.3 KiB)

Hello,
as suggested by Yves-Alexis I report here further informations about the missing PAM_CHANGE_EXPIRED_AUTHTOK flag.
I have spent my day on reading the PAM code after we found a problem during the test phase of our LDAP authentication environment. Initially we've fixed our lightdm package and filled a Debian/Ubuntu bug (#735670/#869501, please note that #869501 is actually a private issue, so maybe you can't read it).

Today I have spent the morning looking about the implications of this missing flag in the lightdm code.

The PAM_CHANGE_EXPIRED_AUTHTOK flag involvs many pam modules.
I'm going to trace down and prepare a report about this.

What is more interesting is that the standard Debian pam package is involved!

~/dev/pam/pam-1.1.3$ grep -r PAM_CHANGE_EXPIRED_AUTHTOK * | grep modules
modules/pam_stress/pam_stress.c: && (flags & PAM_CHANGE_EXPIRED_AUTHTOK)
modules/pam_unix/support.c: if (getuid() == 0 && !(flags & PAM_CHANGE_EXPIRED_AUTHTOK)) {
modules/pam_cracklib/pam_cracklib.c: if (getuid() || (flags & PAM_CHANGE_EXPIRED_AUTHTOK))
modules/pam_cracklib/pam_cracklib.c: if (getuid() || (flags & PAM_CHANGE_EXPIRED_AUTHTOK))

Above all it involves the pam_unix module which is the STANDARD/DEFAULT pam module!

What does it matter?

For example for pam_unix the missing PAM_CHANGE_EXPIRED_AUTHTOK flag in the lightdm code
causes the activation of another pam flag (UNIX__IAMROOT [1]) which causes unexpected behaviours [2].

You can verify this on Wheezy (and probably on Ubuntu):

1) install lightdm
2) create a new test user (call it "giulio", set password "giulio")
# adduser giulio
3) login with giulio and try to change the account password
giulio$ passwd
try to use the password "t", it fails because it's too short
try to use the password "turetta", it fails because it's too simple
password change succeeds only with an (almost) secret password like
"tuREtt4"
3) now expire giulio's password
# chage -d 0 giulio
4) try to login by lightdm, current password is "tuREtt4"
5) login succeeds but you will be asked to insert a new password, insert "t"
6) giulio's password is now "t"! Ouch!!!!
7) now, expire the password again and try to change it to "a" by a login
with gdm3 (ssh, console, ...): the right policies will be enforced

Note, about pam_unix, that this bug also breaks the "remember" pam_unix
policy and the "obscure" policy.

I think that this bug probably impacts most of the pam modules and so it
must be considered an important security issue (security policies are
not enforced).

I'm performing further checks...

[1] from Wheezy pam source: /pam-1.1.3/modules/pam_unix/support.c:68
if (getuid() == 0 && !(flags & PAM_CHANGE_EXPIRED_AUTHTOK)) {
  D(("IAMROOT"));
  set(UNIX__IAMROOT, ctrl);
}

[2] from Wheezy pam source:
/pam-1.1.3/modules/pam_unix/pam_unix_passwd.c:491
if (off(UNIX__IAMROOT, ctrl)) {
  if (strlen(pass_new) < pass_min_len)
    remark = _("You must choose a longer password");
  D(("length check [%s]", remark));
  if (on(UNIX_REMEMBER_PASSWD, ctrl)) {
    if ((retval = check_old_password(user, pass_new)) == PAM_AUTHTOK_ERR)
      remark = _("Password has been already used. Choose another.");
    if (retval == PAM_A...

Read more...

Revision history for this message
Giulio Turetta (giulio-9) wrote :
Download full text (3.2 KiB)

Please note that in the examples of PAM src the PAM_CHANGE_EXPIRED_AUTHOK flag is always used after the check about the expired password (PAM_NEW_AUTHTOK_REQD):

pam-1.1.3$ grep -n4 -r PAM_CHANGE_EXPIRED_AUTHTOK examples/
examples/xsh.c-105- bail_out(pamh,0,retcode,"pam_acct_mgmt");
examples/xsh.c-106-
examples/xsh.c-107- if (retcode == PAM_NEW_AUTHTOK_REQD) {
examples/xsh.c-108- fprintf(stderr,"Application must request new password...\n");
examples/xsh.c:109: retcode = pam_chauthtok(pamh,PAM_CHANGE_EXPIRED_AUTHTOK);
examples/xsh.c-110- bail_out(pamh,0,retcode,"pam_chauthtok");
examples/xsh.c-111- }
examples/xsh.c-112-
examples/xsh.c-113- if (retcode != PAM_SUCCESS) {
--
examples/blank.c-101- bail_out(pamh,0,retcode,"pam_acct_mgmt");
examples/blank.c-102-
examples/blank.c-103- if (retcode == PAM_NEW_AUTHTOK_REQD) {
examples/blank.c-104- fprintf(stderr,"Application must request new password...\n");
examples/blank.c:105: retcode = pam_chauthtok(pamh,PAM_CHANGE_EXPIRED_AUTHTOK);
examples/blank.c-106- bail_out(pamh,0,retcode,"pam_chauthtok");
examples/blank.c-107- }
examples/blank.c-108-
examples/blank.c-109- if (retcode != PAM_SUCCESS) {

The same happens with gdm3...

gdm3-3.4.1$ grep -n4 -r PAM_CHANGE_EXPIRED_AUTHTOK *
daemon/gdm-session-worker.c-1287-
daemon/gdm-session-worker.c-1288- /* it's possible that the user needs to change their password or pin code
daemon/gdm-session-worker.c-1289- */
daemon/gdm-session-worker.c-1290- if (error_code == PAM_NEW_AUTHTOK_REQD && !worker->priv->is_program_session) {
daemon/gdm-session-worker.c:1291: error_code = pam_chauthtok (worker->priv->pam_handle, PAM_CHANGE_EXPIRED_AUTHTOK);
daemon/gdm-session-worker.c-1292-
daemon/gdm-session-worker.c-1293- gdm_session_worker_get_username (worker, NULL);
daemon/gdm-session-worker.c-1294-
daemon/gdm-session-worker.c-1295- if (error_code != PAM_SUCCESS) {

...and passwd:

shadow-4.1.5.1$ grep -n4 -r PAM_CHANGE_EXPIRED_AUTHTOK *
libmisc/pam_pass.c-54-
libmisc/pam_pass.c-55- if (silent)
libmisc/pam_pass.c-56- flags |= PAM_SILENT;
libmisc/pam_pass.c-57- if (change_expired)
libmisc/pam_pass.c:58: flags |= PAM_CHANGE_EXPIRED_AUTHTOK;
libmisc/pam_pass.c-59-
libmisc/pam_pass.c-60- ret = pam_start ("passwd", user, &conv, &pamh);
libmisc/pam_pass.c-61- if (ret != PAM_SUCCESS) {
libmisc/pam_pass.c-62- fprintf (stderr,
--
src/su.c-436- fprintf (stderr,
src/su.c-437- _("%s: %s\n(Ignored)\n"),
src/su.c-438- Prog, pam_strerror (pamh, ret));
src/su.c-439- } else if (PAM_NEW_AUTHTOK_REQD == ret) {
src/su.c:440: ret = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
src/su.c-441- if (PAM_SUCCESS != ret) {
src/su.c-442- SYSLOG ((LOG_ERR, "pam_chauthtok: %s",
src/su.c-443- pam_strerror (pamh, ret)));
src/su.c-444- fprintf (stderr,
--
src/login.c-857-
src/login.c-858- /* Check the account validity */
src/login.c-859- retcode = pam_acct_mgmt (pamh, 0);
src/login.c-860- if (retcode == PAM_NEW_AUTHTOK_REQD) {
src/login.c:861: retcode = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
src/login.c-862- }
src/login.c...

Read more...

Revision history for this message
Steve Langasek (vorlon) wrote : Re: [Pkg-xfce-devel] Bug#735670: lightdm ask ldap administrator password when changing a password expired

On Mon, Jan 27, 2014 at 08:55:05PM +0100, Yves-Alexis Perez wrote:

> > Steve about the man page:
> > > Well, this information from the manpage authoritatively describes how the
> > > flag is meant to be used: if pam_chauthtok() is being called to request
> > > changing expired tokens, the flag is expected to be passed.

> That's not what it says:

> PAM_CHANGE_EXPIRED_AUTHTOK
> This argument indicates to the modules that the users
> authentication token (password) should only be changed if it has
> expired. If this argument is not passed, the application requires
> that all authentication tokens are to be changed.

> I'm not a native speaker, but I parse as “if it's passed, the password
> won't be changed if it has expired” and “if it's not passed, all the
> authentication tokens should be changed”. Nothing relevant to the
> superuser is given here, and nothing says flag must be passed in order
> to change expired password.

> So maybe it should be rephrased to more precisely describe what it does?

I don't think there's anything imprecise here. It says nothing about the
superuser because that's not part of the spec; it's a side effect of the
application misusing the API.

If an application is enforcing a password change policy on the user by
forcing expired passwords to be reset, you must be passing
PAM_CHANGE_EXPIRED_AUTHTOK. The application should not be calling
pam_chauthtok() *without* PAM_CHANGE_EXPIRED_AUTHTOK unless there's a
user-initiated request for changing the password. It's just wrong for the
application to insist all un-expired authentication tokens be changed just
because one authentication token is expired.

--
Steve Langasek Give me a lever long enough and a Free OS
Debian Developer to set it on, and I can move the world.
Ubuntu Developer http://www.debian.org/
<email address hidden> <email address hidden>

Changed in lightdm (Debian):
status: Confirmed → Fix Released
Revision history for this message
Rémi Verschelde (rverschelde) wrote :

Testing the lightdm 1.8.7 update candidate for Mageia 4 (following the procedure in comment #6), I ran into a potential regression, as explained here: https://bugs.mageia.org/show_bug.cgi?id=12670#c3

With lightdm 1.8.6, the procedure to set a new password when the old expires is:
1. Type in your old password
2. Lightdm displays: "You are required to change your password immediately."
3. Type in your new password
4. It is changed without confirmation, and you can now type in the new password to log in

This poses security issues as discussed in this topic, but now here is the procedure with lightdm 1.8.7 (French locale, if it's relevant):
1. Type in your old password, validate.
2. Lightdm displays (in French): "Change password for $user."
  2.1 Type in a new (strong) password, validate. Lightdm answers: "Incorrect password, please try again"
  2.2 Start again with 1., then guess (!) that you have to type in your former password a second time! (though the message is "Change password for $user.") Validate.
3. Lightdm shows nothing. Type in your new (strong) password, validate.
4. Lightdm still shows nothing. Type in your new (strong) password again, validate. You're now logging in.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.