Bug #85009 Authentication_pam with Unix password needs read access to /etc/shadow
Submitted: 15 Feb 2017 12:57 Modified: 26 May 2017 10:42
Reporter: Jörg Brühe (OCA) Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Documentation Severity:S3 (Non-critical)
Version:5.7.16, 5.7.17 OS:Linux
Assigned to: CPU Architecture:Any
Tags: /etc/shadow, password, privilege, read

[15 Feb 2017 12:57] Jörg Brühe
Description:
Using an Enterprise Edition, I tried the authentication_pam plugin.
To avoid setting up additional infrastructure, I wanted to use the native Unix (Linux) password, as described in the manual:
   7.5.1.5.3 Unix Password Authentication without Proxy Users

With default installation (the server running as "mysql"), this doesn't work:
The server needs to access the file "/etc/shadow", and this file is (by default) not readable for anybody. As a consequence, the server doesn't recognize the password as correct, and the connect attempt fails.

The bad thing is: the server doesn't tell the reason. All I got was the standard message in the error log:
    Access denied for user 'U'@'localhost' (using password: YES)
This cannot be distinguished from a wrong password.

How to repeat:
Just follow the manual ...

(And please, make sure documentation gets verified using default setups!)

Suggested fix:
At the very least, give a helpful error message:
    Server cannot read /etc/shadow

In fact, I firmly believe the plugin code uses some system call to get the hashed password, this fails, and the code doesn't produce an error message.
This would violate all principles of good programming ...

Better, find a way for the server to read and compare the hashed password, to make it work as described.
[15 Feb 2017 14:45] Jörg Brühe
Linux distributions differ in how they handle /etc/shadow, just two examples:

Kubuntu 14.04:
joerg@mach:~$ ls -ld /etc/shadow*
-rw-r----- 1 root shadow 1216 Jul 28  2015 /etc/shadow
-rw------- 1 root root   1216 Jul 28  2015 /etc/shadow-

Oracle Linux 7.2:
Kubuntu 14.04:
joerg@VM:~$ ls -ld /etc/shadow*
---------- 1 root root   1216 Jul 28  2015 /etc/shadow
---------- 1 root root   1216 Jul 28  2015 /etc/shadow-
[16 Feb 2017 8:45] Georgi Kodinov
Hi Jörg,

The Enterprise authentication plugin is not doing anything special. It's mostly calling the PAM library APIs. This typically results in PAM backend modules being loaded in the calling process. In your case that's the pam_unix module. And that has a known dependency on /etc/shadow (see e.g. http://manpages.ubuntu.com/manpages/zesty/man8/pam_unix.8.html). 

Unfortunately the man page says "usually" so we can't really add that to our docs. IMHO configuring pam_unix properly is a bit beyond the scope of the MySQL docs. 

Please feel free to re-open the bug as a docs bug if you feel like you should still have it there and want to get a second, more informed opinion.
[16 Feb 2017 10:59] Jörg Brühe
Sorry, I had started from wrong assumptions:
I had believed (strongly) that the PAM plugin would handle the two cases "I cannot access the necessary information" and "I checked the password, and it doesn't match" differently.
From looking at the debug output, this was wrong: In both cases, a "rc = 7" is logged, so it really seems the caller cannot differ these two reasons for failure.

IMNSHO, that's bad, but I cannot blame the MySQL developers for that. Please accept my sincere apologies for my initial wrong assumptions.

This turns my bug report from a code to a documentation issue.
Please, add a note to the manual which essentially says:

With the current PAM modules, it is impossible for the MySQL server to differ between "password could not be checked" and "password doesn't match", both cases will produce the same error message. It is the administrator's responsibility to ensure that the server (and any library code it calls) can access the necessary information.

On Oracle Linux 7.2, I got it to work by creating a Linux group with read permission for "/etc/shadow", setting that group as an additional group for the user "mysql", and restarting the "mysqld" service.
(No, I didn't invent that, others pointed me at that approach.)
If you don't want to endorse that approach by adding it to the manual, I can add it as a note.

Please let me know which way you prefer - I feel this information should be accessible from the "PAM authentication plugin" manual page without searching the internet.
[16 Feb 2017 13:10] MySQL Verification Team
Thank you, verifying as doc bug.
[22 May 2017 14:33] Paul DuBois
Posted by developer:
 
https://dev.mysql.com/doc/refman/5.7/en/pam-pluggable-authentication.html
[26 May 2017 10:42] Jörg Brühe
Nice new text in the manual, probably the best way to handle it.

Just one typo:
In step 3, the file to assign is "/etc/shadow".
The code quote is correct, but the introductory sentence mentions "/etc/group".
In step 2, that was the correct name, but in step 3 it is wrong.