userok: Don't double check for expiry
[openafs.git] / src / auth / userok.c
index 7b7abd4..28e715a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
@@ -10,8 +10,6 @@
 #include <afsconfig.h>
 #include <afs/param.h>
 
-RCSID
-    ("$Header$");
 
 #include <afs/stds.h>
 #include <afs/pthread_glock.h>
@@ -24,6 +22,7 @@ RCSID
 #include <sys/file.h>
 #include <netinet/in.h>
 #include <netdb.h>
+#include <unistd.h>
 #endif
 #include <sys/stat.h>
 #include <stdlib.h>            /* for realpath() */
@@ -46,22 +45,21 @@ RCSID
 #include "keys.h"
 #include "afs/audit.h"
 
-afs_int32 afsconf_SuperUser();
-
 #if !defined(UKERNEL)
 int
-afsconf_CheckAuth(adir, acall)
-     register struct rx_call *acall;
-     register struct afsconf_dir *adir;
+afsconf_CheckAuth(void *arock, struct rx_call *acall)
 {
-    LOCK_GLOBAL_MUTEX return ((afsconf_SuperUser(adir, acall, NULL) == 0) ?
-                             10029 : 0);
-UNLOCK_GLOBAL_MUTEX}
+    struct afsconf_dir *adir = (struct afsconf_dir *) arock;
+    int rc;
+    LOCK_GLOBAL_MUTEX;
+    rc = ((afsconf_SuperUser(adir, acall, NULL) == 0) ? 10029 : 0);
+    UNLOCK_GLOBAL_MUTEX;
+    return rc;
+}
 #endif /* !defined(UKERNEL) */
 
 static int
