openafs/tests/auth/superuser-t.c
Marc Dionne 0c3670914a tests: cleanup temporary files
Call the configuration directory cleanup function before exiting
so there are no files left behind, even in case of error.

Add KeyFileExt to the list of files that are removed.

Change-Id: Ie795bef0d44609b36950970244c02a6c6da1a843
Reviewed-on: http://gerrit.openafs.org/8142
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Simon Wilkinson <simonxwilkinson@gmail.com>
Reviewed-by: Derrick Brashear <shadow@your-file-system.com>
2012-10-30 03:27:16 -07:00

448 lines
14 KiB
C

/*
* 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>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#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 <hcrypto/des.h>
#include <tests/tap/basic.h>
#include "test.h"
#include "common.h"
#define TEST_PORT 1234
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);
}
void
startClient(char *configPath)
{
struct afsconf_dir *dir;
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 = NULL;
plan(63);
dir = afsconf_Open(configPath);
ok(dir!=NULL,
"Configuration directory opened sucessfully by client");
/* 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");
/* Now, what happens if we're doing something over the network instead */
code = rx_Init(0);
is_int(code, 0, "Initialised RX");
/* 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 */
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");
xdr_free((xdrproc_t)xdr_string, &string);
/* 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 = afstest_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);
xdr_free((xdrproc_t)xdr_string, &string);
is_int(EPERM, code,
"Running RPC returning string fails as expected");
code = TEST_NewWhoAmI(conn, &string);
xdr_free((xdrproc_t)xdr_string, &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");
xdr_free((xdrproc_t)xdr_string, &string);
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");
xdr_free((xdrproc_t)xdr_string, &string);
rx_DestroyConnection(conn);
rxs_Release(class);
/* Now try with an admin principal */
startTime = time(NULL);
class = afstest_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);
xdr_free((xdrproc_t)xdr_string, &string);
is_int(EPERM, code,
"Running RPC returning string fails as expected");
code = TEST_NewWhoAmI(conn, &string);
xdr_free((xdrproc_t)xdr_string, &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");
xdr_free((xdrproc_t)xdr_string, &string);
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");
xdr_free((xdrproc_t)xdr_string, &string);
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;
}
int main(int argc, char **argv)
{
struct afsconf_dir *dir;
char *dirname;
int serverPid, clientPid, waited, stat;
int code;
int ret = 0;
/* Start the client and the server if requested */
if (argc == 3 ) {
if (strcmp(argv[1], "-server") == 0) {
globalDir = afsconf_Open(argv[2]);
afstest_StartTestRPCService(argv[2], TEST_PORT, TEST_SERVICE_ID,
TEST_ExecuteRequest);
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 */
dirname = afstest_BuildTestConfig();
dir = afsconf_Open(dirname);
if (dir == NULL) {
fprintf(stderr, "Unable to configure directory.\n");
ret = 1;
goto out;
}
code = afstest_AddDESKeyFile(dir);
if (code) {
afs_com_err("superuser-t", code, "while adding new key\n");
ret = 1;
goto out;
}
printf("Config directory is %s\n", dirname);
serverPid = fork();
if (serverPid == -1) {
/* Bang */
} else if (serverPid == 0) {
execl(argv[0], argv[0], "-server", dirname, NULL);
ret = 1;
goto out;
}
clientPid = fork();
if (clientPid == -1) {
kill(serverPid, SIGTERM);
waitpid(serverPid, &stat, 0);
ret = 1;
goto out;
} else if (clientPid == 0) {
execl(argv[0], argv[0], "-client", dirname, 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);
out:
/* Client and server are both done, so cleanup after everything */
afstest_UnlinkTestConfig(dirname);
return ret;
}