/*
* 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
*/
-#include <afs/param.h>
#include <afsconfig.h>
+#include <afs/param.h>
+#include <afs/stds.h>
-RCSID("$Header$");
+#include <roken.h>
+#include <afs/opr.h>
-#include <afs/stds.h>
-#include <afs/pthread_glock.h>
-#include <sys/types.h>
-#ifdef AFS_NT40_ENV
-#include <winsock2.h>
-#include <fcntl.h>
-#include <io.h>
-#else
-#include <sys/file.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#endif
-#include <sys/stat.h>
-#include <stdlib.h> /* for realpath() */
-#include <errno.h>
-#include <string.h>
#include <ctype.h>
+#include <afs/pthread_glock.h>
#include <rx/xdr.h>
#include <rx/rx.h>
-#include <stdio.h>
+#include <rx/rx_identity.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"
#include "keys.h"
#include "afs/audit.h"
-afs_int32 afsconf_SuperUser();
+/* The display names for localauth and noauth identities; they aren't used
+ * inside tickets or anything, but just serve as something to display in logs,
+ * etc. */
+#define AFS_LOCALAUTH_NAME "<LocalAuth>"
+#define AFS_LOCALAUTH_LEN (sizeof(AFS_LOCALAUTH_NAME)-1)
+#define AFS_NOAUTH_NAME "<NoAuth>"
+#define AFS_NOAUTH_LEN (sizeof(AFS_NOAUTH_NAME)-1)
+
+static int ParseLine(char *buffer, struct rx_identity *user);
+
+static void
+UserListFileName(struct afsconf_dir *adir,
+ char *buffer, size_t len)
+{
+ strcompose(buffer, len, adir->name, "/", AFSDIR_ULIST_FILE, (char *)NULL);
+}
#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; {
- register afs_int32 code;
-
- LOCK_GLOBAL_MUTEX
+void
+afsconf_SetNoAuthFlag(struct afsconf_dir *adir, int aflag)
+{
+ afs_int32 code;
+ 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; {
- char tbuffer[1024];
- char nbuffer[1024];
- register FILE *tf;
- register FILE *nf;
- register int flag;
- char tname[64];
+/*!
+ * Remove an identity from the UserList file
+ *
+ * This function removes the given identity from the user list file.
+ * For the purposes of identifying entries to remove, only the
+ * type and exportedName portions of the identity are used. Callers
+ * should remember that a given identity may be listed in the file in
+ * a number of different ways.
+ *
+ * @param adir
+ * A structure representing the configuration directory currently
+ * in use
+ * @param user
+ * The RX identity to delete
+ *
+ * @returns
+ * 0 on success, an error code on failure
+ */
+
+int
+afsconf_DeleteIdentity(struct afsconf_dir *adir, struct rx_identity *user)
+{
+ char *filename, *nfilename;
+ char *buffer;
+ char *copy;
+ FILE *tf;
+ FILE *nf;
+ int flag;
char *tp;
int found;
struct stat tstat;
- register afs_int32 code;
+ struct rx_identity identity;
+ afs_int32 code;
+
+ 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
- strcompose(tbuffer, sizeof tbuffer, adir->name, "/", AFSDIR_ULIST_FILE, NULL);
+ LOCK_GLOBAL_MUTEX;
+ UserListFileName(adir, filename, AFSDIR_PATH_MAX);
#ifndef AFS_NT40_ENV
{
/*
* 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
+ 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
+ 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
+ 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);
- if (tp == (char *)0) break;
- code = sscanf(nbuffer, "%64s", tname);
- if (code == 1 && strcmp(tname, auser) == 0) {
+ tp = fgets(buffer, AFSDIR_PATH_MAX, tf);
+ if (tp == NULL)
+ break;
+
+ copy = strdup(buffer);
+ if (copy == NULL) {
+ flag = 1;
+ break;
+ }
+ code = ParseLine(copy, &identity);
+ if (code == 0 && rx_identity_match(user, &identity)) {
/* found the guy, don't copy to output file */
found = 1;
+ } else {
+ /* otherwise copy original line to output */
+ fprintf(nf, "%s", buffer);
}
- else {
- /* otherwise copy original line to output */
- fprintf(nf, "%s", nbuffer);
- }
+ free(copy);
+ rx_identity_freeContents(&identity);
}
fclose(tf);
- if (ferror(nf)) flag = 1;
- if (fclose(nf) == EOF) flag = 1;
- strcpy(nbuffer, tbuffer);
- strcat(nbuffer, ".NXX"); /* generate new file name again */
+ free(buffer);
+ if (ferror(nf))
+ flag = 1;
+ if (fclose(nf) == EOF)
+ flag = 1;
if (flag == 0) {
/* try the rename */
- flag = renamefile(nbuffer, tbuffer);
+ flag = rk_rename(nfilename, filename);
if (flag == 0)
- flag = chmod(tbuffer, tstat.st_mode);
- }
- else unlink(nbuffer);
+ flag = chmod(filename, tstat.st_mode);
+ } else
+ unlink(nfilename);
/* 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;
+ free(filename);
+ free(nfilename);
+ 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; {
- char tbuffer[256];
- register FILE *tf;
- char tname[64];
- register char *tp;
- register int flag;
- register afs_int32 code;
-
- LOCK_GLOBAL_MUTEX
- strcompose(tbuffer, sizeof tbuffer, adir->name, "/", AFSDIR_ULIST_FILE, NULL);
- tf = fopen(tbuffer, "r");
- if (!tf) {
- UNLOCK_GLOBAL_MUTEX
- return 1;
+/*!
+ * Remove a legacy Kerberos 4 name from the UserList file.
+ *
+ * This function removes a Kerberos 4 name from the super user list. It
+ * can only remove names which were added by the afsconf_AddUser interface,
+ * or with an explicit Kerberos v4 type.
+ *
+ * @param[in] adir
+ * A structure representing the configuration directory
+ * @param[in] name
+ * The Kerberos v4 name to remove
+ *
+ * @returns
+ * 0 on success, an error code upon failure.
+ *
+ * Note that this function is deprecated. New callers should use
+ * afsconf_DeleteIdentity instead.
+ */
+
+int
+afsconf_DeleteUser(struct afsconf_dir *adir, char *name)
+{
+ struct rx_identity *user;
+ int code;
+
+ user = rx_identity_new(RX_ID_KRB4, name, name, strlen(name));
+ if (!user)
+ return ENOMEM;
+
+ code = afsconf_DeleteIdentity(adir, user);
+
+ rx_identity_free(&user);
+
+ return code;
+}
+
+/* This is a multi-purpose funciton for use by either
+ * GetNthIdentity or GetNthUser. The parameter 'id' indicates
+ * whether we are counting all identities (if true), or just
+ * ones which can be represented by the old-style interfaces
+ */
+static int
+GetNthIdentityOrUser(struct afsconf_dir *dir, int count,
+ struct rx_identity **identity, int id)
+{
+ bufio_p bp;
+ 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, AFSDIR_PATH_MAX);
+ bp = BufioOpen(tbuffer, O_RDONLY, 0);
+ if (!bp) {
+ UNLOCK_GLOBAL_MUTEX;
+ free(tbuffer);
+ return EIO;
}
- flag = 1;
while (1) {
- /* check for our user id */
- tp = fgets(tbuffer, sizeof(tbuffer), tf);
- if (tp == (char *)0) break;
- code = sscanf(tbuffer, "%64s", tname);
- if (code == 1 && an-- == 0) {
- flag = 0;
+ code = BufioGets(bp, tbuffer, AFSDIR_PATH_MAX);
+ if (code < 0)
+ break;
+
+ code = ParseLine(tbuffer, &fileUser);
+ if (code != 0)
+ break;
+
+ if (id || fileUser.kind == RX_ID_KRB4)
+ count--;
+
+ if (count < 0)
break;
+ else
+ rx_identity_freeContents(&fileUser);
+ }
+ if (code == 0) {
+ *identity = rx_identity_copy(&fileUser);
+ rx_identity_freeContents(&fileUser);
+ }
+
+ BufioClose(bp);
+
+ UNLOCK_GLOBAL_MUTEX;
+ free(tbuffer);
+ return code;
+}
+
+/*!
+ * Return the Nth super user identity from the UserList
+ *
+ * @param[in] dir
+ * A structure representing the configuration directory
+ * @param[in] count
+ * A count (from zero) of the entries to return from the
+ * UserList
+ * @param[out] identity
+ * A pointer to the Nth identity
+ * @returns
+ * 0 on success, non-zero on failure
+ */
+
+int
+afsconf_GetNthIdentity(struct afsconf_dir *dir, int count,
+ struct rx_identity **identity)
+{
+ return GetNthIdentityOrUser(dir, count, identity, 1);
+}
+
+/*!
+ * Return the Nth Kerberos v4 identity from the UserList
+ *
+ * This returns the Nth old, kerberos v4 style name from
+ * the UserList file. In counting entries it skips any other
+ * name types it encounters - so will hide any new-style
+ * identities from its callers.
+ *
+ * @param[in] dir
+ * A structure representing the configuration directory
+ * @param[in] count
+ * A count (from zero) of the entries to return from the
+ * UserList
+ * @param abuffer
+ * A string in which to write the name of the Nth identity
+ * @param abufferLen
+ * The length of the buffer passed in abuffer
+ * @returns
+ * 0 on success, non-zero on failure
+ *
+ * This function is deprecated, all new callers should use
+ * GetNthIdentity instead. This function is particularly dangerous
+ * as it will hide any new-style identities from callers.
+ */
+
+int
+afsconf_GetNthUser(struct afsconf_dir *adir, afs_int32 an, char *abuffer,
+ afs_int32 abufferLen)
+{
+ struct rx_identity *identity;
+ int code;
+
+ code = GetNthIdentityOrUser(adir, an, &identity, 0);
+ if (code == 0) {
+ strlcpy(abuffer, identity->displayName, abufferLen);
+ rx_identity_free(&identity);
+ }
+ return code;
+}
+
+/*!
+ * Parse a UserList list
+ *
+ * Parse a line of data from a UserList file
+ *
+ * This parses a line of data in a UserList, and populates the passed
+ * rx_identity structure with the information about the user.
+ *
+ * @param buffer A string containing the line to be parsed
+ * @param user The user structure to be populated
+ *
+ * Note that the user->displayName, and user->exportedName.val fields
+ * must be freed with free() by the caller.
+ *
+ * This function damages the buffer thats passed to it. Callers are
+ * expected to make a copy if they want the buffer preserved.
+ *
+ * @return
+ * 0 on success, non-zero on failure.
+ */
+
+static int
+ParseLine(char *buffer, struct rx_identity *user)
+{
+ char *ptr;
+ char *ename;
+ char *displayName;
+ char *decodedName;
+ char name[64+1];
+ int len;
+ int kind;
+ int code;
+
+ if (buffer[0] == ' ') { /* extended names have leading space */
+ ptr = buffer + 1;
+ code = sscanf(ptr, "%i", &kind);
+ if (code != 1)
+ return EINVAL;
+
+ strsep(&ptr, " "); /* skip the bit we just read with scanf */
+ ename = strsep(&ptr, " "); /* Pull out the ename */
+ displayName = strsep(&ptr, " "); /* Display name runs to the end */
+ if (ename == NULL || displayName == NULL)
+ return EINVAL;
+
+ decodedName = malloc(strlen(ename));
+ if (decodedName == NULL)
+ return ENOMEM;
+
+ len = base64_decode(ename, decodedName);
+ if (len<0) {
+ free(decodedName);
+ return EINVAL;
}
+
+ rx_identity_populate(user, kind, displayName, decodedName, len);
+ free(decodedName);
+
+ return 0; /* Success ! */
}
- if (flag == 0) strcpy(abuffer, tname);
- fclose(tf);
- UNLOCK_GLOBAL_MUTEX
- return flag;
+
+ /* No extended name, try for a legacy name */
+ code = sscanf(buffer, "%64s", name);
+ if (code != 1)
+ return EINVAL;
+
+ rx_identity_populate(user, RX_ID_KRB4, name, name, strlen(name));
+ return 0;
}
-/* returns true iff user is in the UserList file */
-static FindUser(adir, auser)
-struct afsconf_dir *adir;
-register char *auser; {
- char tbuffer[256];
- register bufio_p bp;
- char tname[64];
- register char *tp;
- register int flag;
- register afs_int32 code;
- int rc;
+/*!
+ * Check if a given identity is in the UserList file,
+ * and thus is a super user
+ *
+ * @param adir
+ * A structure representing the configuration directory to check
+ * @param user
+ * The identity to check
+ * @returns
+ * True if the user is listed in the UserList, otherwise false
+ */
+
+int
+afsconf_IsSuperIdentity(struct afsconf_dir *adir,
+ struct rx_identity *user)
+{
+ bufio_p bp;
+ char *tbuffer;
+ struct rx_identity fileUser;
+ int match;
+ afs_int32 code;
+
+ tbuffer = malloc(AFSDIR_PATH_MAX);
+ if (tbuffer == NULL)
+ return 0;
- strcompose(tbuffer, sizeof tbuffer, adir->name, "/", AFSDIR_ULIST_FILE, NULL);
+ UserListFileName(adir, tbuffer, AFSDIR_PATH_MAX);
bp = BufioOpen(tbuffer, O_RDONLY, 0);
- if (!bp) return 0;
- flag = 0;
- while (1) {
- /* check for our user id */
- rc = BufioGets(bp, tbuffer, sizeof(tbuffer));
- if (rc < 0) break;
- code = sscanf(tbuffer, "%64s", tname);
- if (code == 1 && strcmp(tname, auser) == 0) {
- flag = 1;
+ if (!bp) {
+ free(tbuffer);
+ return 0;
+ }
+ match = 0;
+ while (!match) {
+ code = BufioGets(bp, tbuffer, AFSDIR_PATH_MAX);
+ if (code < 0)
break;
- }
+
+ code = ParseLine(tbuffer, &fileUser);
+ if (code != 0)
+ break;
+
+ match = rx_identity_match(user, &fileUser);
+
+ rx_identity_freeContents(&fileUser);
}
BufioClose(bp);
- return flag;
+ free(tbuffer);
+ return match;
}
/* add a user to the user list, checking for duplicates */
-afsconf_AddUser(adir, aname)
-struct afsconf_dir *adir;
-char *aname; {
+int
+afsconf_AddIdentity(struct afsconf_dir *adir, struct rx_identity *user)
+{
FILE *tf;
- register afs_int32 code;
- char tbuffer[256];
-
- LOCK_GLOBAL_MUTEX
- if (FindUser(adir, aname)) {
- UNLOCK_GLOBAL_MUTEX
- return EEXIST; /* already in the list */
+ afs_int32 code;
+ char *ename;
+ char *tbuffer;
+
+ LOCK_GLOBAL_MUTEX;
+ if (afsconf_IsSuperIdentity(adir, user)) {
+ UNLOCK_GLOBAL_MUTEX;
+ return EEXIST; /* already in the list */
}
- strcompose(tbuffer, sizeof tbuffer, adir->name, "/", AFSDIR_ULIST_FILE, NULL);
+ tbuffer = malloc(AFSDIR_PATH_MAX);
+ UserListFileName(adir, tbuffer, AFSDIR_PATH_MAX);
tf = fopen(tbuffer, "a+");
+ free(tbuffer);
if (!tf) {
- UNLOCK_GLOBAL_MUTEX
+ UNLOCK_GLOBAL_MUTEX;
return EIO;
}
- fprintf(tf, "%s\n", aname);
+ if (user->kind == RX_ID_KRB4) {
+ fprintf(tf, "%s\n", user->displayName);
+ } else {
+ base64_encode(user->exportedName.val, user->exportedName.len,
+ &ename);
+ fprintf(tf, " %d %s %s\n", user->kind, ename, user->displayName);
+ free(ename);
+ }
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;
+}
+
+int
+afsconf_AddUser(struct afsconf_dir *adir, char *aname)
+{
+ struct rx_identity *user;
+ int code;
+
+ user = rx_identity_new(RX_ID_KRB4, aname, aname, strlen(aname));
+ if (user == NULL)
+ return ENOMEM;
+
+ code = afsconf_AddIdentity(adir, user);
+
+ rx_identity_free(&user);
+
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;
+static int
+CompFindUser(struct afsconf_dir *adir, char *name, char *sep, char *inst,
+ char *realm, struct rx_identity **identity)
{
- static char fullname[ MAXKTCNAMELEN + MAXKTCNAMELEN +
- MAXKTCREALMLEN + 3 ];
+ static char fullname[MAXKTCNAMELEN + MAXKTCNAMELEN + MAXKTCREALMLEN + 3];
+ struct rx_identity *testId;
/* always must have name */
- if ( !name || !name[0] ) { return NULL; }
- strcpy(fullname, name);
+ if (!name || !name[0]) {
+ return 0;
+ }
+
+ if (strlcpy(fullname, name, sizeof(fullname)) >= sizeof(fullname))
+ return 0;
/* might have instance */
- if ( inst && inst[0] ) {
- if ( !sep || !sep[0] ) { return NULL; }
+ if (inst && inst[0]) {
+ if (!sep || !sep[0]) {
+ return 0;
+ }
+
+ if (strlcat(fullname, sep, sizeof(fullname)) >= sizeof(fullname))
+ return 0;
- strcat(fullname, sep);
- strcat(fullname, inst);
+ if (strlcat(fullname, inst, sizeof(fullname)) >= sizeof(fullname))
+ return 0;
}
/* might have realm */
- if ( realm && realm[0] )
- {
- strcat(fullname, "@");
- strcat(fullname, realm);
+ if (realm && realm[0]) {
+ if (strlcat(fullname, "@", sizeof(fullname)) >= sizeof(fullname))
+ return 0;
+
+ if (strlcat(fullname, realm, sizeof(fullname)) >= sizeof(fullname))
+ return 0;
}
- if ( FindUser(adir, fullname) ) {
- return fullname;
+ testId = rx_identity_new(RX_ID_KRB4, fullname, fullname, strlen(fullname));
+ if (afsconf_IsSuperIdentity(adir, testId)) {
+ if (identity)
+ *identity = testId;
+ else
+ rx_identity_free(&testId);
+ return 1;
+ }
+
+ rx_identity_free(&testId);
+ return 0;
+}
+
+static int
+kerberosSuperUser(struct afsconf_dir *adir, char *tname, char *tinst,
+ char *tcell, struct rx_identity **identity)
+{
+ char tcell_l[MAXKTCREALMLEN] = "";
+ int code;
+ afs_int32 islocal;
+ int flag;
+
+ /* generate lowercased version of cell name */
+ if (tcell)
+ opr_lcstring(tcell_l, tcell, sizeof(tcell_l));
+
+ code = afsconf_IsLocalRealmMatch(adir, &islocal, tname, tinst, tcell);
+ if (code) {
+ return 0;
+ }
+
+ /* start with no authorization */
+ flag = 0;
+
+ /* localauth special case */
+ if ((tinst == NULL || strlen(tinst) == 0) &&
+ (tcell == NULL || strlen(tcell) == 0)
+ && !strcmp(tname, AUTH_SUPERUSER)) {
+ if (identity)
+ *identity = rx_identity_new(RX_ID_KRB4, AFS_LOCALAUTH_NAME,
+ AFS_LOCALAUTH_NAME, AFS_LOCALAUTH_LEN);
+ flag = 1;
+
+ /* cell of connection matches local cell or one of the realms */
+ } else if (islocal) {
+ if (CompFindUser(adir, tname, ".", tinst, NULL, identity)) {
+ flag = 1;
+ }
+ /* cell of conn doesn't match local cell or realm */
} else {
- return NULL;
+ if (CompFindUser(adir, tname, ".", tinst, tcell, identity)) {
+ flag = 1;
+ } else if (CompFindUser(adir, tname, ".", tinst, tcell_l, identity)) {
+ flag = 1;
+ }
}
+
+ return flag;
}
+static int
+rxkadSuperUser(struct afsconf_dir *adir, struct rx_call *acall,
+ struct rx_identity **identity)
+{
+ char tname[MAXKTCNAMELEN]; /* authentication from ticket */
+ char tinst[MAXKTCNAMELEN];
+ char tcell[MAXKTCREALMLEN];
+
+ afs_uint32 exp;
+ int code;
-/* 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; {
- register struct rx_connection *tconn;
- register afs_int32 code;
+ /* get auth details from server connection */
+ code = rxkad_GetServerInfo(rx_ConnectionOf(acall), NULL, &exp, tname,
+ tinst, tcell, NULL);
+ if (code)
+ return 0; /* bogus connection/other error */
+
+ return kerberosSuperUser(adir, tname, tinst, tcell, identity);
+}
+
+/*!
+ * Check whether the user authenticated on a given RX call is a super
+ * user or not. If they are, return a pointer to the identity of that
+ * user.
+ *
+ * @param[in] adir
+ * The configuration directory currently in use
+ * @param[in] acall
+ * The RX call whose authenticated identity is being checked
+ * @param[out] identity
+ * The RX identity of the user. Caller must free this structure.
+ * @returns
+ * True if the user is a super user, or if the server is running
+ * in noauth mode. Otherwise, false.
+ */
+afs_int32
+afsconf_SuperIdentity(struct afsconf_dir *adir, struct rx_call *acall,
+ struct rx_identity **identity)
+{
+ struct rx_connection *tconn;
+ 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 (identity)
+ *identity = rx_identity_new(RX_ID_KRB4, AFS_NOAUTH_NAME,
+ AFS_NOAUTH_NAME, AFS_NOAUTH_LEN);
+ 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 */
+ UNLOCK_GLOBAL_MUTEX;
+ return 0; /* not supported any longer */
+ } else if (code == 2) {
+ flag = rxkadSuperUser(adir, acall, identity);
+ UNLOCK_GLOBAL_MUTEX;
+ return flag;
+ } else { /* some other auth type */
+ UNLOCK_GLOBAL_MUTEX;
+ return 0; /* mysterious, just say no */
}
- 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];
-
- afs_uint32 exp;
- static char lcell[MAXCELLCHARS] = "";
- static char lrealm[AFS_REALM_SZ] = "";
-
- /* get auth details from server connection */
- code = rxkad_GetServerInfo
- (acall->conn, (afs_int32 *) 0, &exp,
- tname, tinst, tcell, (afs_int32 *) 0);
- if (code) {
- 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()) {
-#else
- if (exp < FT_ApproxTime()) {
-#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;
-#ifdef notyet
- } else if ( (tmp = CompFindUser(adir, tname, "/", tinst, NULL)) ) {
- strcpy(uname, tmp);
- flag = 1;
-#endif
- }
+/*!
+ * Check whether the user authenticated on a given RX call is a super
+ * user or not. If they are, return a pointer to the name of that
+ * user.
+ *
+ * @param[in] adir
+ * The configuration directory currently in use
+ * @param[in] acall
+ * The RX call whose authenticated identity is being checked
+ * @param[out] namep
+ * A printable version of the name of the user
+ * @returns
+ * True if the user is a super user, or if the server is running
+ * in noauth mode. Otherwise, false.
+ *
+ * This function is provided for backwards compatibility. New callers
+ * should use the afsconf_SuperIdentity function.
+ */
- /* 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;
-#endif
- } 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;
-#endif
+afs_int32
+afsconf_SuperUser(struct afsconf_dir *adir, struct rx_call *acall,
+ char *namep)
+{
+ struct rx_identity *identity;
+ int ret;
+
+ if (namep) {
+ ret = afsconf_SuperIdentity(adir, acall, &identity);
+ if (ret) {
+ if (identity->kind == RX_ID_KRB4) {
+ strlcpy(namep, identity->displayName, MAXKTCNAMELEN-1);
+ } else {
+ snprintf(namep, MAXKTCNAMELEN-1, "eName: %s",
+ identity->displayName);
}
+ rx_identity_free(&identity);
}
-
- if (namep)
- strcpy(namep, uname);
- UNLOCK_GLOBAL_MUTEX
- return flag;
- }
- else { /* some other auth type */
- UNLOCK_GLOBAL_MUTEX
- return 0; /* mysterious, just say no */
+ } else {
+ ret = afsconf_SuperIdentity(adir, acall, NULL);
}
+
+ return ret;
}