#include <afs/afsutil.h>
#include <rx/rxkad.h>
+#include <tap/basic.h>
+
+#include "test.h"
+#include "common.h"
+
static int
copy(char *inFile, char *outFile)
{
int in, out;
- int code, written;
char *block;
size_t len;
return 0;
}
+int
+keyMatches(struct afsconf_typedKey *typedKey,
+ afsconf_keyType type, int kvno, int subType,
+ void *keyMaterial, size_t keyLen)
+{
+ afsconf_keyType keyType;
+ int keyKvno;
+ int keySubType;
+ struct rx_opaque *buffer;
+
+ afsconf_typedKey_values(typedKey, &keyType, &keyKvno, &keySubType,
+ &buffer);
+
+ return (keyType == type && keyKvno == kvno && keySubType == subType &&
+ buffer->len == keyLen &&
+ memcmp(keyMaterial, buffer->val, buffer->len) == 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;
+ struct rx_opaque *keyMaterial;
+ struct afsconf_typedKey *typedKey;
+ struct afsconf_typedKeyList *typedKeyList;
+ char *dirname;
+ char *keyfile;
+ char *keyfilesrc;
afs_int32 kvno;
int code;
+ int i;
- plan(47);
+ plan(134);
/* 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';
+ dirname = buildTestConfig();
- /* Start with a blank configuration directory */
- dir = afsconf_Open(strdup(buffer));
- if (dir == NULL) {
- fprintf(stderr, "Unable to open configuration directory.\n");
- exit(1);
+ if (asprintf(&keyfile, "%s/KeyFile", dirname) == -1)
+ goto out;
+
+ /* Work out the path to our KeyFile. If the test harness hasn't set
+ * the SOURCE environment variable, then assume it is in our CWD */
+ if (getenv("SOURCE") == NULL) {
+ keyfilesrc = strdup("KeyFile");
+ } else {
+ if (asprintf(&keyfilesrc, "%s/auth/KeyFile", getenv("SOURCE")) == -1)
+ goto out;
}
+ /* First, copy in a known keyfile */
+ code = copy(keyfilesrc, keyfile);
+ free(keyfilesrc);
+ if (code)
+ goto out;
+
+ /* Start with a blank configuration directory */
+ dir = afsconf_Open(dirname);
+ ok(dir != NULL, "Sucessfully re-opened config directory");
+ if (dir == NULL)
+ goto out;
/* Verify that GetKeys returns the entire set of keys correctly */
code = afsconf_GetKeys(dir, &keys);
ok(memcmp(&key, "\x19\x16\xfe\xe6\xba\x77\x2f\xfd", 8) == 0,
" ... and correct key");
+ /* Check that GetLatestKey works if called with NULL parameters */
+ code = afsconf_GetLatestKey(dir, NULL, NULL);
+ is_int(0, code, "afsconf_GetLatestKey works if parameters are NULL");
+
/* Verify that random access using GetKey works properly */
code = afsconf_GetKey(dir, 2, &key);
is_int(0, code, "afsconf_GetKey returns successfully");
is_int(4, keys.key[1].kvno, " ... second key number is correct");
is_int(5, keys.key[2].kvno, " ... third key number is correct");
+ /* Make sure that if we drop the dir structure, and then rebuild it, we
+ * still have the same KeyFile */
+ afsconf_Close(dir);
+
+ dir = afsconf_Open(dirname);
+ ok(dir != NULL, "Sucessfully re-opened config directory");
+ if (dir == NULL)
+ goto out;
+
+ code = afsconf_GetKeys(dir, &keys);
+ is_int(0, code, "afsconf_GetKeys still works");
+ 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");
+
+ /* Now check that we're limited to 8 keys */
+ for (i=0; i<5; i++) {
+ code = afsconf_AddKey(dir, 10+i, "\x10\x10\x10\x10\x10\x10\x10\x10",
+ 0);
+ is_int(0, code, "Adding %dth key with AddKey works", i+4);
+ }
+ code = afsconf_AddKey(dir, 20, "\x10\x10\x10\x10\x10\x10\x10\x10",0);
+ is_int(AFSCONF_FULL, code, "afsconf_AddKey fails once we've got 8 keys");
+
+ /* Check that the new interface also fails when we've got too many
+ * keys */
+ keyMaterial = rx_opaque_new("\x10\x10\x10\x10\x10\x10\x10\x10", 8);
+ typedKey = afsconf_typedKey_new(afsconf_rxkad, 20, 0, keyMaterial);
+ rx_opaque_free(&keyMaterial);
+ code = afsconf_AddTypedKey(dir, typedKey, 0);
+ afsconf_typedKey_put(&typedKey);
+ is_int(AFSCONF_FULL, code,
+ "afsconf_AddTypedKey fails for rxkad once we've got 8 keys");
+
+ /* Check the new accessors work for rxkad keys */
+ code = afsconf_GetKeyByTypes(dir, afsconf_rxkad, 4, 0, &typedKey);
+ is_int(0, code,
+ "afsconf_GetKeyByTypes works for rxkad");
+ ok(keyMatches(typedKey, afsconf_rxkad, 4, 0,
+ "\x19\x16\xfe\xe6\xba\x77\x2f\xfd", 8),
+ " ... and returned key matches");
+
+ afsconf_typedKey_put(&typedKey);
+
+ code = afsconf_GetKeysByType(dir, afsconf_rxkad, 4, &typedKeyList);
+ is_int(0, code,
+ "afsconf_GetKeysByType works for rxkad");
+ is_int(1, typedKeyList->nkeys,
+ " ... and returns 1 key, as expected");
+ ok(keyMatches(typedKeyList->keys[0], afsconf_rxkad, 4, 0,
+ "\x19\x16\xfe\xe6\xba\x77\x2f\xfd", 8),
+ " ... and returned key matches");
+
+ afsconf_PutTypedKeyList(&typedKeyList);
+
+ code = afsconf_GetLatestKeyByTypes(dir, afsconf_rxkad, 0, &typedKey);
+ is_int(0, code,
+ "afsconf_GetLatestKeyByTypes works for rxkad");
+ ok(keyMatches(typedKey, afsconf_rxkad, 14, 0,
+ "\x10\x10\x10\x10\x10\x10\x10\x10", 8),
+ " ... and returned key matches");
+
+ afsconf_typedKey_put(&typedKey);
+
+ code = afsconf_GetLatestKeysByType(dir, afsconf_rxkad, &typedKeyList);
+ is_int(0, code,
+ "afsconf_GetLatestKeysByType works for rxkad");
+ is_int(1, typedKeyList->nkeys,
+ " ... and returns 1 key, as expected");
+ ok(keyMatches(typedKeyList->keys[0], afsconf_rxkad, 14, 0,
+ "\x10\x10\x10\x10\x10\x10\x10\x10", 8),
+ " ... and returned key matches");
+ afsconf_PutTypedKeyList(&typedKeyList);
+
+ /* Check that we can't delete a key that doesn't exist */
+ code = afsconf_DeleteKeyByType(dir, afsconf_rxkad, 6);
+ is_int(AFSCONF_NOTFOUND, code,
+ "afsconf_DeleteKeyByType returns NOTFOUND if key doesn't exist");
+ code = afsconf_DeleteKeyBySubType(dir, afsconf_rxkad, 6, 0);
+ is_int(AFSCONF_NOTFOUND, code,
+ "afsconf_DeleteKeyBySubType returns NOTFOUND if key doesn't exist");
+ code = afsconf_DeleteKeyBySubType(dir, afsconf_rxkad, 14, 1);
+ is_int(AFSCONF_NOTFOUND, code,
+ "afsconf_DeleteKeyBySubType doesn't delete with wrong subtype");
+ code = afsconf_GetKeyByTypes(dir, afsconf_rxkad, 14, 0, &typedKey);
+ is_int(0, code, " ... and key is still there!");
+ afsconf_typedKey_put(&typedKey);
+
+ /* Check that we can delete a key that does */
+ code = afsconf_DeleteKeyByType(dir, afsconf_rxkad, 13);
+ is_int(0, code, "afsconf_DeleteKeyByType works");
+ code = afsconf_GetKeysByType(dir, afsconf_rxkad, 13, &typedKeyList);
+ is_int(AFSCONF_NOTFOUND, code, " ... and is really gone");
+
+ code = afsconf_DeleteKeyBySubType(dir, afsconf_rxkad, 14, 0);
+ is_int(0, code, "afsconf_DeleteKeyBySubType works");
+ code = afsconf_GetKeyByTypes(dir, afsconf_rxkad, 14, 0, &typedKey);
+ is_int(AFSCONF_NOTFOUND, code, " ... and is really gone");
+
/* Unlink the KeyFile */
- strcpy(dirEnd, "/KeyFile");
- unlink(buffer);
+ unlink(keyfile);
/* 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;
- }
+ dir = afsconf_Open(dirname);
+ ok(dir != NULL, "Sucessfully re-opened config directory");
+ if (dir == NULL)
+ goto out;
/* Check that all of the various functions work properly if the file
* isn't there */
code = afsconf_GetLatestKey(dir, &kvno, &key);
is_int(AFSCONF_NOTFOUND, code,
"afsconf_GetLatestKey returns NOTFOUND with an empty KeyFile");
+ code = afsconf_GetKeysByType(dir, afsconf_rxkad, 1, &typedKeyList);
+ is_int(AFSCONF_NOTFOUND, code,
+ "afsconf_GetKeysByType returns NOTFOUND with an empty KeyFile");
+ code = afsconf_GetKeyByTypes(dir, afsconf_rxkad, 1, 0, &typedKey);
+ is_int(AFSCONF_NOTFOUND, code,
+ "afsconf_GetKeyByTypes returns NOTFOUND with an empty KeyFile");
+ code = afsconf_GetLatestKeysByType(dir, afsconf_rxkad, &typedKeyList);
+ is_int(AFSCONF_NOTFOUND, code,
+ "afsconf_GetLatestKeysByType returns NOTFOUND with empty KeyFile");
+ code = afsconf_GetLatestKeyByTypes(dir, afsconf_rxkad, 0, &typedKey);
+ is_int(AFSCONF_NOTFOUND, code,
+ "afsconf_GetLatestKeyByTypes returns NOTFOUND with 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);
ok(memcmp(&key, "\x10\x10\x10\x10\x10\x10\x10\x10", 8) == 0,
" ... and key");
+ /* And adding a key using the new interface */
+
+ keyMaterial = rx_opaque_new("\x20\x20\x20\x20\x20\x20\x20\x20", 8);
+ typedKey = afsconf_typedKey_new(afsconf_rxkad, 2, 0, keyMaterial);
+ rx_opaque_free(&keyMaterial);
+ code = afsconf_AddTypedKey(dir, typedKey, 0);
+ afsconf_typedKey_put(&typedKey);
+ is_int(0, code, "afsconf_AddTypedKey works");
+ code = afsconf_GetLatestKey(dir, &kvno, &key);
+ is_int(0, code, " ... and afsconf_GetLatestKey succeeds");
+ is_int(2, kvno, " ... with correct kvno");
+ ok(memcmp(&key, "\x20\x20\x20\x20\x20\x20\x20\x20", 8) == 0,
+ " ... and key");
+ code = afsconf_GetLatestKeyByTypes(dir, afsconf_rxkad, 0, &typedKey);
+ is_int(0, code, " ... and so does afsconf_GetLatestKeyByTypes");
+ ok(keyMatches(typedKey, afsconf_rxkad, 2, 0,
+ "\x20\x20\x20\x20\x20\x20\x20\x20", 8),
+ " ... with correct key");
+ afsconf_typedKey_put(&typedKey);
+
+ /* And that we can't add a key to an existing kvno and type */
+ keyMaterial = rx_opaque_new("\x30\x30\x30\x30\x30\x30\x30\x30", 8);
+ typedKey = afsconf_typedKey_new(afsconf_rxkad, 2, 0, keyMaterial);
+ rx_opaque_free(&keyMaterial);
+ code = afsconf_AddTypedKey(dir, typedKey, 0);
+ afsconf_typedKey_put(&typedKey);
+ is_int(AFSCONF_KEYINUSE, code,
+ "afsconf_AddTypedKey won't overwrite without being told to");
+ code = afsconf_GetKeyByTypes(dir, afsconf_rxkad, 2, 0, &typedKey);
+ is_int(0, code, " ... and key still exists");
+ ok(keyMatches(typedKey, afsconf_rxkad, 2, 0,
+ "\x20\x20\x20\x20\x20\x20\x20\x20", 8),
+ " ... and hasn't changed");
+ afsconf_typedKey_put(&typedKey);
+
+ /* But we can if we force */
+ keyMaterial = rx_opaque_new("\x30\x30\x30\x30\x30\x30\x30\x30", 8);
+ typedKey = afsconf_typedKey_new(afsconf_rxkad, 2, 0, keyMaterial);
+ rx_opaque_free(&keyMaterial);
+ code = afsconf_AddTypedKey(dir, typedKey, 1);
+ afsconf_typedKey_put(&typedKey);
+ is_int(0, code, "afsconf_AddTypedKey overwrites when asked");
+ code = afsconf_GetKeyByTypes(dir, afsconf_rxkad, 2, 0, &typedKey);
+ is_int(0, code, " ... and GetKeyByTypes retrieves new key");
+ ok(keyMatches(typedKey, afsconf_rxkad, 2, 0,
+ "\x30\x30\x30\x30\x30\x30\x30\x30", 8),
+ " ... and it is the new key");
+
+ /* Check that we can't add bad rxkad keys */
+ keyMaterial = rx_opaque_new("\x30\x30\x30\x30\x30\x30\x30", 7);
+ typedKey = afsconf_typedKey_new(afsconf_rxkad, 3, 0, keyMaterial);
+ rx_opaque_free(&keyMaterial);
+ code = afsconf_AddTypedKey(dir, typedKey, 1);
+ afsconf_typedKey_put(&typedKey);
+ is_int(AFSCONF_BADKEY, code,
+ "afsconf_AddTypedKey won't add short rxkad keys");
+ keyMaterial = rx_opaque_new("\x30\x30\x30\x30\x30\x30\x30\x30\x30", 9);
+ typedKey = afsconf_typedKey_new(afsconf_rxkad, 3, 0, keyMaterial);
+ rx_opaque_free(&keyMaterial);
+ code = afsconf_AddTypedKey(dir, typedKey, 1);
+ afsconf_typedKey_put(&typedKey);
+ is_int(AFSCONF_BADKEY, code,
+ "afsconf_AddTypedKey won't add long rxkad keys");
+ keyMaterial = rx_opaque_new("\x30\x30\x30\x30\x30\x30\x30\x30", 8);
+ typedKey = afsconf_typedKey_new(afsconf_rxkad, 3, 1, keyMaterial);
+ rx_opaque_free(&keyMaterial);
+ code = afsconf_AddTypedKey(dir, typedKey, 1);
+ afsconf_typedKey_put(&typedKey);
+ is_int(AFSCONF_BADKEY, code,
+ "afsconf_AddTypedKey won't add rxkad keys with non-zero subtype");
+
+ /* Now, test things with other key types. */
+
+ /* Add a different key type, but with same kvno as rxkad */
+ keyMaterial = rx_opaque_new("\x01", 1);
+ typedKey = afsconf_typedKey_new(1, 2, 0, keyMaterial);
+ code = afsconf_AddTypedKey(dir, typedKey, 0);
+ afsconf_typedKey_put(&typedKey);
+ is_int(0, code,
+ "afsconf_AddTypedKey can add keys with different key type");
+
+ /* Add a different subtype, with same kvno */
+ keyMaterial = rx_opaque_new("\x02\x03", 2);
+ typedKey = afsconf_typedKey_new(1, 2, 1, keyMaterial);
+ code = afsconf_AddTypedKey(dir, typedKey, 0);
+ afsconf_typedKey_put(&typedKey);
+ is_int(0, code,
+ "afsconf_AddTypedKey can add keys with different sub type");
+
+ /* Check the GetKeyByTypes returns one of the keys */
+ code = afsconf_GetKeyByTypes(dir, 1, 2, 1, &typedKey);
+ is_int(0, code, "afsconf_GetKeyByTypes returns");
+ ok(keyMatches(typedKey, 1, 2, 1, "\x02\x03", 2),
+ " ... with the right key");
+
+ /* Check that GetKeysByType returns both of the keys */
+ code = afsconf_GetKeysByType(dir, 1, 2, &typedKeyList);
+ is_int(0, code, "afsconf_GetKeysByType returns");
+ is_int(2, typedKeyList->nkeys, " ... with correct number of keys");
+ ok(keyMatches(typedKeyList->keys[0], 1, 2, 0, "\x01", 1),
+ " ... with the right key in slot 0");
+ ok(keyMatches(typedKeyList->keys[1], 1, 2, 1, "\x02\x03", 2),
+ " ... with the right key in slot 1");
+ afsconf_PutTypedKeyList(&typedKeyList);
+
+ /* Add another key, before these ones, so we can check that
+ * latest really works */
+ keyMaterial = rx_opaque_new("\x03", 1);
+ typedKey = afsconf_typedKey_new(1, 1, 0, keyMaterial);
+ code = afsconf_AddTypedKey(dir, typedKey, 0);
+ afsconf_typedKey_put(&typedKey);
+ is_int(0, code, "afsconf_AddTypedKey worked again");
+
+ /* Check that GetLatestKeyByTypes returns one */
+ code = afsconf_GetLatestKeyByTypes(dir, 1, 1, &typedKey);
+ is_int(0, code, "afsconf_GetLatestKeyByTypes returns");
+ ok(keyMatches(typedKey, 1, 2, 1, "\x02\x03", 2),
+ " ... with the right key");
+
+ /* Check that GetLatestKeysByType returns both */
+ code = afsconf_GetLatestKeysByType(dir, 1, &typedKeyList);
+ is_int(0, code, "afsconf_GetLatestKeysByType returns");
+ is_int(2, typedKeyList->nkeys, " ... with correct number of keys");
+ ok(keyMatches(typedKeyList->keys[0], 1, 2, 0, "\x01", 1),
+ " ... with the right key in slot 0");
+ ok(keyMatches(typedKeyList->keys[1], 1, 2, 1, "\x02\x03", 2),
+ " ... with the right key in slot 1");
+ afsconf_PutTypedKeyList(&typedKeyList);
+
+ /* Check that closing this instance, and reopening, still has all of
+ * the required keys
+ */
+ afsconf_Close(dir);
+
+ dir = afsconf_Open(dirname);
+ ok(dir != NULL, "Sucessfully re-opened config directory");
+ if (dir == NULL)
+ goto out;
+
+ /* Check that GetKeysByType returns all of the keys */
+ code = afsconf_GetKeysByType(dir, 1, 1, &typedKeyList);
+ is_int(0, code, "afsconf_GetKeysByType returns after reopening");
+ is_int(1, typedKeyList->nkeys, " ... First kvno has correct number of keys");
+ ok(keyMatches(typedKeyList->keys[0], 1, 1, 0, "\x03", 1),
+ " ... and key material is correct");
+ afsconf_PutTypedKeyList(&typedKeyList);
+
+ code = afsconf_GetKeysByType(dir, 1, 2, &typedKeyList);
+ is_int(0, code, "afsconf_GetKeysByType returns after reopening");
+ is_int(2, typedKeyList->nkeys, " ... with correct number of keys");
+ ok(keyMatches(typedKeyList->keys[0], 1, 2, 0, "\x01", 1),
+ " ... with the right key in slot 0");
+ ok(keyMatches(typedKeyList->keys[1], 1, 2, 1, "\x02\x03", 2),
+ " ... with the right key in slot 1");
+ afsconf_PutTypedKeyList(&typedKeyList);
+
+ /* Check that GetAllKeys works as expected */
+ code = afsconf_GetAllKeys(dir, &typedKeyList);
+ is_int(0, code, "afsconf_GetAllKeys returns success");
+ is_int(5, typedKeyList->nkeys, " ... with the correct number of keys");
+ ok(keyMatches(typedKeyList->keys[0], afsconf_rxkad, 1, 0,
+ "\x10\x10\x10\x10\x10\x10\x10\x10", 8),
+ " ... with right key in slot 0");
+ ok(keyMatches(typedKeyList->keys[1], afsconf_rxkad, 2, 0,
+ "\x30\x30\x30\x30\x30\x30\x30\x30", 8),
+ " ... with right key in slot 1");
+ ok(keyMatches(typedKeyList->keys[2], 1, 1, 0, "\x03", 1),
+ " ... with right key in slot 2");
+ ok(keyMatches(typedKeyList->keys[3], 1, 2, 0, "\x01", 1),
+ " ... with right key in slot 3");
+ ok(keyMatches(typedKeyList->keys[4], 1, 2, 1, "\x02\03", 2),
+ " ... with right key in slot 4");
+
+ afsconf_Close(dir);
+
+ unlinkTestConfig(dirname);
+ free(dirname);
+ free(keyfile);
+
+ /* Start a new test configuration */
+ dirname = buildTestConfig();
+ dir = afsconf_Open(dirname);
+ ok(dir != NULL, "Sucessfully opened brand new config directory");
+ if (dir == NULL)
+ goto out;
+
+ /* Check that directories with just new style keys work */
+ keyMaterial = rx_opaque_new("\x02\x03", 2);
+ typedKey = afsconf_typedKey_new(1, 2, 1, keyMaterial);
+ code = afsconf_AddTypedKey(dir, typedKey, 0);
+ afsconf_typedKey_put(&typedKey);
+ is_int(0, code,
+ "afsconf_AddTypedKey can add keys with different sub type");
+
+ /* Check the GetKeyByTypes returns one of the keys */
+ code = afsconf_GetKeyByTypes(dir, 1, 2, 1, &typedKey);
+ is_int(0, code, "afsconf_GetKeyByTypes returns it");
+ ok(keyMatches(typedKey, 1, 2, 1, "\x02\x03", 2),
+ " ... with the right 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);
+ unlinkTestConfig(dirname);
+
+ return 0;
}