auth-unistd-not-on-windows-20090316
[openafs.git] / src / auth / userok.c
index 71595de..36e1034 100644 (file)
@@ -7,19 +7,12 @@
  * directory or online at http://www.openafs.org/dl/license10.html
  */
 
-/*
- * Revision 2.3  91/08/09  18:10:56
- * added a new param to afsconf_SuperUser
- * 
- * Revision 2.2  90/08/29  15:10:43
- * Cleanups.
- * Reject security index #1: rxvab/bcrypt.
- * 
- * Revision 2.1  90/08/07  18:52:21
- * Start with clean version to sync test and dev trees.
- * */
-
+#include <afsconfig.h>
 #include <afs/param.h>
+
+RCSID
+    ("$Header$");
+
 #include <afs/stds.h>
 #include <afs/pthread_glock.h>
 #include <sys/types.h>
 #include <sys/file.h>
 #include <netinet/in.h>
 #include <netdb.h>
+#include <unistd.h>
 #endif
 #include <sys/stat.h>
-#include <stdlib.h>    /* for realpath() */
+#include <stdlib.h>            /* for realpath() */
 #include <errno.h>
 #include <string.h>
 #include <ctype.h>
-
+    
 #include <rx/xdr.h>
 #include <rx/rx.h>
 #include <stdio.h>
 #include "keys.h"
 #include "afs/audit.h"
 
-
 #if !defined(UKERNEL)
-int afsconf_CheckAuth(adir, acall)
-register struct rx_call *acall;
-register struct afsconf_dir *adir; {
-    LOCK_GLOBAL_MUTEX
-    return ((afsconf_SuperUser(adir, acall, (char *)0) == 0)? 10029 : 0);
-    UNLOCK_GLOBAL_MUTEX
+int
+afsconf_CheckAuth(void *arock, struct rx_call *acall)
+{
+    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 GetNoAuthFlag(adir)
-struct afsconf_dir *adir; {
+static int
+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 */
-       return 1;   /* if /usr/afs/local/NoAuth file exists, allow access */
-      }
+       osi_audit(NoAuthEvent, 0, AUD_END);     /* some random server is running noauth */
+       return 1;               /* if /usr/afs/local/NoAuth file exists, allow access */
+    }
     return 0;
 }
 
 
