userok.c: Fix fixed-size on-stack path buffers
[openafs.git] / src / auth / userok.c
index b8f8166..326a736 100644 (file)
@@ -12,6 +12,7 @@
 #include <afs/stds.h>
 
 #include <roken.h>
+#include <afs/opr.h>
 
 #include <ctype.h>
 
 #include <rx/xdr.h>
 #include <rx/rx.h>
 #include <rx/rx_identity.h>
-#include <stdio.h>
 #include <afs/afsutil.h>
 #include <afs/fileutil.h>
 
-#ifdef AFS_ATHENA_STDENV
-#include <krb.h>
-#endif
-
 #include "base64.h"
 #include "auth.h"
 #include "cellconfig.h"
@@ -47,8 +43,7 @@ static void
 UserListFileName(struct afsconf_dir *adir,
                 char *buffer, size_t len)
 {
-    strcompose(buffer, len, adir->name, "/",
-              AFSDIR_ULIST_FILE, NULL);
+    strcompose(buffer, len, adir->name, "/", AFSDIR_ULIST_FILE, (char *)NULL);
 }
 
 #if !defined(UKERNEL)
@@ -132,8 +127,8 @@ afsconf_SetNoAuthFlag(struct afsconf_dir *adir, int aflag)
 int
 afsconf_DeleteIdentity(struct afsconf_dir *adir, struct rx_identity *user)
 {
-    char tbuffer[1024];
-    char nbuffer[1024];
+    char *filename, *nfilename;
+    char *buffer;
     char *copy;
     FILE *tf;
     FILE *nf;
@@ -146,8 +141,17 @@ afsconf_DeleteIdentity(struct afsconf_dir *adir, struct rx_identity *user)
 
     memset(&identity, 0, sizeof(struct rx_identity));
 
+    buffer = malloc(AFSDIR_PATH_MAX);
+    if (buffer == NULL)
+       return ENOMEM;
+    filename = malloc(AFSDIR_PATH_MAX);
+    if (filename == NULL) {
+       free(buffer);
+       return ENOMEM;
+    }
+
     LOCK_GLOBAL_MUTEX;
-    UserListFileName(adir, tbuffer, sizeof tbuffer);
+    UserListFileName(adir, filename, AFSDIR_PATH_MAX);
 #ifndef AFS_NT40_ENV
     {
        /*
@@ -155,40 +159,61 @@ afsconf_DeleteIdentity(struct afsconf_dir *adir, struct rx_identity *user)
         * of the temporary file will work even if UserList is a symlink
         * into a different filesystem.
         */
-       char resolved_path[1024];
-
-       if (realpath(tbuffer, resolved_path)) {
-           strcpy(tbuffer, resolved_path);
+       nfilename = malloc(AFSDIR_PATH_MAX);
+       if (nfilename == NULL) {
+           UNLOCK_GLOBAL_MUTEX;
+           free(filename);
+           free(buffer);
+           return ENOMEM;
+       }
+       if (realpath(filename, nfilename)) {
+           free(filename);
+           filename = nfilename;
+       } else {
+           free(nfilename);
        }
     }
 #endif /* AFS_NT40_ENV */
-    tf = fopen(tbuffer, "r");
+    if (asprintf(&nfilename, "%s.NXX", filename) < 0) {
+       UNLOCK_GLOBAL_MUTEX;
+       free(filename);
+       free(buffer);
+       return -1;
+    }
+    tf = fopen(filename, "r");
     if (!tf) {
        UNLOCK_GLOBAL_MUTEX;
+       free(filename);
+       free(nfilename);
+       free(buffer);
        return -1;
     }
-    code = stat(tbuffer, &tstat);
+    code = stat(filename, &tstat);
     if (code < 0) {
        UNLOCK_GLOBAL_MUTEX;
+       free(filename);
+       free(nfilename);
+       free(buffer);
        return code;
     }
-    strcpy(nbuffer, tbuffer);
-    strcat(nbuffer, ".NXX");
-    nf = fopen(nbuffer, "w+");
+    nf = fopen(nfilename, "w+");
     if (!nf) {
        fclose(tf);
        UNLOCK_GLOBAL_MUTEX;
+       free(filename);
+       free(nfilename);
+       free(buffer);
        return EIO;
     }
     flag = 0;
     found = 0;
     while (1) {
        /* check for our user id */
-       tp = fgets(nbuffer, sizeof(nbuffer), tf);
+       tp = fgets(buffer, AFSDIR_PATH_MAX, tf);
        if (tp == NULL)
            break;
 
-       copy = strdup(nbuffer);
+       copy = strdup(buffer);
        if (copy == NULL) {
            flag = 1;
            break;
@@ -199,28 +224,29 @@ afsconf_DeleteIdentity(struct afsconf_dir *adir, struct rx_identity *user)
            found = 1;
        } else {
            /* otherwise copy original line to output */
-           fprintf(nf, "%s", nbuffer);
+           fprintf(nf, "%s", buffer);
        }
        free(copy);
        rx_identity_freeContents(&identity);
     }
     fclose(tf);
+    free(buffer);
     if (ferror(nf))
        flag = 1;
     if (fclose(nf) == EOF)
        flag = 1;
-    strcpy(nbuffer, tbuffer);
-    strcat(nbuffer, ".NXX");   /* generate new file name again */
     if (flag == 0) {
        /* try the rename */
-       flag = renamefile(nbuffer, tbuffer);
+       flag = rk_rename(nfilename, filename);
        if (flag == 0)
-           flag = chmod(tbuffer, tstat.st_mode);
+           flag = chmod(filename, tstat.st_mode);
     } else
-       unlink(nbuffer);
+       unlink(nfilename);
 
     /* finally, decide what to return to the caller */
     UNLOCK_GLOBAL_MUTEX;
+    free(filename);
+    free(nfilename);
     if (flag)
        return EIO;             /* something mysterious went wrong */
     if (!found)
@@ -274,19 +300,24 @@ GetNthIdentityOrUser(struct afsconf_dir *dir, int count,
                     struct rx_identity **identity, int id)
 {
     bufio_p bp;
-    char tbuffer[1024];
+    char *tbuffer;
     struct rx_identity fileUser;
     afs_int32 code;
 
+    tbuffer = malloc(AFSDIR_PATH_MAX);
+    if (tbuffer == NULL)
+       return ENOMEM;
+
     LOCK_GLOBAL_MUTEX;
-    UserListFileName(dir, tbuffer, sizeof(tbuffer));
+    UserListFileName(dir, tbuffer, AFSDIR_PATH_MAX);
     bp = BufioOpen(tbuffer, O_RDONLY, 0);
     if (!bp) {
        UNLOCK_GLOBAL_MUTEX;
+       free(tbuffer);
        return EIO;
     }
     while (1) {
-       code = BufioGets(bp, tbuffer, sizeof(tbuffer));
+       code = BufioGets(bp, tbuffer, AFSDIR_PATH_MAX);
        if (code < 0)
            break;
 
@@ -310,6 +341,7 @@ GetNthIdentityOrUser(struct afsconf_dir *dir, int count,
     BufioClose(bp);
 
     UNLOCK_GLOBAL_MUTEX;
+    free(tbuffer);
     return code;
 }
 
@@ -461,18 +493,24 @@ afsconf_IsSuperIdentity(struct afsconf_dir *adir,
                        struct rx_identity *user)
 {
     bufio_p bp;
-    char tbuffer[1024];
+    char *tbuffer;
     struct rx_identity fileUser;
     int match;
     afs_int32 code;
 
-    UserListFileName(adir, tbuffer, sizeof tbuffer);
+    tbuffer = malloc(AFSDIR_PATH_MAX);
+    if (tbuffer == NULL)
+       return 0;
+
+    UserListFileName(adir, tbuffer, AFSDIR_PATH_MAX);
     bp = BufioOpen(tbuffer, O_RDONLY, 0);
-    if (!bp)
+    if (!bp) {
+       free(tbuffer);
        return 0;
+    }
     match = 0;
     while (!match) {
-       code = BufioGets(bp, tbuffer, sizeof(tbuffer));
+       code = BufioGets(bp, tbuffer, AFSDIR_PATH_MAX);
         if (code < 0)
            break;
 
@@ -485,6 +523,7 @@ afsconf_IsSuperIdentity(struct afsconf_dir *adir,
        rx_identity_freeContents(&fileUser);
     }
     BufioClose(bp);
+    free(tbuffer);
     return match;
 }
 
@@ -495,7 +534,7 @@ afsconf_AddIdentity(struct afsconf_dir *adir, struct rx_identity *user)
     FILE *tf;
     afs_int32 code;
     char *ename;
-    char tbuffer[256];
+    char *tbuffer;
 
     LOCK_GLOBAL_MUTEX;
     if (afsconf_IsSuperIdentity(adir, user)) {
@@ -503,8 +542,10 @@ afsconf_AddIdentity(struct afsconf_dir *adir, struct rx_identity *user)
        return EEXIST;          /* already in the list */
     }
 
-    UserListFileName(adir, tbuffer, sizeof tbuffer);
+    tbuffer = malloc(AFSDIR_PATH_MAX);
+    UserListFileName(adir, tbuffer, AFSDIR_PATH_MAX);
     tf = fopen(tbuffer, "a+");
+    free(tbuffer);
     if (!tf) {
        UNLOCK_GLOBAL_MUTEX;
        return EIO;
@@ -558,7 +599,9 @@ CompFindUser(struct afsconf_dir *adir, char *name, char *sep, char *inst,
     if (!name || !name[0]) {
        return 0;
     }
-    strcpy(fullname, name);
+
+    if (strlcpy(fullname, name, sizeof(fullname)) >= sizeof(fullname))
+       return 0;
 
     /* might have instance */
     if (inst && inst[0]) {
@@ -566,14 +609,20 @@ CompFindUser(struct afsconf_dir *adir, char *name, char *sep, char *inst,
            return 0;
        }
 
-       strcat(fullname, sep);
-       strcat(fullname, inst);
+       if (strlcat(fullname, sep, sizeof(fullname)) >= sizeof(fullname))
+           return 0;
+
+       if (strlcat(fullname, inst, sizeof(fullname)) >= sizeof(fullname))
+           return 0;
     }
 
     /* might have realm */
     if (realm && realm[0]) {
-       strcat(fullname, "@");
-       strcat(fullname, realm);
+       if (strlcat(fullname, "@", sizeof(fullname)) >= sizeof(fullname))
+           return 0;
+
+       if (strlcat(fullname, realm, sizeof(fullname)) >= sizeof(fullname))
+           return 0;
     }
 
     testId = rx_identity_new(RX_ID_KRB4, fullname, fullname, strlen(fullname));
@@ -594,65 +643,17 @@ kerberosSuperUser(struct afsconf_dir *adir, char *tname, char *tinst,
                  char *tcell, struct rx_identity **identity)
 {
     char tcell_l[MAXKTCREALMLEN] = "";
-    char *tmp;
-    static char lcell[MAXCELLCHARS] = "";
-    static char lrealms[AFS_NUM_LREALMS][AFS_REALM_SZ];
-    static int  num_lrealms = -1;
-    int lrealm_match = 0, i;
+    int code;
+    afs_int32 islocal;
     int flag;
 
     /* generate lowercased version of cell name */
-    if (tcell) {
-       strcpy(tcell_l, tcell);
-       tmp = tcell_l;
-       while (*tmp) {
-           *tmp = tolower(*tmp);
-           tmp++;
-       }
-    }
+    if (tcell)
+       opr_lcstring(tcell_l, tcell, sizeof(tcell_l));
 
-    /* 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;
-       }
-
-       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) {
-       char uname[MAXKTCNAMELEN + MAXKTCNAMELEN + MAXKTCREALMLEN + 3];
-       if (tinst && 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;
+    code = afsconf_IsLocalRealmMatch(adir, &islocal, tname, tinst, tcell);
+    if (code) {
+       return 0;
     }
 
     /* start with no authorization */
@@ -668,7 +669,7 @@ kerberosSuperUser(struct afsconf_dir *adir, char *tname, char *tinst,
        flag = 1;
 
        /* cell of connection matches local cell or one of the realms */
-    } else if (!strcasecmp(tcell, lcell) || lrealm_match) {
+    } else if (islocal) {
        if (CompFindUser(adir, tname, ".", tinst, NULL, identity)) {
            flag = 1;
        }
@@ -696,8 +697,8 @@ rxkadSuperUser(struct afsconf_dir *adir, struct rx_call *acall,
     int code;
 
     /* get auth details from server connection */
-    code = rxkad_GetServerInfo(acall->conn, NULL, &exp, tname, tinst, tcell,
-                              NULL);
+    code = rxkad_GetServerInfo(rx_ConnectionOf(acall), NULL, &exp, tname,
+                              tinst, tcell, NULL);
     if (code)
        return 0;               /* bogus connection/other error */