mirror of
https://git.openafs.org/openafs.git
synced 2025-01-18 06:50:12 +00:00
auth: Allow identities in the UserList
Extend the userok interface provided by the auth library to permit the addition, deletion and inspection of identities within the UserList. A number of additional functions are added, as direct replacements for their Kerberos v4 only counterparts - these are: *) afsconf_DeleteIdentity *) afsconf_GetNthIdentity *) afsconf_AddIdentity *) afsconf_SuperIdentity In addition, a new function is added to allow the status of any given identity to be queried *) afsconf_IsSuperIdentity New form identities are stored within the same UserList file as Kerberos v4 identities. We take advantage of the fact that the current code skips any entry with a leading whitespace. Identities are stored as a single line, with a leading space, followed by the integer representation of their type (0 for Kerberos 4, 1 for GSSAPI), followed by the base64 encoded representation of their exported name, followed by the display name of the identity. Each field is whitespace separated. For example: 1 BAEACwYJKoZIhvcSAQICAAAAEHN4d0BJTkYuRUQuQUMuVUs= sxw@INF.ED.AC.UK is the representation of the GSSAPI identity "sxw@INF.ED.AC.UK" An addition to the test suite is also provided which will test all of the existing, and new super user manipulation functions. Change-Id: I50648bb1ecc3037a90d623c87a60193be4f122ff Reviewed-on: http://gerrit.openafs.org/3355 Tested-by: BuildBot <buildbot@rampaginggeek.com> Reviewed-by: Derrick Brashear <shadow@dementia.org>
This commit is contained in:
parent
46a6d6129d
commit
0af17e7ecc
@ -893,6 +893,7 @@ distclean: clean
|
||||
src/tbutc/Makefile \
|
||||
src/tests/Makefile \
|
||||
src/tests/run-tests \
|
||||
src/tests/auth/Makefile \
|
||||
src/tsalvaged/Makefile \
|
||||
src/tsm41/Makefile \
|
||||
src/tviced/Makefile \
|
||||
|
@ -237,6 +237,7 @@ src/volser/Makefile \
|
||||
src/xstat/Makefile \
|
||||
src/helper-splint.sh \
|
||||
tests/Makefile \
|
||||
tests/auth/Makefile \
|
||||
tests/rpctestlib/Makefile \
|
||||
tests/tap/Makefile \
|
||||
tests/util/Makefile,
|
||||
|
@ -177,15 +177,23 @@ int afsconf_SetCellInfo(struct afsconf_dir *adir, const char *apath,
|
||||
/* userok.c */
|
||||
|
||||
struct rx_call;
|
||||
struct rx_identity;
|
||||
extern int afsconf_CheckAuth(void *arock, struct rx_call *acall);
|
||||
extern int afsconf_GetNoAuthFlag(struct afsconf_dir *adir);
|
||||
extern void afsconf_SetNoAuthFlag(struct afsconf_dir *adir, int aflag);
|
||||
extern int afsconf_DeleteUser(struct afsconf_dir *adir, char *auser);
|
||||
extern int afsconf_DeleteIdentity(struct afsconf_dir *, struct rx_identity *);
|
||||
extern int afsconf_GetNthUser(struct afsconf_dir *adir, afs_int32 an,
|
||||
char *abuffer, afs_int32 abufferLen);
|
||||
extern int afsconf_GetNthIdentity(struct afsconf_dir *, int,
|
||||
struct rx_identity **);
|
||||
extern int afsconf_AddUser(struct afsconf_dir *adir, char *aname);
|
||||
extern int afsconf_AddIdentity(struct afsconf_dir *adir, struct rx_identity *);
|
||||
extern int afsconf_SuperUser(struct afsconf_dir *adir, struct rx_call *acall,
|
||||
char *namep);
|
||||
extern int afsconf_SuperIdentity(struct afsconf_dir *, struct rx_call *,
|
||||
struct rx_identity **);
|
||||
extern int afsconf_IsSuperIdentity(struct afsconf_dir *, struct rx_identity *);
|
||||
|
||||
/* some well-known ports and their names; new additions to table in cellconfig.c, too */
|
||||
#define AFSCONF_FILESERVICE "afs"
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <afs/param.h>
|
||||
|
||||
#include <roken.h>
|
||||
#include "base64.h"
|
||||
|
||||
#include <afs/stds.h>
|
||||
#include <afs/pthread_glock.h>
|
||||
@ -33,6 +34,7 @@
|
||||
|
||||
#include <rx/xdr.h>
|
||||
#include <rx/rx.h>
|
||||
#include <rx/rx_identity.h>
|
||||
#include <stdio.h>
|
||||
#include <afs/afsutil.h>
|
||||
#include <afs/fileutil.h>
|
||||
@ -46,6 +48,16 @@
|
||||
#include "keys.h"
|
||||
#include "afs/audit.h"
|
||||
|
||||
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, NULL);
|
||||
}
|
||||
|
||||
#if !defined(UKERNEL)
|
||||
int
|
||||
afsconf_CheckAuth(void *arock, struct rx_call *acall)
|
||||
@ -105,24 +117,42 @@ afsconf_SetNoAuthFlag(struct afsconf_dir *adir, int aflag)
|
||||
UNLOCK_GLOBAL_MUTEX;
|
||||
}
|
||||
|
||||
/* deletes a user from the UserList file */
|
||||
/*!
|
||||
* 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_DeleteUser(struct afsconf_dir *adir, char *auser)
|
||||
afsconf_DeleteIdentity(struct afsconf_dir *adir, struct rx_identity *user)
|
||||
{
|
||||
char tbuffer[1024];
|
||||
char nbuffer[1024];
|
||||
char *copy;
|
||||
FILE *tf;
|
||||
FILE *nf;
|
||||
int flag;
|
||||
char tname[64 + 1];
|
||||
char *tp;
|
||||
int found;
|
||||
struct stat tstat;
|
||||
struct rx_identity identity;
|
||||
afs_int32 code;
|
||||
|
||||
LOCK_GLOBAL_MUTEX;
|
||||
strcompose(tbuffer, sizeof tbuffer, adir->name, "/",
|
||||
AFSDIR_ULIST_FILE, NULL);
|
||||
UserListFileName(adir, tbuffer, sizeof tbuffer);
|
||||
#ifndef AFS_NT40_ENV
|
||||
{
|
||||
/*
|
||||
@ -162,14 +192,22 @@ afsconf_DeleteUser(struct afsconf_dir *adir, char *auser)
|
||||
tp = fgets(nbuffer, sizeof(nbuffer), tf);
|
||||
if (tp == NULL)
|
||||
break;
|
||||
code = sscanf(nbuffer, "%64s", tname);
|
||||
if (code == 1 && strcmp(tname, auser) == 0) {
|
||||
|
||||
copy = strdup(nbuffer);
|
||||
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 */
|
||||
/* otherwise copy original line to output */
|
||||
fprintf(nf, "%s", nbuffer);
|
||||
}
|
||||
free(copy);
|
||||
rx_identity_freeContents(&identity);
|
||||
}
|
||||
fclose(tf);
|
||||
if (ferror(nf))
|
||||
@ -195,87 +233,278 @@ afsconf_DeleteUser(struct afsconf_dir *adir, char *auser)
|
||||
return 0; /* everything was fine */
|
||||
}
|
||||
|
||||
/* returns nth super user from the UserList file */
|
||||
/*!
|
||||
* 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[1024];
|
||||
struct rx_identity fileUser;
|
||||
afs_int32 code;
|
||||
|
||||
LOCK_GLOBAL_MUTEX;
|
||||
UserListFileName(dir, tbuffer, sizeof(tbuffer));
|
||||
bp = BufioOpen(tbuffer, O_RDONLY, 0);
|
||||
if (!bp) {
|
||||
UNLOCK_GLOBAL_MUTEX;
|
||||
return EIO;
|
||||
}
|
||||
while (1) {
|
||||
code = BufioGets(bp, tbuffer, sizeof(tbuffer));
|
||||
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;
|
||||
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)
|
||||
{
|
||||
char tbuffer[256];
|
||||
FILE *tf;
|
||||
char tname[64 + 1];
|
||||
char *tp;
|
||||
int flag;
|
||||
afs_int32 code;
|
||||
struct rx_identity *identity;
|
||||
int 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;
|
||||
code = GetNthIdentityOrUser(adir, an, &identity, 0);
|
||||
if (code == 0) {
|
||||
strlcpy(abuffer, identity->displayName, abufferLen);
|
||||
rx_identity_free(&identity);
|
||||
}
|
||||
flag = 1;
|
||||
while (1) {
|
||||
/* check for our user id */
|
||||
tp = fgets(tbuffer, sizeof(tbuffer), tf);
|
||||
if (tp == NULL)
|
||||
break;
|
||||
code = sscanf(tbuffer, "%64s", tname);
|
||||
if (code == 1 && an-- == 0) {
|
||||
flag = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (flag == 0)
|
||||
strcpy(abuffer, tname);
|
||||
fclose(tf);
|
||||
UNLOCK_GLOBAL_MUTEX;
|
||||
return flag;
|
||||
return code;
|
||||
}
|
||||
|
||||
/* returns true iff user is in the UserList file */
|
||||
/*!
|
||||
* 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
|
||||
FindUser(struct afsconf_dir *adir, char *auser)
|
||||
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 ! */
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/*!
|
||||
* 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)
|
||||
{
|
||||
char tbuffer[256];
|
||||
bufio_p bp;
|
||||
char tname[64 + 1];
|
||||
int flag;
|
||||
char tbuffer[1024];
|
||||
struct rx_identity fileUser;
|
||||
int match;
|
||||
afs_int32 code;
|
||||
int rc;
|
||||
|
||||
strcompose(tbuffer, sizeof tbuffer, adir->name, "/", AFSDIR_ULIST_FILE,
|
||||
NULL);
|
||||
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)
|
||||
match = 0;
|
||||
while (!match) {
|
||||
code = BufioGets(bp, tbuffer, sizeof(tbuffer));
|
||||
if (code < 0)
|
||||
break;
|
||||
code = sscanf(tbuffer, "%64s", tname);
|
||||
if (code == 1 && strcmp(tname, auser) == 0) {
|
||||
flag = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
code = ParseLine(tbuffer, &fileUser);
|
||||
if (code != 0)
|
||||
break;
|
||||
|
||||
match = rx_identity_match(user, &fileUser);
|
||||
|
||||
rx_identity_freeContents(&fileUser);
|
||||
}
|
||||
BufioClose(bp);
|
||||
return flag;
|
||||
return match;
|
||||
}
|
||||
|
||||
/* add a user to the user list, checking for duplicates */
|
||||
int
|
||||
afsconf_AddUser(struct afsconf_dir *adir, char *aname)
|
||||
afsconf_AddIdentity(struct afsconf_dir *adir, struct rx_identity *user)
|
||||
{
|
||||
FILE *tf;
|
||||
afs_int32 code;
|
||||
char *ename;
|
||||
char tbuffer[256];
|
||||
|
||||
LOCK_GLOBAL_MUTEX;
|
||||
if (FindUser(adir, aname)) {
|
||||
if (afsconf_IsSuperIdentity(adir, user)) {
|
||||
UNLOCK_GLOBAL_MUTEX;
|
||||
return EEXIST; /* already in the list */
|
||||
}
|
||||
@ -287,7 +516,14 @@ afsconf_AddUser(struct afsconf_dir *adir, char *aname)
|
||||
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;
|
||||
@ -297,26 +533,44 @@ afsconf_AddUser(struct afsconf_dir *adir, char *aname)
|
||||
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,
|
||||
otherwise returns NULL. The resulting string should be immediately
|
||||
copied to other storage prior to release of mutex. */
|
||||
static char *
|
||||
static int
|
||||
CompFindUser(struct afsconf_dir *adir, char *name, char *sep, char *inst,
|
||||
char *realm)
|
||||
char *realm, struct rx_identity **identity)
|
||||
{
|
||||
static char fullname[MAXKTCNAMELEN + MAXKTCNAMELEN + MAXKTCREALMLEN + 3];
|
||||
struct rx_identity *testId;
|
||||
|
||||
/* always must have name */
|
||||
if (!name || !name[0]) {
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
strcpy(fullname, name);
|
||||
|
||||
/* might have instance */
|
||||
if (inst && inst[0]) {
|
||||
if (!sep || !sep[0]) {
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
strcat(fullname, sep);
|
||||
@ -329,16 +583,22 @@ CompFindUser(struct afsconf_dir *adir, char *name, char *sep, char *inst,
|
||||
strcat(fullname, realm);
|
||||
}
|
||||
|
||||
if (FindUser(adir, fullname)) {
|
||||
return fullname;
|
||||
} else {
|
||||
return NULL;
|
||||
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, char *namep)
|
||||
char *tcell, struct rx_identity **identity)
|
||||
{
|
||||
char tcell_l[MAXKTCREALMLEN] = "";
|
||||
char *tmp;
|
||||
@ -418,44 +678,24 @@ kerberosSuperUser(struct afsconf_dir *adir, char *tname, char *tinst,
|
||||
|
||||
/* 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);
|
||||
if (CompFindUser(adir, tname, ".", tinst, NULL, identity)) {
|
||||
flag = 1;
|
||||
#ifdef notyet
|
||||
} 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);
|
||||
if (CompFindUser(adir, tname, ".", tinst, tcell, identity)) {
|
||||
flag = 1;
|
||||
#ifdef notyet
|
||||
} else if ((tmp = CompFindUser(adir, tname, "/", tinst, tcell))) {
|
||||
strcpy(uname, tmp);
|
||||
} else if (CompFindUser(adir, tname, ".", tinst, tcell_l, identity)) {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
if (namep)
|
||||
strcpy(namep, uname);
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
static int
|
||||
rxkadSuperUser(struct afsconf_dir *adir, struct rx_call *acall, char *namep)
|
||||
rxkadSuperUser(struct afsconf_dir *adir, struct rx_call *acall,
|
||||
struct rx_identity **identity)
|
||||
{
|
||||
char tname[MAXKTCNAMELEN]; /* authentication from ticket */
|
||||
char tinst[MAXKTCNAMELEN];
|
||||
@ -470,15 +710,27 @@ rxkadSuperUser(struct afsconf_dir *adir, struct rx_call *acall, char *namep)
|
||||
if (code)
|
||||
return 0; /* bogus connection/other error */
|
||||
|
||||
return kerberosSuperUser(adir, tname, tinst, tcell, namep);
|
||||
return kerberosSuperUser(adir, tname, tinst, tcell, identity);
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
/*!
|
||||
* 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_SuperUser(struct afsconf_dir *adir, struct rx_call *acall, char *namep)
|
||||
afsconf_SuperIdentity(struct afsconf_dir *adir, struct rx_call *acall,
|
||||
struct rx_identity **identity)
|
||||
{
|
||||
struct rx_connection *tconn;
|
||||
afs_int32 code;
|
||||
@ -491,8 +743,8 @@ afsconf_SuperUser(struct afsconf_dir *adir, struct rx_call *acall, char *namep)
|
||||
}
|
||||
|
||||
if (afsconf_GetNoAuthFlag(adir)) {
|
||||
if (namep)
|
||||
strcpy(namep, "<NoAuth>");
|
||||
if (identity)
|
||||
*identity = rx_identity_new(RX_ID_KRB4, "<NoAuth>", "<NoAuth>", 8);
|
||||
UNLOCK_GLOBAL_MUTEX;
|
||||
return 1;
|
||||
}
|
||||
@ -507,7 +759,7 @@ afsconf_SuperUser(struct afsconf_dir *adir, struct rx_call *acall, char *namep)
|
||||
UNLOCK_GLOBAL_MUTEX;
|
||||
return 0; /* not supported any longer */
|
||||
} else if (code == 2) {
|
||||
flag = rxkadSuperUser(adir, acall, namep);
|
||||
flag = rxkadSuperUser(adir, acall, identity);
|
||||
UNLOCK_GLOBAL_MUTEX;
|
||||
return flag;
|
||||
} else { /* some other auth type */
|
||||
@ -515,3 +767,43 @@ afsconf_SuperUser(struct afsconf_dir *adir, struct rx_call *acall, char *namep)
|
||||
return 0; /* mysterious, just say no */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* 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.
|
||||
*/
|
||||
|
||||
afs_int32
|
||||
afsconf_SuperUser(struct afsconf_dir *adir, struct rx_call *acall,
|
||||
char *namep)
|
||||
{
|
||||
struct rx_identity *identity;
|
||||
int code;
|
||||
|
||||
code = afsconf_SuperIdentity(adir, acall, &identity);
|
||||
if (namep) {
|
||||
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);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
@ -11,6 +11,8 @@ MODULE_CFLAGS = -DSOURCE='"$(abs_top_srcdir)/tests"' \
|
||||
|
||||
all: runtests
|
||||
cd tap && $(MAKE) $@
|
||||
cd auth && $(MAKE) $@
|
||||
cd rxgk && $(MAKE) $@
|
||||
cd util && $(MAKE) $@
|
||||
|
||||
runtests: runtests.o
|
||||
@ -18,6 +20,7 @@ runtests: runtests.o
|
||||
|
||||
check test tests: runtests
|
||||
cd tap && $(MAKE) $@
|
||||
cd auth && $(MAKE) $@
|
||||
cd util && $(MAKE) $@
|
||||
./runtests $(abs_top_srcdir)/tests/TESTS
|
||||
|
||||
@ -25,5 +28,6 @@ install:
|
||||
|
||||
clean distclean:
|
||||
cd tap && $(MAKE) $@
|
||||
cd auth && $(MAKE) $@
|
||||
cd util && $(MAKE) $@
|
||||
$(RM) -f *.o core runtests
|
||||
|
@ -1,2 +1,3 @@
|
||||
util/ktime
|
||||
util/exec-alt
|
||||
auth/superuser
|
||||
|
1
tests/auth/.gitignore
vendored
Normal file
1
tests/auth/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/superuser-t
|
22
tests/auth/Makefile.in
Normal file
22
tests/auth/Makefile.in
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
srcdir=@srcdir@
|
||||
abs_top_builddir=@abs_top_builddir@
|
||||
include @TOP_OBJDIR@/src/config/Makefile.config
|
||||
include @TOP_OBJDIR@/src/config/Makefile.pthread
|
||||
|
||||
TESTS = superuser-t
|
||||
|
||||
MODULE_CFLAGS=-I$(srcdir)/..
|
||||
|
||||
all check test tests: $(TESTS)
|
||||
|
||||
superuser-t: superuser-t.o
|
||||
$(AFS_LDRULE) superuser-t.o ../tap/libtap.a \
|
||||
$(abs_top_builddir)/lib/libafsauthent.a \
|
||||
$(abs_top_builddir)/lib/librxgk.a \
|
||||
$(abs_top_builddir)/lib/libafsrpc.a \
|
||||
$(abs_top_builddir)/lib/libafshcrypto.a \
|
||||
$(LIB_rfc3961) $(LIB_roken) -lafsutil\
|
||||
$(XLIBS)
|
||||
clean:
|
||||
rm -f *.o superuser-t
|
197
tests/auth/superuser-t.c
Normal file
197
tests/auth/superuser-t.c
Normal file
@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Your File System Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <afsconfig.h>
|
||||
#include <afs/param.h>
|
||||
|
||||
#include <roken.h>
|
||||
|
||||
#include <afs/cellconfig.h>
|
||||
#include <afs/afsutil.h>
|
||||
#include <rx/rx_identity.h>
|
||||
|
||||
#include <tap/basic.h>
|
||||
|
||||
static void
|
||||
testOriginalIterator(struct afsconf_dir *dir, int num, char *user) {
|
||||
char buffer[256];
|
||||
|
||||
ok((afsconf_GetNthUser(dir, num, buffer, sizeof buffer) == 0),
|
||||
"User %d successfully returned as %s", num, buffer);
|
||||
|
||||
ok(strcmp(user, buffer) == 0,
|
||||
"User %d matches", num);
|
||||
}
|
||||
|
||||
static void
|
||||
testNewIterator(struct afsconf_dir *dir, int num, struct rx_identity *id) {
|
||||
struct rx_identity *fileId;
|
||||
|
||||
ok((afsconf_GetNthIdentity(dir, num, &fileId) == 0),
|
||||
"Identity %d successfully returned", num);
|
||||
|
||||
ok(rx_identity_match(fileId, id), "Identity %d matches", num);
|
||||
|
||||
rx_identity_free(&fileId);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct afsconf_dir *dir;
|
||||
char buffer[1024];
|
||||
char ubuffer[256];
|
||||
char *dirEnd;
|
||||
FILE *file;
|
||||
struct rx_identity *testId, *anotherId, *extendedId, *dummy;
|
||||
|
||||
plan(36);
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "%s/afs_XXXXXX", gettmpdir());
|
||||
mkdtemp(buffer);
|
||||
dirEnd = buffer + strlen(buffer);
|
||||
|
||||
/* Create a CellServDB file */
|
||||
strcpy(dirEnd, "/CellServDB");
|
||||
file = fopen(buffer, "w");
|
||||
fprintf(file, ">example.org # An example cell\n");
|
||||
fprintf(file, "127.0.0.1 #test.example.org\n");
|
||||
fclose(file);
|
||||
|
||||
/* Create a ThisCell file */
|
||||
strcpy(dirEnd, "/ThisCell");
|
||||
file = fopen(buffer, "w");
|
||||
fprintf(file, "example.org\n");
|
||||
fclose(file);
|
||||
|
||||
*dirEnd='\0';
|
||||
/* Start with a blank configuration directory */
|
||||
dir = afsconf_Open(strdup(buffer));
|
||||
ok(dir!=NULL,
|
||||
"Configuration directory opened sucessfully");
|
||||
|
||||
/* Add a normal user to the super user file */
|
||||
ok(afsconf_AddUser(dir, "test") == 0,
|
||||
"Adding a simple user works");
|
||||
|
||||
testId = rx_identity_new(RX_ID_KRB4, "test", "test", strlen("test"));
|
||||
|
||||
/* Check that they are a super user */
|
||||
ok(afsconf_IsSuperIdentity(dir, testId),
|
||||
"User added with old i/face is identitifed as super user");
|
||||
|
||||
/* Check that nobody else is */
|
||||
ok(!afsconf_IsSuperIdentity(dir,
|
||||
rx_identity_new(RX_ID_KRB4, "testy",
|
||||
"testy", strlen("testy"))),
|
||||
"Additional users are not super users");
|
||||
|
||||
ok(afsconf_AddUser(dir, "test") == EEXIST,
|
||||
"Adding a user that already exists fails");
|
||||
|
||||
ok(afsconf_AddIdentity(dir, testId) == EEXIST,
|
||||
"Adding an identity that already exists fails");
|
||||
|
||||
anotherId = rx_identity_new(RX_ID_KRB4, "another",
|
||||
"another", strlen("another"));
|
||||
|
||||
/* Add another normal user, but using the extended interface */
|
||||
ok(afsconf_AddIdentity(dir, anotherId) == 0,
|
||||
"Adding a KRB4 identity works");
|
||||
|
||||
/* Check that they are a super user */
|
||||
ok(afsconf_IsSuperIdentity(dir, anotherId),
|
||||
"User added with new i/face is identitifed as super user");
|
||||
|
||||
ok(afsconf_AddIdentity(dir, anotherId) == EEXIST,
|
||||
"Adding a KRB4 identity that already exists fails");
|
||||
|
||||
/* Add an extended user to the super user file */
|
||||
extendedId = rx_identity_new(RX_ID_GSS, "sxw@INF.ED.AC.UK",
|
||||
"\x04\x01\x00\x0B\x06\x09\x2A\x86\x48\x86\xF7\x12\x01\x02\x02\x00\x00\x00\x10sxw@INF.ED.AC.UK", 35);
|
||||
|
||||
ok(afsconf_AddIdentity(dir, extendedId) == 0,
|
||||
"Adding a GSSAPI identity works");
|
||||
|
||||
/* Check that they are now special */
|
||||
ok(afsconf_IsSuperIdentity(dir, extendedId),
|
||||
"Added GSSAPI identity is a super user");
|
||||
|
||||
/* Check that display name isn't used for matches */
|
||||
ok(!afsconf_IsSuperIdentity(dir,
|
||||
rx_identity_new(RX_ID_GSS, "sxw@INF.ED.AC.UK",
|
||||
"abcdefghijklmnopqrstuvwxyz123456789", 35)),
|
||||
"Display name is not used for extended matches");
|
||||
|
||||
ok(afsconf_AddIdentity(dir, extendedId) == EEXIST,
|
||||
"Adding GSSAPI identity twice fails");
|
||||
|
||||
/* Add a final normal user, so we can check that iteration works */
|
||||
/* Add a normal user to the super user file */
|
||||
ok(afsconf_AddUser(dir, "test2") == 0,
|
||||
"Adding another simple user works");
|
||||
|
||||
testOriginalIterator(dir, 0, "test");
|
||||
testOriginalIterator(dir, 1, "another");
|
||||
testOriginalIterator(dir, 2, "test2");
|
||||
ok(afsconf_GetNthUser(dir, 3, ubuffer, sizeof ubuffer) != 0,
|
||||
"Reading past the end of the superuser list fails");
|
||||
|
||||
testNewIterator(dir, 0, testId);
|
||||
testNewIterator(dir, 1, anotherId);
|
||||
testNewIterator(dir, 2, extendedId);
|
||||
testNewIterator(dir, 3, rx_identity_new(RX_ID_KRB4, "test2",
|
||||
"test2", strlen("test2")));
|
||||
ok(afsconf_GetNthIdentity(dir, 4, &dummy) != 0,
|
||||
"Reading past the end of the superuser list fails");
|
||||
|
||||
ok(afsconf_DeleteUser(dir, "notthere") != 0,
|
||||
"Deleting a user that doesn't exist fails");
|
||||
|
||||
/* Delete the normal user */
|
||||
ok(afsconf_DeleteUser(dir, "another") == 0,
|
||||
"Deleting normal user works");
|
||||
|
||||
ok(!afsconf_IsSuperIdentity(dir, anotherId),
|
||||
"Deleted user is no longer super user");
|
||||
|
||||
ok(afsconf_IsSuperIdentity(dir, testId) &&
|
||||
afsconf_IsSuperIdentity(dir, extendedId),
|
||||
"Other identities still are");
|
||||
|
||||
ok(afsconf_DeleteIdentity(dir, extendedId) == 0,
|
||||
"Deleting identity works");
|
||||
|
||||
ok(!afsconf_IsSuperIdentity(dir, extendedId),
|
||||
"Deleted identity is no longer special");
|
||||
|
||||
strcpy(dirEnd, "/CellServDB");
|
||||
unlink(buffer);
|
||||
strcpy(dirEnd, "/ThisCell");
|
||||
unlink(buffer);
|
||||
strcpy(dirEnd, "/UserList");
|
||||
unlink(buffer);
|
||||
*dirEnd='\0';
|
||||
rmdir(buffer);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user