Bug 638279

Summary: pam_unix's unix_chkpwd SUID helper is not used when nss_ldap returns "*" for password
Product: Red Hat Enterprise Linux 5 Reporter: ross tyler <retyler>
Component: nss_ldapAssignee: Nalin Dahyabhai <nalin>
Status: CLOSED WONTFIX QA Contact: BaseOS QE Security Team <qe-baseos-security>
Severity: high Docs Contact:
Priority: low    
Version: 5.4CC: dpal, jnansi, jplans, sgallagh, ssorce, tmraz
Target Milestone: rcKeywords: Reopened
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2011-02-01 21:38:21 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
patch for modules/pam_unix/support.c to fix the problem none

Description ross tyler 2010-09-28 16:28:04 UTC
Created attachment 450240 [details]
patch for modules/pam_unix/support.c to fix the problem

Description of problem:
The nss_ldap can be configured to extend, via the Name Service Switch (NSS), the passwd/shadow data normally found in /etc files to include posixAccount/shadowAccount objects in an LDAP directory.
Such a configuration should allow pam_unix to authenticate users defined in the LDAP directory.
The nss_ldap configuration allows for anonymous and privileged access to the directory.
Privileged access is extended to processes running as root using the rootbinddn specified in /etc/ldap.conf and password found in /etc/ldap.secret.
Anonymous access is given to all others.

PAM (pam_unix) authenticators running as root (e.g. gdm, sshd, mingetty logins) should have privileged rootbinddn nss_ldap access to posixAccount/shadowAccount attributes in the directory that would allow them to authenticate using the userPassword.
PAM (pam_unix) authenticators not running as root (e.g. gnome-screensaver-dialog) should not have privileged rootbinddn nss_ldap access.
Their anonymous access to the LDAP directory should preclude access to posixAccount/shadowAccount attributes as they have no access to /etc/{passwd,shadow}.
pam_unix should recognize this and spawn the SUID unix_chkpwd helper to try authentication as root.

Unfortunately, pam_unix does not properly recognize this access problem when  shadow data returned by getspam is fetched by nss_ldap as an anonymous user of the directory.
nss_ldap will return "*" as the password in such cases.
pam_unix should special case this "*" (as it does "x") and call its helper.

Version-Release number of selected component (if applicable):
pam-0.99.6.2-6.el5_4.1

How reproducible:
Every time.

Steps to Reproduce:
1. Configure nss_ldap as described above.
2. Configure PAM to insist that pam_unix must succeed for authentication.
3. Login as LDAP based user and use gnome-screensaver to lock the screen.
4. Find that you are unable to unlock the screen.
  
Actual results:
Screensaver cannot be unlocked with user's password.

Expected results:
Screensaver should be unlocked with user's password.

Additional info:
See patch attached.

Comment 1 Tomas Mraz 2010-09-29 07:21:51 UTC
This is not a bug and the behavior of pam_unix is right. The '*' in the user's passwd entry indicates the user does not have a password in the shadow file.

Comment 2 ross tyler 2010-09-29 13:31:46 UTC
No, this is a bug.
Please look at the code.

In the case described above, getpwnam returns "+" for the user's password.
This can be shown with "getent passwd $user".
This indicates, to the code, to look in the shadow "file".
The code calls getspnam to retrieve it.
When the account is nss_ldap based and the non-root authenticator, bound anonymously to the LDAP service, accesses the userPassword attribute it will be denied (which is as it should be - the non-root authenticator would not have access to /etc/shadow) and the nss_ldap code will return "*" for the user's password.
If the authenticator is root and nss_ldap is configured (/etc/ldap) with identity (rootbinddn) and credentials (/etc/ldap.secret) that give it read access to the userPassword attribute (which is as it should be - root would have access to /etc/shadow), the nss_ldap code will return the hashed userPassword value.
This can be shown with "getent shadow $user" (as root and as the unprivileged $user).

So, the way the code is written now, only root authenticators (e.g. gdm, sshd, mingetty-login) can authenticate nss_ldap users.
A non-root authenticator (e.g. gnome-screensaver-dialog) can not authenticate nss_ldap users.

Try it.

Comment 3 Tomas Mraz 2010-09-29 13:45:48 UTC
OK, but then it is a problem of nss_ldap.

Comment 4 Tomas Mraz 2010-09-29 13:50:27 UTC
pam_unix cannot know that it should call the helper when the shadow entry returned by the glibc call contains '*'.

I doubt nss_ldap can fix this though. I'd say that your configuration is incorrect and thus unsupported. You should use pam_ldap for authentication.

