[OpenAFS-devel] Rewite of the auth/userok.c SuperUser check routine

Nathan Neulinger nneul@umr.edu
Fri, 11 May 2001 10:08:42 -0500


--gKMricLos+KVdGMg
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

This rewrite cleans up the code a bit, removes any athena specific 
references (not needed anymore in this version), and adds support for 
multi realm management of afs servers (you can now specify 
"admin@OTHERREALM" in your userlist).

Code now checks as follows:

tname
tinst  - remote user info from conn
tcell
lcell - local cell
lrealm - local realm (defaults to lcell if not avail)

if no remote cell or instance
	allow localauth
if the cell of the remote connection matches local cell or local realm
	if not tinst
		allow if tname in UserList
	if tinst
		allow if tname.tinst in UserList
		allow if tname/tinst in UserList
if cell doesn't match local cell or realm
	if not tinst
		allow if tname@cell in UserList
		allow if tname@CELL in UserList
	if tinst
		allow if tname.tinst@cell in UserList
		allow if tname/tinst@cell in UserList
		allow if tname.tinst@CELL in UserList
		allow if tname/tinst@CELL in UserList


note - it may not actually be "CELL". It basically checks for the 
tolower()'d version of the cell name. This way, you can either use the
same style as in pts (user@realm) or the typical krb5 style (user@REALM).

-- Nathan

------------------------------------------------------------
Nathan Neulinger                       EMail:  nneul@umr.edu
University of Missouri - Rolla         Phone: (573) 341-4841
Computing Services                       Fax: (573) 341-4216

--gKMricLos+KVdGMg
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="auth-userok.diff"

Index: auth/userok.c
===================================================================
RCS file: /cvs/openafs/src/auth/userok.c,v
retrieving revision 1.3
diff -u -r1.3 userok.c
--- auth/userok.c	2000/11/05 03:25:14	1.3
+++ auth/userok.c	2001/05/11 15:05:23
@@ -35,6 +35,8 @@
 #include <sys/stat.h>
 #include <stdlib.h>	/* for realpath() */
 #include <errno.h>
+#include <string.h>
+#include <ctype.h>
 
 #include <rx/xdr.h>
 #include <rx/rx.h>
@@ -287,10 +289,52 @@
     return code;
 }
 
+/* special CompFindUser routine that builds up a princ and then
+	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 fullname[ MAXKTCNAMELEN + MAXKTCNAMELEN +
+	MAXKTCREALMLEN + 3 ];
+
+    /* always must have name */
+    if ( !name || !name[0] ) { return NULL; }
+    strcpy(fullname, name);
+
+    /* might have instance */
+    if ( inst && inst[0] ) {
+	if ( !sep || !sep[0] ) { return NULL; }
+
+	strcat(fullname, sep);
+	strcat(fullname, inst);
+    }
+
+    /* might have realm */
+    if ( realm && realm[0] )
+    {
+	strcat(fullname, "@");
+	strcat(fullname, realm);
+    }
+
+    if ( FindUser(adir, fullname) ) {
+	return fullname;
+    } else {
+	return NULL;
+    }
+}
+
+
 /* make sure user authenticated on rx call acall is in list of valid
-    users.
+    users. Copy the "real name" of the authenticated user into namep
+    if a pointer is passed.
 */
-afsconf_SuperUser(adir, acall, namep)
+afs_int32 afsconf_SuperUser(adir, acall, namep)
 struct afsconf_dir *adir;
 struct rx_call *acall;
 char *namep; {
@@ -303,11 +347,13 @@
 	UNLOCK_GLOBAL_MUTEX
 	return 0;
     }
+
     if (afsconf_GetNoAuthFlag(adir)) {
-	if (namep) strcpy(namep, "<noauth>");
+	if (namep) strcpy(namep, "<NoAuth>");
 	UNLOCK_GLOBAL_MUTEX
 	return 1;
     }
