Heimdal krb5_kuserok fails if user's home directory protected
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
heimdal (Ubuntu) |
New
|
Undecided
|
Unassigned |
Bug Description
I've encountered this problem with Ubuntu 12.04.5 LTS Release: 12.04 and libkrb5-heimdal 1.6~git20120311
Assume a valid Heimdal Kerberos setup, with:
Packages heimdal-clients and libpam-heimdal installed (which also brings in sundry libraries as dependencies);
/etc/krb5.conf properly set up, in particular the default realm under [libdefaults], DNS-domain-to-realm mappings under [domain_realm], and the KDC under [realms];
pam_krb5 configured in /etc/pam.
a proper host principal for the client host, with its key installed in /etc/krb5.keytab;
and a local user with:
a proper entry in /etc/passwd and /etc/shadow;
a proper corresponding principal user@REALM in the KDC;
a home directory accessed over NFS, with root_squash in effect.
If the user's home directory has permissions 755, Kerberos login works just fine; in particular klist displays a TGT.
If the user's home directory has permissions 700, Kerberos login fails. A message containing `pam_krb5(
Workaround: give pam_krb5 the ignore_k5login parameter, either in [appdefaults] in /etc/krb5.conf or whereever it appears in the several files in /etc/pam.d.
I've dug around in the source, and I believe the trouble to be not in the PAM module but in the Heimdal implementation of library function krb5_kuserok. In particular, in function kuserok_
That function:
a. Calls check_one_file to try to read $HOME/.k5login. If the function returns zero, the file was opened and read (and a value returned through a pointer tells whether the current principal was found); if nonzero, the value is an errno code. kuserok_
b. Calls check_directory to scan directory $HOME/.k5login.d. Again, it returns zero if the directory was found and opened; a nonzero errno value if not. kuserok_
The trouble is that when logging in, this code is executed as the super-user; hence, if the user's home directory forbids access to anyone but the owner and NFS root_squash blocks the super-user's extra permissions, check_one_file and check_directory will return EACCES, and krb5_kuserok will return failure as if .k5login existed but didn't list the current principal, and authentication will be denied.
One could quibble over what to do if the file might exist but cannot be opened. (We don't know it exists because it is the directory's permissions that block access.) I've checked the MIT Kerberos source; in their rather-different krb5_kuserok implementation, any open failure for .k5login or .k5login.d allows access. That means maybe it's OK for Heimdal to do the same. On the other hand, one could argue (probably whoever wrote the code would) that it's safer to deny access if you can't tell whether the file is even there.
I would argue that one of two things should happen:
1. The checks for ret == ENOENT should be changed either to ret != 0 (to match the MIT behaviour) or (ret == ENOENT || ret == EACCES) (so the permission-denied case allows access, but less-ordinary errors like EIO don't).
2. It should be documented, perhaps in the Heimdal version of pam_krb5(5), that there will be unexpected failures if the super-user is denied read permission to users' home directories, and if your system is set up that way you should use ignore_k5login.
We'll probably just use ignore_k5login since for other reasons that seems the right answer for our site, but it may be a bigger problem for others.