Comment 5 ross tyler 2010-09-29 18:25:55 UTC
This is not necessarily a problem with nss_ldap although this problem could be solved by returning "x" instead of "*".
I think it is better to accept/expect this nss_ldap behavior and fix it in pam_unix.

pam_unix can "know" whatever you tell it to.
I suggest that it "know" the truth: that is, when nss_ldap returns "*" for a shadow password that it means, effectively, "access denied".
Such access denial should be treated as it is in other cases by using a privileged helper program with elevated access.
If the privileged helper program fails then this would be a configuration problem.

My configuration is not incorrect and, thus, must be supported.
Actually, I do use pam_ldap as part of authentication but I must also use pam_unix to authenticate local users (e.g. root).
So, both pam_unix and pam_ldap are "required" parts of PAM "auth".
pam_ldap is configured to PAM_IGNORE users that are not in LDAP.

Please read the ignore_unknown_user section of the pam_ldap manual page which supports my position as a correct configuration.

Actually, use of pam_ldap as part of PAM authentication is not the issue at all.
Authentication should work with only pam_unix (see pam_ldap man page).
nss_ldap should/must provide everything that pam_unix needs to authenticate a UNIX user.
If it doesn't then it isn't federating the name services as it was designed / is expected to do.
I say nss_ldap does its part - pam_unix just needs to recognize what nss_ldap means by "*" for a shadow password.

Comment 6 ross tyler 2010-09-29 18:36:43 UTC
Also, note that in the pam_unix/support.c code, special consideration is taken for what appears to be a response from an NIS+ name service (password equals "*NP*").
Symmetry argues in favor of making similar accommodations for what appears to be a response from an LDAP name service (shadow password equals "*").
This is what my proposed patch does, quite simply.

Comment 7 Tomas Mraz 2010-09-29 19:20:43 UTC
That's nonsense, * in shadow simply means that the user has invalid password. There would have to be some new special value such as *LP* or so similar to the *NP* that could be recognized by pam_unix.

You can support your configuration with making both pam_ldap and pam_unix as 'sufficient' modules in the stack and that's the way authconfig configures the stack for you if you use it.

Comment 8 Tomas Mraz 2010-09-29 19:21:44 UTC
Also can you please open a support request with the regular support channels - http://www.redhat.com/support/ for your case?

Comment 9 ross tyler 2010-09-29 23:28:52 UTC
No, I cannot support my configuration by making both sufficient.
I know that authconfig configures it this way.
It took me a long time to figure out that authconfig does it wrong - for me.
I am using LDAP to store authentication failures with the slapo-ppolicy overlay.
I need for both of them to be "required" as documented in the pam_ldap man page in order for this to work.

Let's agree on a few things:

1. The user has a valid password and its value is properly hashed.
2. nss_ldap will present a privileged user (root) this hashed password.
3. nss_ldap will present an unprivileged user (non-root) "*" instead.
4. pam_unix cannot hash any password to match "*" so unprivileged authentication will fail.
5. this is a bug. nss_ldap and pam_unix need to agree on how to handle this.

Of these, I think that we might have a disagreement on how to do 5.

I think the easiest thing to do is for pam_unix to interpret a "*" returned by getpsnam as "nss_ldap might be telling me that access is denied" just as it interprets a getpwnam value of "*NP*" as "NIS+ is telling me something".
Both of these interpretations may be false.
For example, I might have either of these values in /etc/shadow and not be using LDAP or NIS+ at all.

So, what if these interpretations are wrong?
I can't speak for the NIS+ code but I see no downside to interpreting "*" as nss_ldap encodes it (access denied).
Having pam_unix try to hash the password to match "*" is futile as it will never happen.
Why not, in this case, have a helper try with elevated privileges that might work (nss_ldap really was denied access) or not (e.g. /etc/shadow had "*" as the hashed password value).

If you are suggesting that nss_ldap's encoding of "access denied" as "*" collides with some other encoded meaning so something different should be used, I have no problem with that.
It's just that the open source community will have to come to some agreement on what this new encoding is and both nss_ldap and pam_unix will have to be changed to use it.
I just don't think that its worth all that bother.
The fix is simple.