+
     tconn = rx_ConnectionOf(acall);
     code = rx_SecurityClassOf(tconn);
     if (code ==	0) {
@@ -323,52 +369,26 @@
 	char tname[MAXKTCNAMELEN];	/* authentication from ticket */
 	char tinst[MAXKTCNAMELEN];
 	char tcell[MAXKTCREALMLEN];
-	char uname[MAXKTCNAMELEN];	/* name.instance */
-	int  ilen;			/* length of instance */
+	char tcell_l[MAXKTCREALMLEN];
+	char *tmp;
+	
+	/* keep track of which one actually authorized request */
+	char uname[MAXKTCNAMELEN+MAXKTCNAMELEN+MAXKTCREALMLEN+3];
+
 	afs_uint32 exp;
-	static char localcellname[MAXCELLCHARS] = "";
-#if	defined(AFS_ATHENA_STDENV) || defined(AFS_KERBREALM_ENV)
-	static char local_realm[AFS_REALM_SZ] = "";
-#endif
+	static char lcell[MAXCELLCHARS] = "";
+	static char lrealm[AFS_REALM_SZ] = "";
 	
-	/* des tokens */
+	/* get auth details from server connection */
 	code = rxkad_GetServerInfo
-	    (acall->conn, (afs_int32 *) 0, &exp, tname, tinst, tcell, (afs_int32 *) 0);
+	    (acall->conn, (afs_int32 *) 0, &exp, 
+		tname, tinst, tcell, (afs_int32 *) 0);
 	if (code) {
 	    UNLOCK_GLOBAL_MUTEX
-	    return 0; /* bogus */
-	}
-
-	if (strlen (tcell)) {
-	    if (!localcellname[0])
-		afsconf_GetLocalCell
-		    (adir, localcellname, sizeof(localcellname));
-#if	defined(AFS_ATHENA_STDENV) || defined(AFS_KERBREALM_ENV)
-	    if (!local_realm[0]) {
-		if (afs_krb_get_lrealm(local_realm, 0) != 0/*KSUCCESS*/)
-		    strncpy(local_realm, localcellname, AFS_REALM_SZ);
-	    }
-	    if (strcasecmp(local_realm, tcell) &&
-	       (strcasecmp(localcellname, tcell)))
-#else
-	    if (strcasecmp(localcellname, tcell))
-#endif
-		{
-		    UNLOCK_GLOBAL_MUTEX
-		    return 0;
-		}
+	    return 0; /* bogus connection/other error */
 	}
-	ilen = strlen(tinst);
-	strncpy (uname, tname, sizeof(uname));
-	if (ilen) {
-	    if (strlen(uname) + 1 + ilen >= sizeof(uname)) {
-		UNLOCK_GLOBAL_MUTEX
-		return 0;
-	    }
-	    strcat (uname, ".");
-	    strcat (uname, tinst);
-	}
 
+	/* don't bother checking anything else if tix have expired */
 #ifdef AFS_PTHREAD_ENV
 	if (exp	< clock_Sec()) {
 #else
@@ -376,15 +396,70 @@
 #endif
 	    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++; }
+
+	/* 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);
+	}
+
+
+	/* 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;
+
+	/* 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;
+	    } else if ( (tmp = CompFindUser(adir, tname, "/", tinst, NULL)) ) {
+		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;
+	    } else if ( (tmp = CompFindUser(adir, tname, "/", tinst, tcell)) ) {
+		strcpy(uname, tmp);
+		flag = 1;
+	    } 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;
+	    }
 	}
-	if (strcmp(AUTH_SUPERUSER, uname) == 0) flag = 1;
-	else flag = FindUser(adir, uname);	/* true iff in userlist file */
+
 	if (namep)
 	    strcpy(namep, uname);
 	UNLOCK_GLOBAL_MUTEX
 	return flag;
     }
-    else {
+    else { /* some other auth type */
 	UNLOCK_GLOBAL_MUTEX
 	return	0;	    /* mysterious, just say no */
     }

--gKMricLos+KVdGMg--