-afsconf_GetNoAuthFlag(adir)
-struct afsconf_dir *adir; {
+int
+afsconf_GetNoAuthFlag(struct afsconf_dir *adir)
+{
     int rc;
 
-    LOCK_GLOBAL_MUTEX
+    LOCK_GLOBAL_MUTEX;
     rc = GetNoAuthFlag(adir);
-    UNLOCK_GLOBAL_MUTEX
+    UNLOCK_GLOBAL_MUTEX;
     return rc;
 }
 
-afsconf_SetNoAuthFlag(adir, aflag)
-struct afsconf_dir *adir;
-int aflag; {
+void
+afsconf_SetNoAuthFlag(struct afsconf_dir *adir, int aflag)
+{
     register afs_int32 code;
-    
-    LOCK_GLOBAL_MUTEX
 
+    LOCK_GLOBAL_MUTEX;
     if (aflag == 0) {
        /* turn off noauth flag */
-       code = ( unlink(AFSDIR_SERVER_NOAUTH_FILEPATH) ? errno : 0 );
-        osi_audit ( NoAuthDisableEvent, code, AUD_END ); 
-    }
-    else {
+       code = (unlink(AFSDIR_SERVER_NOAUTH_FILEPATH) ? errno : 0);
+       osi_audit(NoAuthDisableEvent, code, AUD_END);
+    } else {
        /* try to create file */
-       code = open(AFSDIR_SERVER_NOAUTH_FILEPATH, O_CREAT | O_TRUNC | O_RDWR, 0666);
-       if (code >= 0) { 
-         close(code);
-          osi_audit ( NoAuthEnableEvent, 0, AUD_END ); 
-       }
-       else 
-          osi_audit ( NoAuthEnableEvent, errno, AUD_END ); 
+       code =
+           open(AFSDIR_SERVER_NOAUTH_FILEPATH, O_CREAT | O_TRUNC | O_RDWR,
+                0666);
+       if (code >= 0) {
+           close(code);
+           osi_audit(NoAuthEnableEvent, 0, AUD_END);
+       } else
+           osi_audit(NoAuthEnableEvent, errno, AUD_END);
     }
-    UNLOCK_GLOBAL_MUTEX
+    UNLOCK_GLOBAL_MUTEX;
 }
 
 /* deletes a user from the UserList file */
-afsconf_DeleteUser(adir, auser)
-struct afsconf_dir *adir;
-register char *auser; {
+int
+afsconf_DeleteUser(struct afsconf_dir *adir, register char *auser)
+{
     char tbuffer[1024];
     char nbuffer[1024];
     register FILE *tf;
     register FILE *nf;
     register int flag;
-    char tname[64];
+    char tname[64 + 1];
     char *tp;
     int found;
     struct stat tstat;
     register 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
     {
        /*
@@ -142,12 +140,12 @@ register char *auser; {
 #endif /* AFS_NT40_ENV */
     tf = fopen(tbuffer, "r");
     if (!tf) {
-       UNLOCK_GLOBAL_MUTEX
+       UNLOCK_GLOBAL_MUTEX;
        return -1;
     }
     code = stat(tbuffer, &tstat);
     if (code < 0) {
-       UNLOCK_GLOBAL_MUTEX
+       UNLOCK_GLOBAL_MUTEX;
        return code;
     }
     strcpy(nbuffer, tbuffer);
@@ -155,7 +153,7 @@ register char *auser; {
     nf = fopen(nbuffer, "w+");
     if (!nf) {
        fclose(tf);
-       UNLOCK_GLOBAL_MUTEX
+       UNLOCK_GLOBAL_MUTEX;
        return EIO;
     }
     flag = 0;
@@ -163,94 +161,102 @@ register char *auser; {
     while (1) {
        /* check for our user id */
        tp = fgets(nbuffer, sizeof(nbuffer), tf);
-       if (tp == (char *)0) break;
+       if (tp == NULL)
+           break;
        code = sscanf(nbuffer, "%64s", tname);
        if (code == 1 && strcmp(tname, auser) == 0) {
            /* found the guy, don't copy to output file */
            found = 1;
-       }
-       else {
+       } else {
            /* otherwise copy original line  to output */
            fprintf(nf, "%s", nbuffer);
        }
     }
     fclose(tf);
-    if (ferror(nf)) flag = 1;
-    if (fclose(nf) == EOF) flag = 1;
+    if (ferror(nf))
+       flag = 1;
+    if (fclose(nf) == EOF)
+       flag = 1;
     strcpy(nbuffer, tbuffer);
-    strcat(nbuffer, ".NXX");    /* generate new file name again */
+    strcat(nbuffer, ".NXX");   /* generate new file name again */
     if (flag == 0) {
        /* try the rename */
        flag = renamefile(nbuffer, tbuffer);
        if (flag == 0)
            flag = chmod(tbuffer, tstat.st_mode);
-    }
-    else unlink(nbuffer);
+    } else
+       unlink(nbuffer);
 
     /* finally, decide what to return to the caller */
-    UNLOCK_GLOBAL_MUTEX
-    if (flag) return EIO;      /* something mysterious went wrong */
-    if (!found) return ENOENT; /* entry wasn't found, no changes made */
+    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 */
 }
 
 /* returns nth super user from the UserList file */
-afsconf_GetNthUser(adir, an, abuffer, abufferLen)
-struct afsconf_dir *adir;
-afs_int32 an;
-char *abuffer;
-afs_int32 abufferLen; {
+int
+afsconf_GetNthUser(struct afsconf_dir *adir, afs_int32 an, char *abuffer, 
+                  afs_int32 abufferLen)
+{
     char tbuffer[256];
     register FILE *tf;
-    char tname[64];
+    char tname[64 + 1];
     register char *tp;
     register int flag;
     register 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
+       UNLOCK_GLOBAL_MUTEX;
        return 1;
     }
     flag = 1;
     while (1) {
        /* check for our user id */
        tp = fgets(tbuffer, sizeof(tbuffer), tf);
-       if (tp == (char *)0) break;
+       if (tp == NULL)
+           break;
        code = sscanf(tbuffer, "%64s", tname);
        if (code == 1 && an-- == 0) {
            flag = 0;
            break;
        }
     }
-    if (flag == 0) strcpy(abuffer, tname);
+    if (flag == 0)
+       strcpy(abuffer, tname);
     fclose(tf);
-    UNLOCK_GLOBAL_MUTEX
+    UNLOCK_GLOBAL_MUTEX;
     return flag;
 }
 
 /* returns true iff user is in the UserList file */
-static FindUser(adir, auser)
-struct afsconf_dir *adir;
-register char *auser; {
+static int
+FindUser(struct afsconf_dir *adir, register char *auser)
+{
     char tbuffer[256];
     register bufio_p bp;
-    char tname[64];
-    register char *tp;
+    char tname[64 + 1];
     register int flag;
     register afs_int32 code;
     int rc;
 
-    strcompose(tbuffer, sizeof tbuffer, adir->name, "/", AFSDIR_ULIST_FILE, NULL);
+    strcompose(tbuffer, sizeof tbuffer, adir->name, "/", AFSDIR_ULIST_FILE,
+              NULL);
     bp = BufioOpen(tbuffer, O_RDONLY, 0);
-    if (!bp) return 0;
+    if (!bp)
+       return 0;
     flag = 0;
     while (1) {
        /* check for our user id */
        rc = BufioGets(bp, tbuffer, sizeof(tbuffer));
-       if (rc < 0) break;
+       if (rc < 0)
+           break;
        code = sscanf(tbuffer, "%64s", tname);
        if (code == 1 && strcmp(tname, auser) == 0) {
            flag = 1;
@@ -262,30 +268,33 @@ register char *auser; {
 }
 
 /* add a user to the user list, checking for duplicates */
-afsconf_AddUser(adir, aname)
-struct afsconf_dir *adir;
-char *aname; {
+int
+afsconf_AddUser(struct afsconf_dir *adir, char *aname)
+{
     FILE *tf;
     register afs_int32 code;
     char tbuffer[256];
 
-    LOCK_GLOBAL_MUTEX
+    LOCK_GLOBAL_MUTEX;
     if (FindUser(adir, aname)) {
-       UNLOCK_GLOBAL_MUTEX
-       return EEXIST;  /* already in the list */
+       UNLOCK_GLOBAL_MUTEX;
+       return EEXIST;          /* already in the list */
     }
 
-    strcompose(tbuffer, sizeof tbuffer, adir->name, "/", AFSDIR_ULIST_FILE, NULL);
+    strcompose(tbuffer, sizeof tbuffer, adir->name, "/", AFSDIR_ULIST_FILE,
+              NULL);
     tf = fopen(tbuffer, "a+");
     if (!tf) {
-       UNLOCK_GLOBAL_MUTEX
+       UNLOCK_GLOBAL_MUTEX;
        return EIO;
     }
     fprintf(tf, "%s\n", aname);
     code = 0;
-    if (ferror(tf)) code = EIO;
-    if (fclose(tf)) code = EIO;
-    UNLOCK_GLOBAL_MUTEX
+    if (ferror(tf))
+       code = EIO;
+    if (fclose(tf))
+       code = EIO;
+    UNLOCK_GLOBAL_MUTEX;
     return code;
 }
 
@@ -293,36 +302,35 @@ char *aname; {
        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;
+static char *
+CompFindUser(struct afsconf_dir *adir, char *name, char *sep, char *inst, 
+            char *realm)
 {
-    static char fullname[ MAXKTCNAMELEN + MAXKTCNAMELEN +
-       MAXKTCREALMLEN + 3 ];
+    static char fullname[MAXKTCNAMELEN + MAXKTCNAMELEN + MAXKTCREALMLEN + 3];
 
     /* always must have name */
-    if ( !name || !name[0] ) { return NULL; }
+    if (!name || !name[0]) {
+       return NULL;
+    }
     strcpy(fullname, name);
 
     /* might have instance */
-    if ( inst && inst[0] ) {
-       if ( !sep || !sep[0] ) { return NULL; }
+    if (inst && inst[0]) {
+       if (!sep || !sep[0]) {
+           return NULL;
+       }
 
        strcat(fullname, sep);
        strcat(fullname, inst);
     }
 
     /* might have realm */
-    if ( realm && realm[0] )
-    {
+    if (realm && realm[0]) {
        strcat(fullname, "@");
        strcat(fullname, realm);
     }
 
-    if ( FindUser(adir, fullname) ) {
+    if (FindUser(adir, fullname)) {
        return fullname;
     } else {
        return NULL;
@@ -334,126 +342,157 @@ static char *CompFindUser(adir, name, sep, inst, realm)
     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; {
+afs_int32
+afsconf_SuperUser(struct afsconf_dir *adir, struct rx_call *acall, char *namep)
+{
     register struct rx_connection *tconn;
     register afs_int32 code;
     int flag;
 
-    LOCK_GLOBAL_MUTEX
+    LOCK_GLOBAL_MUTEX;
     if (!adir) {
-       UNLOCK_GLOBAL_MUTEX
+       UNLOCK_GLOBAL_MUTEX;
        return 0;
     }
 
     if (afsconf_GetNoAuthFlag(adir)) {
-       if (namep) strcpy(namep, "<NoAuth>");
-       UNLOCK_GLOBAL_MUTEX
+       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) {
+    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) {
+       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];
+       char uname[MAXKTCNAMELEN + MAXKTCNAMELEN + MAXKTCREALMLEN + 3];
 
        afs_uint32 exp;
        static char lcell[MAXCELLCHARS] = "";
-       static char lrealm[AFS_REALM_SZ] = "";
-       
+       static char lrealms[AFS_NUM_LREALMS][AFS_REALM_SZ];
+       static int  num_lrealms = -1;
+       int lrealm_match = 0, i;
+
        /* get auth details from server connection */
-       code = rxkad_GetServerInfo
-           (acall->conn, (afs_int32 *) 0, &exp, 
-               tname, tinst, tcell, (afs_int32 *) 0);
+       code =
+           rxkad_GetServerInfo(acall->conn, NULL, &exp, tname, tinst, tcell,
+                               NULL);
        if (code) {
-           UNLOCK_GLOBAL_MUTEX
-           return 0; /* bogus connection/other error */
+           UNLOCK_GLOBAL_MUTEX;
+           return 0;           /* bogus connection/other error */
        }
 
        /* don't bother checking anything else if tix have expired */
 #ifdef AFS_PTHREAD_ENV
-       if (exp < clock_Sec()) {
+       if (exp < clock_Sec()) {
 #else
-       if (exp < FT_ApproxTime()) {
+       if (exp < FT_ApproxTime()) {
 #endif
-           UNLOCK_GLOBAL_MUTEX
-           return 0;   /* expired tix */
+           UNLOCK_GLOBAL_MUTEX;
+           return 0;           /* expired tix */
        }
 
        /* generate lowercased version of cell name */
        strcpy(tcell_l, tcell);
        tmp = tcell_l;
-       while ( *tmp ) { *tmp = tolower(*tmp); *tmp++; }
+       while (*tmp) {
+           *tmp = tolower(*tmp);
+           tmp++;
+       }
 
        /* determine local cell name. It's static, so will only get
-          calculated the first time through */
+        * 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 (num_lrealms == -1) {
+           for (i=0; i<AFS_NUM_LREALMS; i++) {
+               if (afs_krb_get_lrealm(lrealms[i], i) != 0 /*KSUCCESS*/)
+                   break;
+           }
+
+           if (i == 0) {
+               strncpy(lrealms[0], lcell, AFS_REALM_SZ);
+               num_lrealms = 1;
+           } else {
+               num_lrealms = i;
+           }
        }
 
+       /* 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;
+           }
+       }
+
+       /* 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;
 
        /* localauth special case */
-       if ( strlen(tinst) == 0 && strlen(tcell) == 0 && 
-               !strcmp(tname, AUTH_SUPERUSER) ) {
+       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)) ) {
+           /* 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)) ) {
+           } else if ((tmp = CompFindUser(adir, tname, "/", tinst, NULL))) {
                strcpy(uname, tmp);
                flag = 1;
 #endif
            }
-
-       /* cell of conn doesn't match local cell or realm */
+           /* cell of conn doesn't match local cell or realm */
        } else {
-           if ( (tmp = CompFindUser(adir, tname, ".", tinst, tcell)) ) {
+           if ((tmp = CompFindUser(adir, tname, ".", tinst, tcell))) {
                strcpy(uname, tmp);
                flag = 1;
 #ifdef notyet
-           } else if ( (tmp = CompFindUser(adir, tname, "/", tinst, tcell)) ) {
+           } else if ((tmp = CompFindUser(adir, tname, "/", tinst, tcell))) {
                strcpy(uname, tmp);
                flag = 1;
 #endif
-           } else if ( (tmp = CompFindUser(adir, tname, ".", tinst, tcell_l)) ) {
+           } 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)) ) {
+           } else if ((tmp = CompFindUser(adir, tname, "/", tinst, tcell_l))) {
                strcpy(uname, tmp);
                flag = 1;
 #endif
@@ -462,11 +501,10 @@ char *namep; {
 
        if (namep)
            strcpy(namep, uname);
-       UNLOCK_GLOBAL_MUTEX
+       UNLOCK_GLOBAL_MUTEX;
        return flag;
-    }
-    else { /* some other auth type */
-       UNLOCK_GLOBAL_MUTEX
-       return  0;          /* mysterious, just say no */
+    } else {                   /* some other auth type */
+       UNLOCK_GLOBAL_MUTEX;
+       return 0;               /* mysterious, just say no */
     }
 }