Comment 10 Tomas Mraz 2010-09-30 06:36:46 UTC
(In reply to comment #9)
> I just don't think that its worth all that bother.
> The fix is simple.
Nope, this is not a fix, this is a very ugly hack.

Comment 11 Dmitri Pal 2010-09-30 12:39:55 UTC
Have you considered using SSSD? I wonder if that would help you in this case. I know that SSSD had some heuristics around "X" & "*" so may be you will be more lucky there.

Comment 12 ross tyler 2010-09-30 13:24:41 UTC
(In reply to comment #9)
> No, I cannot support my configuration by making both sufficient.
> I know that authconfig configures it this way.
> It took me a long time to figure out that authconfig does it wrong - for me.
> I am using LDAP to store authentication failures with the slapo-ppolicy
> overlay.
> I need for both of them to be "required" as documented in the pam_ldap man page
> in order for this to work.
> 
> Let's agree on a few things:
> 
> 1. The user has a valid password and its value is properly hashed.
> 2. nss_ldap will present a privileged user (root) this hashed password.
> 3. nss_ldap will present an unprivileged user (non-root) "*" instead.
> 4. pam_unix cannot hash any password to match "*" so unprivileged
> authentication will fail.
> 5. this is a bug. nss_ldap and pam_unix need to agree on how to handle this.
> 
> Of these, I think that we might have a disagreement on how to do 5.
> 
> I think the easiest thing to do is for pam_unix to interpret a "*" returned by
> getpsnam as "nss_ldap might be telling me that access is denied" just as it
> interprets a getpwnam value of "*NP*" as "NIS+ is telling me something".
> Both of these interpretations may be false.
> For example, I might have either of these values in /etc/shadow and not be
> using LDAP or NIS+ at all.
> 
> So, what if these interpretations are wrong?
> I can't speak for the NIS+ code but I see no downside to interpreting "*" as
> nss_ldap encodes it (access denied).
> Having pam_unix try to hash the password to match "*" is futile as it will
> never happen.
> Why not, in this case, have a helper try with elevated privileges that might
> work (nss_ldap really was denied access) or not (e.g. /etc/shadow had "*" as
> the hashed password value).
> 
> If you are suggesting that nss_ldap's encoding of "access denied" as "*"
> collides with some other encoded meaning so something different should be used,
> I have no problem with that.
> It's just that the open source community will have to come to some agreement on
> what this new encoding is and both nss_ldap and pam_unix will have to be
> changed to use it.
> I just don't think that its worth all that bother.
> The fix is simple.

On second thought, for security purposes, nss_ldap should not report something different for "password not specified" and "password not accessible".
It is correct for nss_ldap to return the same thing ("*") in both cases in order that an unprivileged attacker not be able to benefit from knowing the difference.

Comment 13 ross tyler 2010-09-30 13:28:01 UTC
(In reply to comment #10)
> (In reply to comment #9)
> > I just don't think that its worth all that bother.
> > The fix is simple.
> Nope, this is not a fix, this is a very ugly hack.

Then please suggest and alternative.
As I mention in comment #12, I don't believe that nss_ldap should change it behavior for the benefit of pam_unix and to the detriment of security.
Therefore, pam_unix must change its behavior with the only clue that it has - "*".
What do you suggest?

Comment 14 ross tyler 2010-09-30 13:36:42 UTC
(In reply to comment #8)
> Also can you please open a support request with the regular support channels -
> http://www.redhat.com/support/ for your case?

https://access.redhat.com/support/cases/00350097

Comment 15 Tomas Mraz 2010-09-30 13:50:48 UTC
(In reply to comment #12)
> On second thought, for security purposes, nss_ldap should not report something
> different for "password not specified" and "password not accessible".
> It is correct for nss_ldap to return the same thing ("*") in both cases in
> order that an unprivileged attacker not be able to benefit from knowing the
> difference.

Not really, the nss_ldap runs in the user's context here and thus this "password not accessible" is not an information the user could not get by other means doing the same things nss_ldap does.

Comment 16 ross tyler 2010-09-30 17:47:23 UTC
(In reply to comment #15)
> Not really, the nss_ldap runs in the user's context here and thus this
> "password not accessible" is not an information the user could not get by other
> means doing the same things nss_ldap does.

You are right.

So, if not the simple fix, what do you suggest?
Inventing a new encoding for "access denied" that nss_ldap and pam_unix can agree on?

Comment 17 ross tyler 2010-09-30 18:25:43 UTC
(In reply to comment #16)
> (In reply to comment #15)
> > Not really, the nss_ldap runs in the user's context here and thus this
> > "password not accessible" is not an information the user could not get by other
> > means doing the same things nss_ldap does.
> 
> You are right.

An unprivileged user should not be able to know the difference between "no password" and "password not accessible" by any means (nss_ldap, ldapsearch, ...).
This is, in fact, the case in my openLDAP configuration.
So, nss_ldap should not be expected to be able to distinguish between "password not specified" and "password not accessible".
It could, however, always return something different than "*" on failure which pam_unix could key on.

Comment 18 Dmitri Pal 2010-09-30 18:39:29 UTC
Can you please try SSSD instead of nss_ldap and see if it addresses your needs? SSSD is a replacement for nss_ldap and pam_ldap or pam_krb5 so it has a lot of things hopefully done "right".

Comment 19 ross tyler 2010-09-30 19:04:14 UTC
(In reply to comment #18)
> Can you please try SSSD instead of nss_ldap and see if it addresses your needs?
> SSSD is a replacement for nss_ldap and pam_ldap or pam_krb5 so it has a lot of
> things hopefully done "right".

I wish I would have known about SSSD before I started down this road.
Unfortunately, I don't think schedule/configuration constraints will allow the change on my project.
I will spend a little bit of time looking at it though.
Thank you for bringing this to my attention.

Comment 20 Tomas Mraz 2010-09-30 19:36:45 UTC
Perhaps you could describe more exactly the reason why do you need to have both modules required? Can you please post your PAM stack configuration?

What if you configured the PAM stack this way:

auth sufficient pam_ldap.so ...
auth sufficient pam_unix.so use_first_pass ...

This way pam_ldap is always called for all users however pam_unix is called only for users that failed the authentication through pam_ldap.

Comment 21 ross tyler 2010-09-30 20:40:52 UTC
(In reply to comment #20)

> Perhaps you could describe more exactly the reason why do you need to have both
> modules required?

I need to have pam_unix authenticate users that are not defined in LDAP.
I need to have pam_ldap authenticate users that are defined in LDAP and apply implicit slapo-ppolicy constraints to the authentication (e.g. login failures).

> Can you please post your PAM stack configuration?

auth    required        pam_unix.so nullok try_first_pass
auth    sufficient      pam_succeed_if.so uid < 500 quiet
auth    required        pam_ldap.so use_first_pass ignore_unknown_user

> What if you configured the PAM stack this way:
>
> auth sufficient pam_ldap.so ...
> auth sufficient pam_unix.so use_first_pass ...

I suspect that it would work with some performance penalty.
Note that I avoid LDAP altogether if pam_unix determines the uid is < 500 (as does the default authconfig configuration).

The performance penalty is significant (especially on my slow virtual machines that I test with) as secure TLS communication must be setup.
I realize that I incur this penalty for all uses of nss_ldap (e.g. reverse uid -> name lookup on things like "ls -l") but would like to avoid where I can.

As mentioned in comment #19, I am interested in the client side caching and connection sharing features of SSSD to address this but I don't know if I will be allowed to.

All told, this is still a bug that should be addressed.
Currently, my workaround is my patch to pam_unix.
I prefer this workaround to any PAM reconfiguration.

Comment 22 Tomas Mraz 2010-10-01 06:24:12 UTC
I disagree that it is a real bug. Definitely not a bug on the pam_unix side as I insist on that '*' instead of password hash in shadow or passwd entry simply means disabled password.

The performance penalty for calling pam_ldap on uid<500 accounts can be easily avoided:

auth [success=1 default=ignore] pam_succeed_if.so uid < 500 quiet
auth sufficient pam_ldap.so ...
auth sufficient pam_unix.so use_first_pass ...
auth required pam_deny.so

Comment 23 ross tyler 2010-10-04 13:42:46 UTC
(In reply to comment #22)
> I disagree that it is a real bug.
Then we disagree.
I don't understand how you can defend your position.
The name service federation goal of NSS is intended to support such.
The ignore_unknown_user section of the pam_ldap man page clearly documents that this configuration is supported.
Whether you call it a bug in nss_ldap, pam_ldap or both doesn't matter to me.
As far as I am concerned, this is clearly a bug.
What kind of support is this?

> The performance penalty for calling pam_ldap on uid<500 accounts can be easily
> avoided:
>
> auth [success=1 default=ignore] pam_succeed_if.so uid < 500 quiet
> auth sufficient pam_ldap.so ...
> auth sufficient pam_unix.so use_first_pass ...
> auth required pam_deny.so

I don't think so.
As the first module on the stack, pam_succeed_if can't know what the numeric uid of the named user is.
This is a job for pam_unix (or pam_ldap) which comes later.

Comment 24 Tomas Mraz 2010-10-04 14:26:52 UTC
(In reply to comment #23)
> > The performance penalty for calling pam_ldap on uid<500 accounts can be easily
> > avoided:
> >
> > auth [success=1 default=ignore] pam_succeed_if.so uid < 500 quiet
> > auth sufficient pam_ldap.so ...
> > auth sufficient pam_unix.so use_first_pass ...
> > auth required pam_deny.so
> 
> I don't think so.
> As the first module on the stack, pam_succeed_if can't know what the numeric
> uid of the named user is.
> This is a job for pam_unix (or pam_ldap) which comes later.

That's simply not true - the user name has to be known to the PAM stack sooner or later and resolution to uid has to be done sooner or later anyway. So it surely does not matter whether the pam_succeed_if module is called before or after pam_unix.

Comment 25 Simo Sorce 2010-10-04 15:16:29 UTC
(In reply to comment #23)
> (In reply to comment #22)
> > I disagree that it is a real bug.
> Then we disagree.
> I don't understand how you can defend your position.
> The name service federation goal of NSS is intended to support such.
> The ignore_unknown_user section of the pam_ldap man page clearly documents that
> this configuration is supported.
> Whether you call it a bug in nss_ldap, pam_ldap or both doesn't matter to me.
> As far as I am concerned, this is clearly a bug.
> What kind of support is this?

Ross, I'd like to point out that bugzilla is not a support venue.
If you want Red Hat support you should go through the official support channels.

> > The performance penalty for calling pam_ldap on uid<500 accounts can be easily
> > avoided:
> >
> > auth [success=1 default=ignore] pam_succeed_if.so uid < 500 quiet
> > auth sufficient pam_ldap.so ...
> > auth sufficient pam_unix.so use_first_pass ...
> > auth required pam_deny.so
> 
> I don't think so.
> As the first module on the stack, pam_succeed_if can't know what the numeric
> uid of the named user is.
> This is a job for pam_unix (or pam_ldap) which comes later.

I find still unclear what's your aim.
Do you want to allow all your clients to read password hashes out of LDAP ?? 
Why using LDAP binds is not sufficient ?

Comment 26 ross tyler 2010-10-04 20:34:45 UTC
(In reply to comment #24)

> That's simply not true - the user name has to be known to the PAM stack sooner
> or later and resolution to uid has to be done sooner or later anyway. So it
> surely does not matter whether the pam_succeed_if module is called before or
> after pam_unix.

The user name is known to the PAM application, certainly.
The resolution to a user id has to be done using (in my system) either /etc/passwd or LDAP - that's the only place where this is information is.
The PAM application doesn't resolve this, the properly stacked PAM modules do.
In my configuration (and authconfig's), this is done via NSS by pam_unix.
It might also be done by pam_ldap.

Comment 27 ross tyler 2010-10-04 20:47:06 UTC
(In reply to comment #25)

> Ross, I'd like to point out that bugzilla is not a support venue.
Well, I am offering support (see my patch).
Sadly, perhaps that's all the support one will see here.

> If you want Red Hat support you should go through the official support channels.
See comment #14.
I have yet to have any dialog about this problem other than here.
I could comment further but suffice to say we get very little support from RedHat for the hundreds of licenses we have.
Past experiences have been similar to this one.

> I find still unclear what's your aim.
My aim is to fix what is clearly a bug.
A workaround for a bug is not a fix for a bug.
I have a workaround for this bug.
Actually, I consider my workaround a fix although it has been considered an "ugly hack" by Tomas.

> Do you want to allow all your clients to read password hashes out of LDAP ??
Absolutely not.
I want only root to be able to read password hashes.
This requires elevated LDAP privileges that nss_ldap can obtain for root (see rootbinddn and /etc/ldap.secret).
This is why pam_unix must use its SUID helper.

> Why using LDAP binds is not sufficient ?
Please read the thread

Comment 28 Simo Sorce 2010-10-04 21:29:40 UTC
(In reply to comment #27)

> > I find still unclear what's your aim.
> My aim is to fix what is clearly a bug.

Well what you define "clearly" a bug is not so clearly one, otherwise it would have already been fixed.
You are asking to change the behaviour of various nss and pam modules to fit your (non-standard) way of configuring pam_unix and pam_ldap.

We are trying to understand why exactly you have to it this way as it is not clear, you have been given options to configure your stack in a different way that looks like would perfectly achieve the same results without any changes, but you seem to refuse that as an option. Unclear why, yet.

> > Do you want to allow all your clients to read password hashes out of LDAP ??
> Absolutely not.
> I want only root to be able to read password hashes.
> This requires elevated LDAP privileges that nss_ldap can obtain for root (see
> rootbinddn and /etc/ldap.secret).
> This is why pam_unix must use its SUID helper.

You do realize that this means every single client has access to password hashes so that if any one of them is compromised your hashes are all compromised ?

This is the reason why, *normally*, password hashes are not exposed at all, no matter who you *claim* to be (root on a different host is no more trusted than any other user), and instead ldap binds are used so that the LDAP server is the one performing the authentication step and passwords never leave the server.

> > Why using LDAP binds is not sufficient ?
> Please read the thread

I've read the thread fully twice now, it is still unclear what is the constraint that forces you to use this configuration, it is also unclear why you can't use normal ldap binds to test passwords and want, instead, to use pam_unix to do that job ...

If that can be sufficiently justified then I am interested in the use case, and we can decide whether pam_unix and nss_ldap can be changed to fit this unexpected use case. The changes are not trivial and require detailed analysis to see if they can cause other side effects, so before touching anything we want to be sure that there is sufficient reason to change them.

We are not resisting the change just because we like to be difficult, changes to core security related components need extra care and extra justification, that is all.

HTH,
Simo.

Comment 29 ross tyler 2010-10-05 13:53:39 UTC
(In reply to comment #28)

> You are asking to change the behaviour of various nss and pam modules to fit
> your (non-standard) way of configuring pam_unix and pam_ldap.
I am asking for the behaviour of pam_unix/nss_ldap to work as documented.
How is my way "non-standard"?
I am following the instructions on the pam_ldap man page (see ignore_unknown_user).
The intent of NSS is to federate otherwise disparate name services in a transparent way so that this type of thing (what I am trying to do, what is documented) can be done.
An unprivileged (run as non-root) application like gnome-screensaver should be able to authenticate the user logged in using nothing more than pam_unix (no pam_ldap at all).
This is already done by pam_unix recognizing access control problems (perhaps, on /etc/shadow) and invoking its privileged SUID helper to do the job.
Using the _same_ model, pam_unix should also do this if it suspects other access control problems (perhaps, on LDAP).
This special casing is already done in pam_unix for what it suspects are other name services (NIS+, files).
NSS/PAM has _clearly_ fallen short here.
This is _clearly_ bug.
 
> We are trying to understand why exactly you have to it this way as it is not
> clear, you have been given options to configure your stack in a different way
> that looks like would perfectly achieve the same results without any changes,
> but you seem to refuse that as an option. Unclear why, yet.
Your statement, said another way: "We are trying to understand why you don't workaround a bug".
My answer is that I can workaround this bug and, in fact, I am - just not in any of the ways that you have suggested.
I have fixed the bug.
I prefer my fix to your workarounds.
I probably don't _have_ to do it my way but, I believe, it is the best way.
I believe that a bug has to be fixed.

> You do realize that this means every single client has access to password
> hashes so that if any one of them is compromised your hashes are all
> compromised ?
> This is the reason why, *normally*, password hashes are not exposed at all, no
> matter who you *claim* to be (root on a different host is no more trusted than
> any other user), and instead ldap binds are used so that the LDAP server is the
> one performing the authentication step and passwords never leave the server.
This is a different subject apart from the bug.
All root users on all machines in this closed system are so trusted.
Even so, I would like to add mutual authentication between LDAP clients and the LDAP server to address this as the protocol allows but there are some problems with this.
Again, this is a separate subject.

> I've read the thread fully twice now, it is still unclear what is the
> constraint that forces you to use this configuration, it is also unclear why
> you can't use normal ldap binds to test passwords and want, instead, to use
> pam_unix to do that job ...
Nothing _forces_ me to use my configuration.
I know (per documentation) my configuration should work.
That fact that it doesn't is a bug.
I am simply reporting a bug.
I also happen to be fixing the bug.
My configuration now works.
Wouldn't it be wonderful if it worked, as documented/intended for others?
That's why I reported and fixed the bug here.
I am trying to be a good open-source citizen.
Also (separate subject, this is all supposed to be about the bug - not workarounds), my configuration performs better than any other offered.
So, I have the best solution.
Even if a better performing solution were offered, if it didn't fix the bug the bug would still be a bug.
I have already said all this.

> If that can be sufficiently justified then I am interested in the use case, and
> we can decide whether pam_unix and nss_ldap can be changed to fit this
> unexpected use case.
Justification to fix a bug?
How about: "it's a bug".

> We are not resisting the change just because we like to be difficult, changes
> to core security related components need extra care and extra justification,
> that is all.
I appreciate your concern for security.
Regardless of your like, this is very difficult.

Comment 30 ross tyler 2010-10-05 14:02:24 UTC
(In reply to comment #29)

> All root users on all machines in this closed system are so trusted.
Actually, only root users with the knowledge of how to authenticate themselves (rootbinddn, /etc/ldap.secret) need to be trusted.
They are.

Comment 31 Tomas Mraz 2010-10-05 14:14:38 UTC
I'm sorry, but I do not see anywhere in documentation, that your non-standard configuration ought to work.

The documentation of 'ignore_unknown_user' option applies just to pam_ldap and nowhere states that pam_unix must support matching user hashes in LDAP directory through a helper.

Your fix is by no way a fix, just an incorrect workaround as '*' in passwd entry has its defined meaning and applying your fix could break other configurations with potential security implications.

Comment 32 ross tyler 2010-10-05 14:53:09 UTC
(In reply to comment #31)
> I'm sorry, but I do not see anywhere in documentation, that your non-standard
> configuration ought to work.

Really?
> in the case of a module such as pam_unix that uses the system accounts database, using nss_ldap(5) should be sufficient to meet this requirement.
How is it that pam_unix and nss_ldap are sufficient to meet this requirement here?
They are not.

Your use of "non-standard" really bothers me.
How do you define "standard"?
If a task is documented and I perform to the documentation, how can one call it non-standard?
I may not have a common configuration but I certainly have a configuration that should be supported.
It is documented.
In any case, whether my configuration is common or not has no bearing on whether this is a bug or not.
It is.
Period.

> The documentation of 'ignore_unknown_user' option applies just to pam_ldap and
> nowhere states that pam_unix must support matching user hashes in LDAP
> directory through a helper.
It says that pam_unix and nss_ldap must be "required" to authenticate an LDAP user.
This simply isn't done.
As pam_unix is architected now, the helper needs to help do this.

> Your fix is by no way a fix, just an incorrect workaround as '*' in passwd
> entry has its defined meaning
Where is this documented?

> and applying your fix could break other configurations with potential security implications.
What could it break?
What are the security implications?

I really don't care if you don't like my fix.
Fix it your own way.
Just fix it.

Comment 33 Tomas Mraz 2010-10-05 19:38:21 UTC
(In reply to comment #32)
> > Your fix is by no way a fix, just an incorrect workaround as '*' in passwd
> > entry has its defined meaning
> Where is this documented?
man 5 passwd

Comment 34 Dmitri Pal 2010-10-05 23:49:51 UTC
Ross, 

I am sorry to say but we are not going to accept the change that will break a lot of customers that have the recommended configurations. Bug or not we can't introduce a regression to what works now for the majority of the customers and fixes your specific use case even if it is technically valid (based on the docs). Imagine that you are one of the customers that are going to be broken by the fix - you would not appreciate such a change from Red Hat. May be documentation is wrong or leaves room to multiple interpretations but let us step back and try to solve the problem in a different way for you rather than focus on this specific problem. This is what Simo and Tomas were trying to accomplish. Let us get productive get your requirements and suggest a configuration that we think is best to accomplish your goals. 

This specific change will not be accepted for the noted above reasons.

Thank you,
Dmitri

Comment 35 ross tyler 2010-10-06 14:18:14 UTC
(In reply to comment #34)
> I am sorry to say but we are not going to accept the change that will break a
> lot of customers ...
What will break?!?!
Name one customer that will be broken and why.
This is the second time this assertion has been made without any substance behind it.
I assert that this can be fixed without breaking anything.
The system should perform as it was designed/documented to.
It is either wrong for pam_unix to use a helper to _try_ to authenticate or it is not.
I assume that it is not wrong because pam_unix already does so under certain circumstances.
Simply extend these circumstances.
You can choose to do it as I have done (getspnam returns *) or otherwise - I don't care.
Just do it and we are done.

> May be documentation is wrong ...
The documentation is correct.
The design/intent of NSS is correct.
NSS is intended to transparently federate naming services so that, for example, standard UNIX authentication can be done.
This is why Sun created NSS!

> Imagine that you are one of the customers that are going to be broken ...
Not hard to imagine - I _am_ one of your customers and I _am_ broken (without my own fix).
However, unlike these others you are so considerate for (why?), I am getting no support.
Unfortunately, sigh, this pattern has been typical for us and RedHat.

> Let us step back and try to solve the problem in a different way ...
There have been no better solutions suggested.
Everything that has been suggested either will not work or penalizes me.

> Let us get productive
Let's.
There are better ways to get productive than this.
What took me minutes to fix is taking weeks (months? years?) to even be acknowledged as a bug.
I don't know why this is so complicated.

Comment 36 Tomas Mraz 2010-10-06 14:29:07 UTC
(In reply to comment #35)

> > Let us step back and try to solve the problem in a different way ...
> There have been no better solutions suggested.
> Everything that has been suggested either will not work or penalizes me.

Except that's not true - this setup of PAM stack does work and does not penalize you with anything (except the need to change the configuration file(s)):

auth [success=1 default=ignore] pam_succeed_if.so uid < 500 quiet
auth sufficient pam_ldap.so ...
auth sufficient pam_unix.so use_first_pass ...
auth required pam_deny.so

It is even more efficient as for the users that are authenticated against the LDAP server the pam_unix code does not have to be called and for users with uid < 500 the LDAP server does not have to be contacted for authentication.

Comment 37 ross tyler 2010-10-06 21:20:26 UTC
(In reply to comment #36)

> Except that's not true - this setup of PAM stack does work and does not
> penalize you with anything (except the need to change the configuration
> file(s)):
> 
> auth [success=1 default=ignore] pam_succeed_if.so uid < 500 quiet
> auth sufficient pam_ldap.so ...
> auth sufficient pam_unix.so use_first_pass ...
> auth required pam_deny.so
> 
> It is even more efficient as for the users that are authenticated against the
> LDAP server the pam_unix code does not have to be called and for users with uid
> < 500 the LDAP server does not have to be contacted for authentication.

At first I thought that this wouldn't work but after looking at it again I am not so sure now (sorry!).
I looked at the pam_succeed_if code and it will resolve the uid from the application provided user name using getpwnam (and perhaps nss_ldap).
I am not sure that this would be done without added penalty or not.
Each getpwnam call might be done with separate nss_ldap LDAP sessions at separate cost.

However, whether or not your workaround works or not is completely beside the point.
The point is that there is a bug that needs to be fixed.
I believe that the bug should be addressed with a bug fix rather than a bug workaround.
While you are considering your customers, please consider your customers that have been bitten by this bug (like me!) or will be in the future.
These people will have to be enterprising enough to stumble on a workaround or deploy a fix themselves (like me!).
A workaround for bugs like these is much harder to stumble on if you don't know what the bug is.
Please fix the bug.

I still assert that a fix can be deployed without any risk to security.
Again, please explain why you think otherwise.

Comment 38 Dmitri Pal 2010-10-07 00:14:22 UTC
Ross,

1) Assumption that local root can be trusted is against best practices and thus makes your configuration "non-standard"
2) '*' in passwd entry has its defined documented meaning and applying your fix would break other configurations because it changes the meaning.

These are the two main reasons why the patch is rejected as is. I am not going to comment any more. 

Thank you
Dmitri

Comment 39 ross tyler 2010-10-07 13:57:46 UTC
(In reply to comment #38)
> 1) Assumption that local root can be trusted is against best practices and thus makes your configuration "non-standard"
No, it doesn't!!!
This kind of trust is absolutely _standard_ nss_ldap configuration!
The trust is only given to a process running as root on a machine for which nss_ldap has been properly (standardly!) configured with the authentication tokens to gain this access (/etc/ldap.conf:rootbinddn and /etc/ldap.secret).
Simple nss enabled things like using the passwd command (a SUID to root command which uses pam_ldap) to change ldap based passwords would not work without it!!!
Read the nss_ldap/pam_ldap documentation.

> 2) '*' in passwd entry has its defined documented meaning and applying your fix would break other configurations because it changes the meaning.
No, it wouldn't!!!
Please describe the use case where this breaks anything.
There is none.
In my fix, the only harm done in misinterpreting "*" is that pam_unix will _try_ to authenticate using its helper (it is useless to try itself as nothing will hash to "*" - but note that it does not special case for "*", it will try anyway).
If the SUID helper finds that the hashed password really is "*" then the user will not be authenticated (just as pam_unix would not authenticate it now).
If, instead, the SUID helper finds the real hashed password, authentication is performed as it should be.
Bug fixed.
What's breaks?
The only thing that is different is the authentication is attempted by the helper instead of pam_unix attempting it itself.

And, I am not insisting that "*" be used to encode this meaning.
Granted, the simplest (my) fix would do so but please feel free to have nss_ldap return something else on failure.
The relationship between NIS+ and pam_unix is already done in a similar way.
See the code.

Also, there is nothing holy about using "*" to mean "not a password".
Note that the pam_unix does _no_ special casing of this value now.
"*" is simply a value that nothing will hash to.
Many, many other values will serve the same purpose and there happens to be other clashing conventions already.
Look at your own /etc/shadow file of accounts created by (standard?!?) RedHat packages.
In mine there are 15 uses of "*" and 12 uses of "!!" and they all mean, effectively, not a password - but not because pam_unix looks for them.
"**", for example, would mean the same thing.
For NIS+, evidently, "*NP*" has special meaning for pam_unix.
Do you have a problem with that?

Comment 40 ross tyler 2010-10-07 14:30:49 UTC
(In reply to comment #38)

> 2) '*' in passwd entry has its defined documented meaning and applying your fix would break other configurations because it changes the meaning.
What does "*" mean when returned by pam_ldap now?
It doesn't always mean "not a password" as you insist it should.
What does this so-called abuse of the "*" encoding break here?
Oh yeah, I almost forgot, it breaks pam_unix.
But you don't need to fix that.
Your argument makes no sense.

Comment 41 ross tyler 2010-10-07 14:31:37 UTC
(In reply to comment #40)
> What does "*" mean when returned by pam_ldap now?
Sorry, I should have said nss_ldap