auth: Add more tests and resulting fixes to userok

Add tests for the functions afsconf_SuperUser() and
afsconf_SuperIdentity(). These had been missing tests because testing
them requires starting a client and a server, so amend the superuser-t
tests so that they can start up a simple server.

Fix a number of problems that the tests expose, with setting (and
freeing) identities in corner cases.

Change-Id: I29f5f9eda7f532c98183d588e488d704f8efad88
Reviewed-on: http://gerrit.openafs.org/3593
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>
This commit is contained in:
Simon Wilkinson 2010-12-24 18:32:30 +00:00 committed by Derrick Brashear
parent affc978be7
commit 83ac1558b6
5 changed files with 395 additions and 40 deletions

View File

@ -593,7 +593,7 @@ CompFindUser(struct afsconf_dir *adir, char *name, char *sep, char *inst,
testId = rx_identity_new(RX_ID_KRB4, fullname, fullname, strlen(fullname));
if (afsconf_IsSuperIdentity(adir, testId)) {
if (*identity)
if (identity)
*identity = testId;
else
rx_identity_free(&testId);
@ -677,8 +677,9 @@ kerberosSuperUser(struct afsconf_dir *adir, char *tname, char *tinst,
if ((tinst == NULL || strlen(tinst) == 0) &&
(tcell == NULL || strlen(tcell) == 0)
&& !strcmp(tname, AUTH_SUPERUSER)) {
*identity = rx_identity_new(RX_ID_KRB4, AFS_LOCALAUTH_NAME,
AFS_LOCALAUTH_NAME, AFS_LOCALAUTH_LEN);
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 */
@ -798,20 +799,22 @@ afsconf_SuperUser(struct afsconf_dir *adir, struct rx_call *acall,
char *namep)
{
struct rx_identity *identity;
int code;
int ret;
code = afsconf_SuperIdentity(adir, acall, &identity);
if (code) {
if (namep) {
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);
}
rx_identity_free(&identity);
} else {
ret = afsconf_SuperIdentity(adir, acall, NULL);
}
return code;
return ret;
}

View File

@ -1 +1,2 @@
/superuser-t
/test.h

View File

@ -10,13 +10,29 @@ MODULE_CFLAGS=-I$(srcdir)/..
all check test tests: $(TESTS)
superuser-t: superuser-t.o
$(AFS_LDRULE) superuser-t.o ../tap/libtap.a \
superuser-t: superuser-t.o test.cs.o test.ss.o test.xdr.o
$(AFS_LDRULE) superuser-t.o test.cs.o test.ss.o test.xdr.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)
test.cs.c: test.xg
$(RXGEN) -A -x -C -o $@ $(srcdir)/test.xg
test.ss.c: test.xg
$(RXGEN) -A -x -S -o $@ $(srcdir)/test.xg
test.xdr.c: test.xg
$(RXGEN) -A -x -c -o $@ $(srcdir)/test.xg
test.h: test.xg
$(RXGEN) -A -x -h -o $@ $(srcdir)/test.xg
superuser-t.o: test.h
clean:
rm -f *.o superuser-t
rm -f *.o *.cs.c *.ss.c *.xdr.c test.h superuser-t

View File

@ -26,12 +26,23 @@
#include <roken.h>
#ifdef IGNORE_SOME_GCC_WARNINGS
# pragma GCC diagnostic warning "-Wdeprecated-declarations"
#endif
#include <afs/cellconfig.h>
#include <afs/afsutil.h>
#include <afs/com_err.h>
#include <rx/rxkad.h>
#include <rx/rx_identity.h>
#include <tap/basic.h>
#include "test.h"
#define TEST_PORT 1234
static void
testOriginalIterator(struct afsconf_dir *dir, int num, char *user) {
char buffer[256];
@ -55,39 +66,65 @@ testNewIterator(struct afsconf_dir *dir, int num, struct rx_identity *id) {
rx_identity_free(&fileId);
}
int main(int argc, char **argv)
struct rx_securityClass *
fakeRXKADClass(struct afsconf_dir *dir,
char *name, char *instance, char *realm,
afs_uint32 startTime, afs_uint32 endTime)
{
int code;
char buffer[256];
struct ktc_encryptionKey key, session;
afs_int32 kvno;
afs_int32 ticketLen;
struct rx_securityClass *class = NULL;
code = afsconf_GetLatestKey(dir, &kvno, &key);
if (code)
goto out;
DES_init_random_number_generator((DES_cblock *) &key);
code = DES_new_random_key((DES_cblock *) &session);
if (code)
goto out;
ticketLen = sizeof(buffer);
memset(buffer, 0, sizeof(buffer));
startTime = time(NULL);
endTime = startTime + 60 * 60;
code = tkt_MakeTicket(buffer, &ticketLen, &key, name, instance, realm,
startTime, endTime, &session, 0, "afs", "");
if (code)
goto out;
class = rxkad_NewClientSecurityObject(rxkad_clear, &session, kvno,
ticketLen, buffer);
out:
return class;
}
void
startClient(char *configPath)
{
struct afsconf_dir *dir;
char buffer[1024];
char ubuffer[256];
char *dirEnd;
FILE *file;
struct rx_identity *testId, *anotherId, *extendedId, *dummy;
struct rx_securityClass *class;
struct rx_connection *conn;
afs_uint32 startTime;
char ubuffer[256];
afs_int32 classIndex;
int code;
struct hostent *he;
afs_uint32 addr;
afs_int32 result;
char *string;
plan(36);
plan(63);
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));
dir = afsconf_Open(configPath);
ok(dir!=NULL,
"Configuration directory opened sucessfully");
"Configuration directory opened sucessfully by client");
/* Add a normal user to the super user file */
ok(afsconf_AddUser(dir, "test") == 0,
@ -112,7 +149,7 @@ int main(int argc, char **argv)
"Adding an identity that already exists fails");
anotherId = rx_identity_new(RX_ID_KRB4, "another",
"another", strlen("another"));
"another", strlen("another"));
/* Add another normal user, but using the extended interface */
ok(afsconf_AddIdentity(dir, anotherId) == 0,
@ -184,6 +221,295 @@ int main(int argc, char **argv)
ok(!afsconf_IsSuperIdentity(dir, extendedId),
"Deleted identity is no longer special");
/* Now, what happens if we're doing something over the network instead */
/* Fake up an rx ticket. Note that this will be for the magic 'superuser' */
code = afsconf_ClientAuth(dir, &class, &classIndex);
is_int(code, 0, "Can successfully create superuser token");
/* Start a connection to our test service with it */
code = rx_Init(0);
is_int(code, 0, "Started RX");
he = gethostbyname("localhost");
if (!he) {
printf("Couldn't look up server hostname");
exit(1);
}
memcpy(&addr, he->h_addr, sizeof(afs_uint32));
conn = rx_NewConnection(addr, htons(TEST_PORT), TEST_SERVICE_ID,
class, classIndex);
/* There's nothing in the list, so this just succeeds because we can */
code = TEST_CanI(conn, &result);
is_int(0, code, "Can run a simple RPC");
code = TEST_WhoAmI(conn, &string);
is_int(0, code, "Can get identity back");
is_string("<LocalAuth>", string, "Forged token is super user");
/* Throw away this connection and security class */
rx_DestroyConnection(conn);
rxs_Release(class);
/* Now fake an rx ticket for a normal user. We have to do more work by hand
* here, sadly */
startTime = time(NULL);
class = fakeRXKADClass(dir, "rpctest", "", "", startTime, startTime + 60* 60);
conn = rx_NewConnection(addr, htons(TEST_PORT), TEST_SERVICE_ID, class,
RX_SECIDX_KAD);
code = TEST_CanI(conn, &result);
is_int(EPERM, code,
"Running RPC as non-super user fails as expected");
code = TEST_NewCanI(conn, &result);
is_int(EPERM, code,
"Running new interface RPC as non-super user fails as expected");
code = TEST_WhoAmI(conn, &string);
is_int(EPERM, code,
"Running RPC returning string fails as expected");
code = TEST_NewWhoAmI(conn, &string);
is_int(EPERM, code,
"Running new interface RPC returning string fails as expected");
ok(afsconf_AddUser(dir, "rpctest") == 0,
"Adding %s user works", "rpctest");
code = TEST_CanI(conn, &result);
is_int(0, code, "Running RPC as rpctest works");
code = TEST_NewCanI(conn, &result);
is_int(0, code, "Running new interface RPC as rpctest works");
code = TEST_WhoAmI(conn, &string);
is_int(0, code, "Running RPC returning string as %s works", "rpctest");
is_string("rpctest", string, "Returned user string matches");
code = TEST_NewWhoAmI(conn, &string);
is_int(0, code, "Running new RPC returning string as %s works", "rpctest");
is_string("rpctest", string, "Returned user string for new interface matches");
rx_DestroyConnection(conn);
rxs_Release(class);
/* Now try with an admin principal */
startTime = time(NULL);
class = fakeRXKADClass(dir, "rpctest", "admin", "", startTime,
startTime + 60* 60);
conn = rx_NewConnection(addr, htons(TEST_PORT), TEST_SERVICE_ID, class,
RX_SECIDX_KAD);
code = TEST_CanI(conn, &result);
is_int(EPERM, code,
"Running RPC as non-super user fails as expected");
code = TEST_NewCanI(conn, &result);
is_int(EPERM, code,
"Running new interface RPC as non-super user fails as expected");
code = TEST_WhoAmI(conn, &string);
is_int(EPERM, code,
"Running RPC returning string fails as expected");
code = TEST_NewWhoAmI(conn, &string);
is_int(EPERM, code,
"Running new interface RPC returning string fails as expected");
ok(afsconf_AddUser(dir, "rpctest.admin") == 0,
"Adding %s user works", "rpctest.admin");
code = TEST_CanI(conn, &result);
is_int(0, code, "Running RPC as %s works", "rpctest/admin");
code = TEST_NewCanI(conn, &result);
is_int(0, code, "Running new interface RPC as %s works", "rpctest/admin");
code = TEST_WhoAmI(conn, &string);
is_int(0, code, "Running RPC returning string as %s works", "rpctest/admin");
is_string("rpctest.admin", string, "Returned user string matches");
code = TEST_NewWhoAmI(conn, &string);
is_int(0, code, "Running new interface RPC returning string as %s works",
"rpctest/admin");
is_string("rpctest.admin", string,
"Returned user string from new interface matches");
rx_DestroyConnection(conn);
rxs_Release(class);
}
/**********************************************************************
* Server
**********************************************************************/
struct afsconf_dir *globalDir;
int
STEST_CanI(struct rx_call *call, afs_int32 *result)
{
*result = 0;
if (!afsconf_SuperUser(globalDir, call, NULL)) {
return EPERM;
}
return 0;
}
int
STEST_NewCanI(struct rx_call *call, afs_int32 *result)
{
*result = 0;
if (!afsconf_SuperIdentity(globalDir, call, NULL)) {
return EPERM;
}
return 0;
}
int
STEST_WhoAmI(struct rx_call *call, char **result)
{
char string[MAXKTCNAMELEN];
if (!afsconf_SuperUser(globalDir, call, string)) {
*result = strdup("");
return EPERM;
}
*result = strdup(string);
return 0;
}
int
STEST_NewWhoAmI(struct rx_call *call, char **result)
{
struct rx_identity *id;
if (!afsconf_SuperIdentity(globalDir, call, &id)) {
*result = strdup("");
return EPERM;
}
*result = strdup(id->displayName);
return 0;
}
void
startServer(char *configPath)
{
struct rx_securityClass **classes;
afs_int32 numClasses;
int code;
struct rx_service *service;
globalDir = afsconf_Open(configPath);
if (globalDir == NULL) {
fprintf(stderr, "Server: Unable to open config directory\n");
exit(1);
}
code = rx_Init(htons(TEST_PORT));
if (code != 0) {
fprintf(stderr, "Server: Unable to initialise RX\n");
exit(1);
}
afsconf_BuildServerSecurityObjects(globalDir, 0, &classes, &numClasses);
service = rx_NewService(0, TEST_SERVICE_ID, "test", classes, numClasses,
TEST_ExecuteRequest);
if (service == NULL) {
fprintf(stderr, "Server: Unable to start to test service\n");
exit(1);
}
rx_StartServer(1);
}
int main(int argc, char **argv)
{
struct afsconf_dir *dir;
char buffer[1024];
int serverPid, clientPid, waited, stat;
char keymaterial[]="\x19\x17\xff\xe6\xbb\x77\x2e\xfc";
char *dirEnd;
FILE *file;
int code;
/* Start the client and the server if requested */
if (argc == 3 ) {
if (strcmp(argv[1], "-server") == 0) {
startServer(argv[2]);
exit(0);
} else if (strcmp(argv[1], "-client") == 0) {
startClient(argv[2]);
exit(0);
} else {
printf("Bad option %s\n", argv[1]);
exit(1);
}
}
/* Otherwise, do the basic configuration, then start the client and
* server */
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));
if (dir == NULL) {
fprintf(stderr, "Unable to configure directory.\n");
exit(1);
}
DES_set_odd_parity((DES_cblock *)keymaterial);
/* Add a key to it so we can use it for connection tests */
code = afsconf_AddKey(dir, 1, keymaterial, 1);
if (code) {
afs_com_err("superuser-t", code, "while adding new key\n");
exit(1);
}
printf("Config directory is %s\n", buffer);
serverPid = fork();
if (serverPid == -1) {
/* Bang */
} else if (serverPid == 0) {
execl(argv[0], argv[0], "-server", buffer, NULL);
exit(1);
}
clientPid = fork();
if (clientPid == -1) {
kill(serverPid, SIGTERM);
waitpid(serverPid, &stat, 0);
exit(1);
} else if (clientPid == 0) {
execl(argv[0], argv[0], "-client", buffer, NULL);
}
do {
waited = waitpid(0, &stat, 0);
} while(waited == -1 && errno == EINTR);
if (waited == serverPid) {
kill(clientPid, SIGTERM);
} else if (waited == clientPid) {
kill(serverPid, SIGTERM);
}
waitpid(0, &stat, 0);
/* Client and server are both done, so cleanup after everything */
strcpy(dirEnd, "/KeyFile");
unlink(buffer);
strcpy(dirEnd, "/CellServDB");
unlink(buffer);
strcpy(dirEnd, "/ThisCell");

9
tests/auth/test.xg Normal file
View File

@ -0,0 +1,9 @@
package TEST_
prefix S
const TEST_SERVICE_ID = 4;
CanI(OUT int *result) = 1;
WhoAmI(OUT string name<>) = 2;
NewCanI(OUT int *result) = 3;
NewWhoAmI(OUT string name<>) = 4;