From 9f17cef3d3614d79b3ab2dc6807f9d0f928ab6db Mon Sep 17 00:00:00 2001 From: Simon Wilkinson Date: Mon, 27 Dec 2010 20:29:48 +0000 Subject: [PATCH 1/1] tests: Add tests for afsconf_'s key functions Add tests for all of the public functions that afsconf exports to manipulate KeyFiles. Include a sample Keyfile to start with, to ensure that we can continue to read KeyFiles produced by current versions of the code. These tests are here to catch regressions with a forthcoming rewrite of KeyFile handling. Change-Id: I02aaff82aa7e1b7a73981c7cf26a81164e0dd932 Reviewed-on: http://gerrit.openafs.org/3598 Tested-by: BuildBot Reviewed-by: Derrick Brashear --- tests/TESTS | 1 + tests/auth/.gitignore | 2 + tests/auth/KeyFile | Bin 0 -> 100 bytes tests/auth/Makefile.in | 19 +++- tests/auth/keys-t.c | 263 ++++++++++++++++++++++++++++++++++++++++++++++ tests/auth/writekeyfile.c | 86 +++++++++++++++ 6 files changed, 366 insertions(+), 5 deletions(-) create mode 100644 tests/auth/KeyFile create mode 100644 tests/auth/keys-t.c create mode 100644 tests/auth/writekeyfile.c diff --git a/tests/TESTS b/tests/TESTS index baa2dcc..f1bab61 100644 --- a/tests/TESTS +++ b/tests/TESTS @@ -1,4 +1,5 @@ util/ktime util/exec-alt util/queues +auth/keys auth/superuser diff --git a/tests/auth/.gitignore b/tests/auth/.gitignore index 6adae6d..3360f1d 100644 --- a/tests/auth/.gitignore +++ b/tests/auth/.gitignore @@ -1,2 +1,4 @@ +/keys-t /superuser-t /test.h +/writekeyfile diff --git a/tests/auth/KeyFile b/tests/auth/KeyFile new file mode 100644 index 0000000000000000000000000000000000000000..d0571769adc0df8c7f9123fc3cd426e01425e58c GIT binary patch literal 100 zcmZQzU|?ooU|?iqV&M=_aA*LsnOL9z$Yzlg`}b^Dx&B`u8!KRgio$3X1_7XH3>*uR J9Do!A0059Y2L=ED literal 0 HcmV?d00001 diff --git a/tests/auth/Makefile.in b/tests/auth/Makefile.in index 83033a1..016a781 100644 --- a/tests/auth/Makefile.in +++ b/tests/auth/Makefile.in @@ -4,15 +4,13 @@ abs_top_builddir=@abs_top_builddir@ include @TOP_OBJDIR@/src/config/Makefile.config include @TOP_OBJDIR@/src/config/Makefile.pthread -TESTS = superuser-t +TESTS = superuser-t keys-t MODULE_CFLAGS=-I$(srcdir)/.. all check test tests: $(TESTS) -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 \ +MODULE_LIBS = ../tap/libtap.a \ $(abs_top_builddir)/lib/libafsauthent.a \ $(abs_top_builddir)/lib/librxgk.a \ $(abs_top_builddir)/lib/libafsrpc.a \ @@ -20,6 +18,16 @@ superuser-t: superuser-t.o test.cs.o test.ss.o test.xdr.o $(LIB_rfc3961) $(LIB_roken) -lafsutil\ $(XLIBS) +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 \ + $(MODULE_LIBS) + +keys-t: keys-t.o + $(AFS_LDRULE) keys-t.o $(MODULE_LIBS) + +writekeyfile: writekeyfile.o + $(AFS_LDRULE) writekeyfile.o $(MODULE_LIBS) + test.cs.c: test.xg $(RXGEN) -A -x -C -o $@ $(srcdir)/test.xg @@ -35,4 +43,5 @@ test.h: test.xg superuser-t.o: test.h clean: - rm -f *.o *.cs.c *.ss.c *.xdr.c test.h superuser-t + rm -f *.o *.cs.c *.ss.c *.xdr.c test.h \ + writekeyfile superuser-t keys-t diff --git a/tests/auth/keys-t.c b/tests/auth/keys-t.c new file mode 100644 index 0000000..c6d6525 --- /dev/null +++ b/tests/auth/keys-t.c @@ -0,0 +1,263 @@ +/* + * 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. + */ + +/*! + * Tests for the afsconf key handling functions + */ + +#include +#include + +#include + +#include +#include +#include +#include + +static int +copy(char *inFile, char *outFile) +{ + int in, out; + int code, written; + char *block; + size_t len; + + in = open(inFile, O_RDONLY); + if (in<0) + return EIO; + + out = open(outFile, O_WRONLY | O_CREAT, 0600); + if (out<0) + return EIO; + + block = malloc(1024); + do { + len = read(in, block, 1024); + if (len > 0) + write(out, block, len); + } while (len > 0); + free(block); + + close(in); + close(out); + + if (len == -1) + return EIO; + + return 0; +} + +int main(int argc, char **argv) +{ + struct afsconf_dir *dir; + struct afsconf_keys keys; + struct ktc_encryptionKey key; + char buffer[1024]; + char *dirEnd; + FILE *file; + afs_int32 kvno; + int code; + + plan(47); + + /* Create a temporary afs configuration directory */ + 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); + + /* Firstly, copy in a known keyfile. */ + strcpy(dirEnd, "/KeyFile"); + code = copy("KeyFile", buffer); + if (code) + goto out; + + *dirEnd='\0'; + + /* Start with a blank configuration directory */ + dir = afsconf_Open(strdup(buffer)); + if (dir == NULL) { + fprintf(stderr, "Unable to open configuration directory.\n"); + exit(1); + } + + + /* Verify that GetKeys returns the entire set of keys correctly */ + code = afsconf_GetKeys(dir, &keys); + is_int(0, code, "afsconf_GetKeys returns successfully"); + is_int(3, keys.nkeys, "... and returns the right number of keys"); + is_int(1, keys.key[0].kvno, " ... first key number is correct"); + is_int(2, keys.key[1].kvno, " ... second key number is correct"); + is_int(4, keys.key[2].kvno, " ... third key number is correct"); + ok(memcmp(keys.key[0].key, "\x01\x02\x04\x08\x10\x20\x40\x80", 8) == 0, + " ... first key matches"); + ok(memcmp(keys.key[1].key, "\x04\x04\x04\x04\x04\x04\x04\x04", 8) == 0, + " ... second key matches"); + ok(memcmp(keys.key[2].key, "\x19\x16\xfe\xe6\xba\x77\x2f\xfd", 8) == 0, + " ... third key matches"); + + /* Verify that GetLatestKey returns the newest key */ + code = afsconf_GetLatestKey(dir, &kvno, &key); + is_int(0, code, "afsconf_GetLatestKey returns sucessfully"); + is_int(4, kvno, " ... with correct key number"); + ok(memcmp(&key, "\x19\x16\xfe\xe6\xba\x77\x2f\xfd", 8) == 0, + " ... and correct key"); + + /* Verify that random access using GetKey works properly */ + code = afsconf_GetKey(dir, 2, &key); + is_int(0, code, "afsconf_GetKey returns successfully"); + ok(memcmp(&key, "\x04\x04\x04\x04\x04\x04\x04\x04", 8) == 0, + " ... and with correct key"); + + /* And that it fails if the key number doesn't exist */ + code = afsconf_GetKey(dir, 3, &key); + is_int(code, AFSCONF_NOTFOUND, + "afsconf_GetKey returns not found for missing key"); + + /* Check that AddKey can be used to add a new 'newest' key */ + code = afsconf_AddKey(dir, 5, "\x08\x08\x08\x08\x08\x08\x08\x08", 0); + is_int(0, code, "afsconf_AddKey sucessfully adds a new key"); + + /* And that we can get it back with GetKeys, GetLatestKey and GetKey */ + code = afsconf_GetKeys(dir, &keys); + is_int(0, code, " ... and GetKeys still works"); + is_int(4, keys.nkeys, "... and has the correct number of keys"); + is_int(5, keys.key[3].kvno, " ... and the fourth key has the correct kvno"); + ok(memcmp(keys.key[3].key, "\x08\x08\x08\x08\x08\x08\x08\x08", 8) == 0, + " ... and is the correct key"); + + code = afsconf_GetLatestKey(dir, &kvno, &key); + is_int(0, code, " ... and GetLatestKey returns successfully"); + is_int(5, kvno, " ... with the correct key number"); + ok(memcmp(&key, "\x08\x08\x08\x08\x08\x08\x08\x08", 8) == 0, + " ... and the correct key"); + + code = afsconf_GetKey(dir, 5, &key); + is_int(0, code, " ... and GetKey still works"); + ok(memcmp(&key, "\x08\x08\x08\x08\x08\x08\x08\x08", 8) == 0, + " ... and returns the correct key"); + + /* Check that AddKey without the overwrite flag won't overwrite an existing + * key */ + code = afsconf_AddKey(dir, 5, "\x10\x10\x10\x10\x10\x10\x10", 0); + is_int(AFSCONF_KEYINUSE, code, "AddKey won't overwrite without being told to"); + + /* Check with GetKey that it didn't */ + code = afsconf_GetKey(dir, 5, &key); + is_int(0, code, " ... and GetKey still works"); + ok(memcmp(&key, "\x08\x08\x08\x08\x08\x08\x08\x08", 8) == 0, + " ... and key hasn't been overwritten"); + + /* Check that AddKey with the overwrite flag will overwrite an existing key */ + code = afsconf_AddKey(dir, 5, "\x10\x10\x10\x10\x10\x10\x10\x10", 1); + is_int(0, code, "AddKey overwrites when asked"); + + /* Use GetKey to check that it did so */ + code = afsconf_GetKey(dir, 5, &key); + is_int(0, code, " ... and GetKey still works"); + ok(memcmp(&key, "\x10\x10\x10\x10\x10\x10\x10\x10", 8) == 0, + " ... and key has been overwritten"); + + /* Check that deleting a key that doesn't exist fails */ + code = afsconf_DeleteKey(dir, 6); + is_int(AFSCONF_NOTFOUND, code, + "afsconf_DeleteKey returns NOTFOUND if key doesn't exist"); + + /* Check that we can delete a key using afsconf_DeleteKey */ + code = afsconf_DeleteKey(dir, 2); + is_int(0, code, "afsconf_DeleteKey can delete a key"); + code = afsconf_GetKey(dir, 2, &key); + is_int(AFSCONF_NOTFOUND, code, " ... and afsconf_GetKey can't find it"); + + /* Check that deleting it doesn't leave a hole in what GetKeys returns */ + code = afsconf_GetKeys(dir, &keys); + is_int(0, code, "... and afsconf_GetKeys returns it"); + is_int(3, keys.nkeys, "... and returns the right number of keys"); + is_int(1, keys.key[0].kvno, " ... first key number is correct"); + is_int(4, keys.key[1].kvno, " ... second key number is correct"); + is_int(5, keys.key[2].kvno, " ... third key number is correct"); + + /* Unlink the KeyFile */ + strcpy(dirEnd, "/KeyFile"); + unlink(buffer); + + /* Force a rebuild of the directory structure, just in case */ + afsconf_Close(dir); + + *dirEnd='\0'; + dir = afsconf_Open(strdup(buffer)); + if (dir == NULL) { + fprintf(stderr, "Unable to open configuration directory.\n"); + goto out; + } + + /* Check that all of the various functions work properly if the file + * isn't there */ + code = afsconf_GetKeys(dir, &keys); + is_int(0, code, "afsconf_GetKeys works with an empty KeyFile"); + is_int(0, keys.nkeys, " ... and returns the right number of keys"); + code = afsconf_GetKey(dir, 1, &key); + is_int(AFSCONF_NOTFOUND, code, + "afsconf_GetKey returns NOTFOUND with an empty KeyFile"); + code = afsconf_DeleteKey(dir, 1); + is_int(AFSCONF_NOTFOUND, code, + "afsconf_DeleteKey returns NOTFOUND with an empty KeyFile"); + code = afsconf_GetLatestKey(dir, &kvno, &key); + is_int(AFSCONF_NOTFOUND, code, + "afsconf_GetLatestKey returns NOTFOUND with an empty KeyFile"); + + /* Now try adding a key to an empty file */ + code = afsconf_AddKey(dir, 1, "\x10\x10\x10\x10\x10\x10\x10\x10", 1); + is_int(0, code, "afsconf_AddKey succeeds with an empty KeyFile"); + code = afsconf_GetLatestKey(dir, &kvno, &key); + is_int(0, code, " ... and afsconf_GetLatestKey succeeds"); + is_int(1, kvno, " ... with correct kvno"); + ok(memcmp(&key, "\x10\x10\x10\x10\x10\x10\x10\x10", 8) == 0, + " ... and key"); + +out: + strcpy(dirEnd, "/KeyFile"); + unlink(buffer); + strcpy(dirEnd, "/CellServDB"); + unlink(buffer); + strcpy(dirEnd, "/ThisCell"); + unlink(buffer); + strcpy(dirEnd, "/UserList"); + unlink(buffer); + *dirEnd='\0'; + rmdir(buffer); +} diff --git a/tests/auth/writekeyfile.c b/tests/auth/writekeyfile.c new file mode 100644 index 0000000..2387da0 --- /dev/null +++ b/tests/auth/writekeyfile.c @@ -0,0 +1,86 @@ +/* This is a simple program which originally produced the KeyFile used + * by the test suite. The contents of that file shouldn't be regenerated, + * though, as the purpose of the tests using that file is to ensure that we + * can still read old KeyFiles. + */ + +#include +#include +#include +#include + +#include + +int +main(int argc, char **argv) +{ + struct afsconf_dir *dir; + char buffer[1024]; + char *block; + char *dirEnd; + FILE *file; + int in, out; + size_t len; + int code; + + 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'; + dir = afsconf_Open(strdup(buffer)); + if (dir == NULL) { + fprintf(stderr, "Unable to open configuration directory\n"); + exit(1); + } + + afsconf_AddKey(dir, 1, "\x01\x02\x04\x08\x10\x20\x40\x80", 1); + afsconf_AddKey(dir, 2, "\x04\x04\x04\x04\x04\x04\x04\x04", 1); + afsconf_AddKey(dir, 4, "\x19\x16\xfe\xe6\xba\x77\x2f\xfd", 1); + + afsconf_Close(dir); + + /* Copy out the resulting keyfile into our homedirectory */ + strcpy(dirEnd, "/KeyFile"); + in = open(buffer, O_RDONLY); + out = open("KeyFile", O_WRONLY | O_CREAT, 0644); + + block = malloc(1024); + do { + len = read(in, block, 1024); + if (len > 0) + write(out, block, len); + } while (len > 0); + + if (len == -1) { + fprintf(stderr, "I/O error whilst copying file\n"); + exit(1); + } + + close(in); + close(out); + + strcpy(dirEnd, "/KeyFile"); + unlink(buffer); + strcpy(dirEnd, "/CellServDB"); + unlink(buffer); + strcpy(dirEnd, "/ThisCell"); + unlink(buffer); + strcpy(dirEnd, "/UserList"); + unlink(buffer); + *dirEnd='\0'; + rmdir(buffer); +} -- 1.9.4