Heimdal krb5_kuserok fails if user's home directory protected

Bug #1484262 reported by Norman Wilson
6
This bug affects 1 person
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.dfsg.1-2ubuntu0.1. It wouldn't surprise me were the problem wider in scope.

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.d/common-auth (as should happen automatically when libpam-heimdal is installed);
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(login:auth): failed authorization check' is written to syslog/auth. No session ticket cache is set up.

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_user_k5login_plug_f in file lib/krb5/kuserok.c in source package heimdal-1.6~git20120311 (fetched by apt-get source libkrb5-26-heimdal).
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_user_k5login_plug_f believes that if errno was ENOENT, the file didn't exist and all is well; otherwise it acts as if it found an empty file, which means the principal wasn't listed there, which means krb5_kuserok will return failure.

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_user_k5login_plug_f declares that all is well if the error value is ENOENT or ENOTDIR; otherwise it again causes krb5_kuserok to fail.

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.

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.