caching + admin specified principals enhance aname_to_lname

Harry Coin <[email protected]>
Newsgroups gmane.comp.encryption.kerberos.heimdal.general
Message-ID <[email protected]>
Here we have the bulk of the changes that add caching to 
krb5_aname_to_lname.  And, it adds the ability to extract the user names 
the administrator prefers from the principal names, defaulting otherwise 
to the current behavior.   Here one administration place, /etc/k5login.d 
serves to enhance both krb5_kuserok, and krb5_aname_to_lname.


So, if file /etc/k5login.d/oscillscopes had

oscillscopes/*.innerlab.domain.org
#stop
firedept@REALM

then principal 'oscilloscopes/whatnot.innerlab.domain.org would be able 
to log in to the local box, and when asked what local user name ought to 
be associated with 'oscilloscopes/whatnot.innerlab.domain.org' the 
routine will return 'oscilloscopes' after consulting the files once, 
then almost instantly for the next 5 minutes.   It will not return 
'oscilloscopes' if asked what user ought be matched to 'firedept@REALM'.

Without these changes, principals having a / in the name will not be 
able to use NFS, such users will regress to 'nobody:nogroup' .

Caching routines in the tarball in misc.c here:
http://www.quietfountain.com/krb5nfspatches.tbz

#include <sys/types.h>
#include <dirent.h>
#include <pwd.h>

RCSID("$Id: aname_to_localname.c 13863 2004-05-25 21:46:46Z lha $");

static int reverse_etck5logind(krb5_context context,krb5_const_principal 
principal,char **user ){
     DIR *d;
     struct dirent *dent;
     struct passwd *pwd;
     krb5_boolean result;
     int errc;
#ifdef POSIX_GETPWNAM_R
     char pwbuf[2048];
     struct passwd pw;
#endif
     if (user==NULL) return EFAULT;
     *user=NULL;
     if((d = opendir(ETCK5LOGIND)) == NULL)
     return errno;
     setpassent(TRUE);
     while((dent = readdir(d)) != NULL) {
     char *fname;
     if(strcmp(dent->d_name, ".") == 0 ||
        strcmp(dent->d_name, "..") == 0 ||
        dent->d_name[0] == '#' ||              /* emacs autosave */
        dent->d_name[strlen(dent->d_name) - 1] == '~') /* emacs backup */
         continue;
#ifdef POSIX_GETPWNAM_R
     if(getpwnam_r(dent->d_name, &pw, pwbuf, sizeof(pwbuf), &pwd) != 0) 
continue;
#else
         pwd = getpwnam (dent->d_name);
#endif
     if (pwd == NULL) continue;
     asprintf(&fname,"%s%s",ETCK5LOGIND,dent->d_name);
     errc = 
krb5_internal_check_one_file(context,fname,pwd,principal,2,&result);
     free(fname);
     if (0==errc) {
         if (result) {
         *user = strdup(dent->d_name);
         break;
         }
     }
     }
     endpwent();
     closedir(d);
     return 0;
}


krb5_error_code KRB5_LIB_FUNCTION
krb5_aname_to_localname (krb5_context context,
              krb5_const_principal aname,
              size_t lnsize,
              char *lname)
{
     krb5_error_code ret;
     krb5_realm *lrealms, *r;
     int valid;
     size_t len;
     const char *res;
     char *rk5;

     //Fastest: one part principal name in the default realm.
     ret = krb5_get_default_realms (context, &lrealms);
     if (ret)
     return ret;

     valid = 0;
     for (r = lrealms; *r != NULL; ++r) {
     if (strcmp (*r, aname->realm) == 0) {
         valid = 1;
         break;
     }
     }
     krb5_free_host_realm (context, lrealms);

     if (valid && (aname->name.name_string.len == 1)) {
     res = aname->name.name_string.val[0];
         len = strlen (res);
     if (len >= lnsize)
         return ERANGE;
     strlcpy (lname, res, lnsize);
     return 0; // do not clutter the cache by adding these 
simplename@REALM principals.
     }

     //Second fastest: check the cache.
     rk5=NULL;
     _krb5_luser_principal_cache_query_princ(context,aname,&rk5); 
//check the cache.
     if (rk5!=NULL) { //found it.
         len = strlen (res);
     if (len >= lnsize)
         return ERANGE;
     strlcpy (lname, rk5, lnsize);
     free(rk5);
     return 0;
     }

     //Third fastest: check the whatnot/root@REALM format.
     if ((valid == 1) && (aname->name.name_string.len == 2)
&& (strcmp (aname->name.name_string.val[1], "root") == 0)) {
     krb5_principal rootprinc;
     krb5_boolean userok;

     res = "root";

     ret = krb5_copy_principal(context, aname, &rootprinc);
     if (ret)
         return ret;

     userok = krb5_kuserok(context, rootprinc, res); //note this makes 
use of the cache, so it is fast.
     krb5_free_principal(context, rootprinc);
     if (userok) {
         len = strlen (res);
         if (len >= lnsize)
         return ERANGE;
         strlcpy (lname, res, lnsize);
         return 0;
     }
     }

     //Slowest: check the files and if found add the result to the cache 
before returning it.
     reverse_etck5logind(context,aname,&rk5);
     if (rk5!=NULL) {
         len = strlen (rk5);
         if (len >= lnsize) { free(rk5); return ERANGE; }
         strlcpy (lname, rk5, lnsize);
         free(rk5);
         return 0;
     }
     return KRB5_NO_LOCALNAME;
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.