-GetNoAuthFlag(adir)
-     struct afsconf_dir *adir;
+GetNoAuthFlag(struct afsconf_dir *adir)
 {
     if (access(AFSDIR_SERVER_NOAUTH_FILEPATH, 0) == 0) {
        osi_audit(NoAuthEvent, 0, AUD_END);     /* some random server is running noauth */
@@ -72,23 +70,23 @@ GetNoAuthFlag(adir)
 
 
 int
-afsconf_GetNoAuthFlag(adir)
-     struct afsconf_dir *adir;
+afsconf_GetNoAuthFlag(struct afsconf_dir *adir)
 {
     int rc;
 
-    LOCK_GLOBAL_MUTEX rc = GetNoAuthFlag(adir);
-    UNLOCK_GLOBAL_MUTEX return rc;
+    LOCK_GLOBAL_MUTEX;
+    rc = GetNoAuthFlag(adir);
+    UNLOCK_GLOBAL_MUTEX;
+    return rc;
 }
 
 void
-afsconf_SetNoAuthFlag(adir, aflag)
-     struct afsconf_dir *adir;
-     int aflag;
+afsconf_SetNoAuthFlag(struct afsconf_dir *adir, int aflag)
 {
-    register afs_int32 code;
+    afs_int32 code;
 
-    LOCK_GLOBAL_MUTEX if (aflag == 0) {
+    LOCK_GLOBAL_MUTEX;
+    if (aflag == 0) {
        /* turn off noauth flag */
        code = (unlink(AFSDIR_SERVER_NOAUTH_FILEPATH) ? errno : 0);
        osi_audit(NoAuthDisableEvent, code, AUD_END);
@@ -103,27 +101,27 @@ afsconf_SetNoAuthFlag(adir, aflag)
        } else
            osi_audit(NoAuthEnableEvent, errno, AUD_END);
     }
-UNLOCK_GLOBAL_MUTEX}
+    UNLOCK_GLOBAL_MUTEX;
+}
 
 /* deletes a user from the UserList file */
 int
-afsconf_DeleteUser(adir, auser)
-     struct afsconf_dir *adir;
-     register char *auser;
+afsconf_DeleteUser(struct afsconf_dir *adir, char *auser)
 {
     char tbuffer[1024];
     char nbuffer[1024];
-    register FILE *tf;
-    register FILE *nf;
-    register int flag;
+    FILE *tf;
+    FILE *nf;
+    int flag;
     char tname[64 + 1];
     char *tp;
     int found;
     struct stat tstat;
-    register afs_int32 code;
+    afs_int32 code;
 
-    LOCK_GLOBAL_MUTEX strcompose(tbuffer, sizeof tbuffer, adir->name, "/",
-                                AFSDIR_ULIST_FILE, NULL);
+    LOCK_GLOBAL_MUTEX;
+    strcompose(tbuffer, sizeof tbuffer, adir->name, "/",
+              AFSDIR_ULIST_FILE, NULL);
 #ifndef AFS_NT40_ENV
     {
        /*
@@ -140,18 +138,21 @@ afsconf_DeleteUser(adir, auser)
 #endif /* AFS_NT40_ENV */
     tf = fopen(tbuffer, "r");
     if (!tf) {
-       UNLOCK_GLOBAL_MUTEX return -1;
+       UNLOCK_GLOBAL_MUTEX;
+       return -1;
     }
     code = stat(tbuffer, &tstat);
     if (code < 0) {
-       UNLOCK_GLOBAL_MUTEX return code;
+       UNLOCK_GLOBAL_MUTEX;
+       return code;
     }
     strcpy(nbuffer, tbuffer);
     strcat(nbuffer, ".NXX");
     nf = fopen(nbuffer, "w+");
     if (!nf) {
        fclose(tf);
-       UNLOCK_GLOBAL_MUTEX return EIO;
+       UNLOCK_GLOBAL_MUTEX;
+       return EIO;
     }
     flag = 0;
     found = 0;
@@ -185,8 +186,9 @@ afsconf_DeleteUser(adir, auser)
        unlink(nbuffer);
 
     /* finally, decide what to return to the caller */
-    UNLOCK_GLOBAL_MUTEX if (flag)
-         return EIO;           /* something mysterious went wrong */
+    UNLOCK_GLOBAL_MUTEX;
+    if (flag)
+       return EIO;             /* something mysterious went wrong */
     if (!found)
        return ENOENT;          /* entry wasn't found, no changes made */
     return 0;                  /* everything was fine */
@@ -194,24 +196,23 @@ afsconf_DeleteUser(adir, auser)
 
 /* returns nth super user from the UserList file */
 int
-afsconf_GetNthUser(adir, an, abuffer, abufferLen)
-     struct afsconf_dir *adir;
-     afs_int32 an;
-     char *abuffer;
-     afs_int32 abufferLen;
+afsconf_GetNthUser(struct afsconf_dir *adir, afs_int32 an, char *abuffer,
+                  afs_int32 abufferLen)
 {
     char tbuffer[256];
-    register FILE *tf;
+    FILE *tf;
     char tname[64 + 1];
-    register char *tp;
-    register int flag;
-    register afs_int32 code;
+    char *tp;
+    int flag;
+    afs_int32 code;
 
-    LOCK_GLOBAL_MUTEX strcompose(tbuffer, sizeof tbuffer, adir->name, "/",
-                                AFSDIR_ULIST_FILE, NULL);
+    LOCK_GLOBAL_MUTEX;
+    strcompose(tbuffer, sizeof tbuffer, adir->name, "/",
+              AFSDIR_ULIST_FILE, NULL);
     tf = fopen(tbuffer, "r");
     if (!tf) {
-       UNLOCK_GLOBAL_MUTEX return 1;
+       UNLOCK_GLOBAL_MUTEX;
+       return 1;
     }
     flag = 1;
     while (1) {
@@ -228,20 +229,19 @@ afsconf_GetNthUser(adir, an, abuffer, abufferLen)
     if (flag == 0)
        strcpy(abuffer, tname);
     fclose(tf);
-    UNLOCK_GLOBAL_MUTEX return flag;
+    UNLOCK_GLOBAL_MUTEX;
+    return flag;
 }
 
 /* returns true iff user is in the UserList file */
 static int
-FindUser(adir, auser)
-     struct afsconf_dir *adir;
-     register char *auser;
+FindUser(struct afsconf_dir *adir, char *auser)
 {
     char tbuffer[256];
-    register bufio_p bp;
+    bufio_p bp;
     char tname[64 + 1];
-    register int flag;
-    register afs_int32 code;
+    int flag;
+    afs_int32 code;
     int rc;
 
     strcompose(tbuffer, sizeof tbuffer, adir->name, "/", AFSDIR_ULIST_FILE,
@@ -267,23 +267,24 @@ FindUser(adir, auser)
 
 /* add a user to the user list, checking for duplicates */
 int
-afsconf_AddUser(adir, aname)
-     struct afsconf_dir *adir;
-     char *aname;
+afsconf_AddUser(struct afsconf_dir *adir, char *aname)
 {
     FILE *tf;
-    register afs_int32 code;
+    afs_int32 code;
     char tbuffer[256];
 
-    LOCK_GLOBAL_MUTEX if (FindUser(adir, aname)) {
-       UNLOCK_GLOBAL_MUTEX return EEXIST;      /* already in the list */
+    LOCK_GLOBAL_MUTEX;
+    if (FindUser(adir, aname)) {
+       UNLOCK_GLOBAL_MUTEX;
+       return EEXIST;          /* already in the list */
     }
 
     strcompose(tbuffer, sizeof tbuffer, adir->name, "/", AFSDIR_ULIST_FILE,
               NULL);
     tf = fopen(tbuffer, "a+");
     if (!tf) {
-       UNLOCK_GLOBAL_MUTEX return EIO;
+       UNLOCK_GLOBAL_MUTEX;
+       return EIO;
     }
     fprintf(tf, "%s\n", aname);
     code = 0;
@@ -291,20 +292,17 @@ afsconf_AddUser(adir, aname)
        code = EIO;
     if (fclose(tf))
        code = EIO;
-    UNLOCK_GLOBAL_MUTEX return code;
+    UNLOCK_GLOBAL_MUTEX;
+    return code;
 }
 
 /* special CompFindUser routine that builds up a princ and then
-       calls finduser on it. If found, returns char * to user string, 
+       calls finduser on it. If found, returns char * to user string,
        otherwise returns NULL. The resulting string should be immediately
        copied to other storage prior to release of mutex. */
 static char *
-CompFindUser(adir, name, sep, inst, realm)
-     struct afsconf_dir *adir;
-     char *name;
-     char *sep;
-     char *inst;
-     char *realm;
+CompFindUser(struct afsconf_dir *adir, char *name, char *sep, char *inst,
+            char *realm)
 {
     static char fullname[MAXKTCNAMELEN + MAXKTCNAMELEN + MAXKTCREALMLEN + 3];
 
@@ -337,138 +335,179 @@ CompFindUser(adir, name, sep, inst, realm)
     }
 }
 
-
-/* make sure user authenticated on rx call acall is in list of valid
-    users. Copy the "real name" of the authenticated user into namep
-    if a pointer is passed.
-*/
-afs_int32
-afsconf_SuperUser(adir, acall, namep)
-     struct afsconf_dir *adir;
-     struct rx_call *acall;
-     char *namep;
+static int
+kerberosSuperUser(struct afsconf_dir *adir, char *tname, char *tinst,
+                 char *tcell, char *namep)
 {
-    register struct rx_connection *tconn;
-    register afs_int32 code;
-    int flag;
+    char tcell_l[MAXKTCREALMLEN];
+    char *tmp;
 
-    LOCK_GLOBAL_MUTEX if (!adir) {
-       UNLOCK_GLOBAL_MUTEX return 0;
-    }
+    /* keep track of which one actually authorized request */
+    char uname[MAXKTCNAMELEN + MAXKTCNAMELEN + MAXKTCREALMLEN + 3];
 
-    if (afsconf_GetNoAuthFlag(adir)) {
-       if (namep)
-           strcpy(namep, "<NoAuth>");
-       UNLOCK_GLOBAL_MUTEX return 1;
-    }
-
-    tconn = rx_ConnectionOf(acall);
-    code = rx_SecurityClassOf(tconn);
-    if (code == 0) {
-       UNLOCK_GLOBAL_MUTEX return 0;   /* not authenticated at all, answer is no */
-    } else if (code == 1) {
-       /* bcrypt tokens */
-       UNLOCK_GLOBAL_MUTEX return 0;   /* not supported any longer */
-    } else if (code == 2) {
-       char tname[MAXKTCNAMELEN];      /* authentication from ticket */
-       char tinst[MAXKTCNAMELEN];
-       char tcell[MAXKTCREALMLEN];
-       char tcell_l[MAXKTCREALMLEN];
-       char *tmp;
-
-       /* keep track of which one actually authorized request */
-       char uname[MAXKTCNAMELEN + MAXKTCNAMELEN + MAXKTCREALMLEN + 3];
+    static char lcell[MAXCELLCHARS] = "";
+    static char lrealms[AFS_NUM_LREALMS][AFS_REALM_SZ];
+    static int  num_lrealms = -1;
+    int lrealm_match = 0, i;
+    int flag;
 
-       afs_uint32 exp;
-       static char lcell[MAXCELLCHARS] = "";
-       static char lrealm[AFS_REALM_SZ] = "";
+    /* generate lowercased version of cell name */
+    strcpy(tcell_l, tcell);
+    tmp = tcell_l;
+    while (*tmp) {
+       *tmp = tolower(*tmp);
+       tmp++;
+    }
 
-       /* get auth details from server connection */
-       code =
-           rxkad_GetServerInfo(acall->conn, NULL, &exp, tname, tinst, tcell,
-                               NULL);
-       if (code) {
-           UNLOCK_GLOBAL_MUTEX return 0;       /* bogus connection/other error */
+    /* determine local cell name. It's static, so will only get
+     * calculated the first time through */
+    if (!lcell[0])
+       afsconf_GetLocalCell(adir, lcell, sizeof(lcell));
+
+    /* if running a krb environment, also get the local realm */
+    /* note - this assumes AFS_REALM_SZ <= MAXCELLCHARS */
+    /* just set it to lcell if it fails */
+    if (num_lrealms == -1) {
+       for (i=0; i<AFS_NUM_LREALMS; i++) {
+           if (afs_krb_get_lrealm(lrealms[i], i) != 0 /*KSUCCESS*/)
+               break;
        }
 
-       /* don't bother checking anything else if tix have expired */
-#ifdef AFS_PTHREAD_ENV
-       if (exp < clock_Sec()) {
-#else
-       if (exp < FT_ApproxTime()) {
-#endif
-           UNLOCK_GLOBAL_MUTEX return 0;       /* expired tix */
+       if (i == 0) {
+           strncpy(lrealms[0], lcell, AFS_REALM_SZ);
+           num_lrealms = 1;
+       } else {
+           num_lrealms = i;
        }
+    }
 
-       /* generate lowercased version of cell name */
-       strcpy(tcell_l, tcell);
-       tmp = tcell_l;
-       while (*tmp) {
-           *tmp = tolower(*tmp);
-           *tmp++;
+    /* See if the ticket cell matches one of the local realms */
+    lrealm_match = 0;
+    for ( i=0;i<num_lrealms;i++ ) {
+       if (!strcasecmp(lrealms[i], tcell)) {
+           lrealm_match = 1;
+           break;
        }
+    }
 
-       /* determine local cell name. It's static, so will only get
-        * calculated the first time through */
-       if (!lcell[0])
-           afsconf_GetLocalCell(adir, lcell, sizeof(lcell));
-
-       /* if running a krb environment, also get the local realm */
-       /* note - this assumes AFS_REALM_SZ <= MAXCELLCHARS */
-       /* just set it to lcell if it fails */
-       if (!lrealm[0]) {
-           if (afs_krb_get_lrealm(lrealm, 0) != 0)     /* KSUCCESS */
-               strncpy(lrealm, lcell, AFS_REALM_SZ);
-       }
+    /* If yes, then make sure that the name is not present in
+     * an exclusion list */
+    if (lrealm_match) {
+       if (tinst[0])
+           snprintf(uname,sizeof(uname),"%s.%s@%s",tname,tinst,tcell);
+       else
+           snprintf(uname,sizeof(uname),"%s@%s",tname,tcell);
 
+       if (afs_krb_exclusion(uname))
+           lrealm_match = 0;
+    }
 
-       /* start with no uname and no authorization */
-       strcpy(uname, "");
-       flag = 0;
+    /* start with no uname and no authorization */
+    strcpy(uname, "");
+    flag = 0;
 
-       /* localauth special case */
-       if (strlen(tinst) == 0 && strlen(tcell) == 0
-           && !strcmp(tname, AUTH_SUPERUSER)) {
-           strcpy(uname, "<LocalAuth>");
-           flag = 1;
+    /* localauth special case */
+    if (strlen(tinst) == 0 && strlen(tcell) == 0
+       && !strcmp(tname, AUTH_SUPERUSER)) {
+       strcpy(uname, "<LocalAuth>");
+       flag = 1;
 
-           /* cell of connection matches local cell or krb4 realm */
-       } else if (!strcasecmp(tcell, lcell) || !strcasecmp(tcell, lrealm)) {
-           if ((tmp = CompFindUser(adir, tname, ".", tinst, NULL))) {
-               strcpy(uname, tmp);
-               flag = 1;
+       /* cell of connection matches local cell or one of the realms */
+    } else if (!strcasecmp(tcell, lcell) || lrealm_match) {
+       if ((tmp = CompFindUser(adir, tname, ".", tinst, NULL))) {
+           strcpy(uname, tmp);
+           flag = 1;
 #ifdef notyet
-           } else if ((tmp = CompFindUser(adir, tname, "/", tinst, NULL))) {
-               strcpy(uname, tmp);
-               flag = 1;
+       } else if ((tmp = CompFindUser(adir, tname, "/", tinst, NULL))) {
+           strcpy(uname, tmp);
+           flag = 1;
 #endif
-           }
-
-           /* cell of conn doesn't match local cell or realm */
-       } else {
-           if ((tmp = CompFindUser(adir, tname, ".", tinst, tcell))) {
-               strcpy(uname, tmp);
-               flag = 1;
+       }
+       /* cell of conn doesn't match local cell or realm */
+    } else {
+       if ((tmp = CompFindUser(adir, tname, ".", tinst, tcell))) {
+           strcpy(uname, tmp);
+           flag = 1;
 #ifdef notyet
-           } else if ((tmp = CompFindUser(adir, tname, "/", tinst, tcell))) {
-               strcpy(uname, tmp);
-               flag = 1;
+       } else if ((tmp = CompFindUser(adir, tname, "/", tinst, tcell))) {
+           strcpy(uname, tmp);
+           flag = 1;
 #endif
-           } else if ((tmp = CompFindUser(adir, tname, ".", tinst, tcell_l))) {
-               strcpy(uname, tmp);
-               flag = 1;
+       } else if ((tmp = CompFindUser(adir, tname, ".", tinst, tcell_l))) {
+           strcpy(uname, tmp);
+           flag = 1;
 #ifdef notyet
-           } else if ((tmp = CompFindUser(adir, tname, "/", tinst, tcell_l))) {
-               strcpy(uname, tmp);
-               flag = 1;
+       } else if ((tmp = CompFindUser(adir, tname, "/", tinst, tcell_l))) {
+           strcpy(uname, tmp);
+           flag = 1;
 #endif
-           }
        }
+    }
+
+    if (namep)
+       strcpy(namep, uname);
+
+    return flag;
+}
+
+static int
+rxkadSuperUser(struct afsconf_dir *adir, struct rx_call *acall, char *namep)
+{
+    char tname[MAXKTCNAMELEN]; /* authentication from ticket */
+    char tinst[MAXKTCNAMELEN];
+    char tcell[MAXKTCREALMLEN];
+
+    afs_uint32 exp;
+    int code;
+
+    /* get auth details from server connection */
+    code = rxkad_GetServerInfo(acall->conn, NULL, &exp, tname, tinst, tcell,
+                              NULL);
+    if (code)
+       return 0;               /* bogus connection/other error */
+
+    return kerberosSuperUser(adir, tname, tinst, tcell, namep);
+}
+
+/* make sure user authenticated on rx call acall is in list of valid
+    users. Copy the "real name" of the authenticated user into namep
+    if a pointer is passed.
+*/
+afs_int32
+afsconf_SuperUser(struct afsconf_dir *adir, struct rx_call *acall, char *namep)
+{
+    struct rx_connection *tconn;
+    afs_int32 code;
+    int flag;
+
+    LOCK_GLOBAL_MUTEX;
+    if (!adir) {
+       UNLOCK_GLOBAL_MUTEX;
+       return 0;
+    }
 
+    if (afsconf_GetNoAuthFlag(adir)) {
        if (namep)
-           strcpy(namep, uname);
-       UNLOCK_GLOBAL_MUTEX return flag;
+           strcpy(namep, "<NoAuth>");
+       UNLOCK_GLOBAL_MUTEX;
+       return 1;
+    }
+
+    tconn = rx_ConnectionOf(acall);
+    code = rx_SecurityClassOf(tconn);
+    if (code == 0) {
+       UNLOCK_GLOBAL_MUTEX;
+       return 0;               /* not authenticated at all, answer is no */
+    } else if (code == 1) {
+       /* bcrypt tokens */
+       UNLOCK_GLOBAL_MUTEX;
+       return 0;               /* not supported any longer */
+    } else if (code == 2) {
+       flag = rxkadSuperUser(adir, acall, namep);
+       UNLOCK_GLOBAL_MUTEX;
+       return flag;
     } else {                   /* some other auth type */
-       UNLOCK_GLOBAL_MUTEX return 0;   /* mysterious, just say no */
+       UNLOCK_GLOBAL_MUTEX;
+       return 0;               /* mysterious, just say no */
     }
 }