Revert "Add some basic tests to check out fuse"
[openafs.git] / tests / auth / keys-t.c
1 /*
2  * Copyright (c) 2010 Your File System Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 /*!
26  * Tests for the afsconf key handling functions
27  */
28
29 #include <afsconfig.h>
30 #include <afs/param.h>
31
32 #include <roken.h>
33
34 #include <afs/cellconfig.h>
35 #include <afs/keys.h>
36 #include <afs/afsutil.h>
37 #include <rx/rxkad.h>
38
39 #include <tests/tap/basic.h>
40
41 #include "test.h"
42 #include "common.h"
43
44 static int
45 copy(char *inFile, char *outFile)
46 {
47     int in, out;
48     char *block;
49     size_t len;
50
51     in = open(inFile, O_RDONLY);
52     if (in<0)
53         return EIO;
54
55     out = open(outFile, O_WRONLY | O_CREAT, 0600);
56     if (out<0)
57         return EIO;
58
59     block = malloc(1024);
60     do {
61         len = read(in, block, 1024);
62         if (len > 0)
63             write(out, block, len);
64     } while (len > 0);
65     free(block);
66
67     close(in);
68     close(out);
69
70     if (len == -1)
71         return EIO;
72
73     return 0;
74 }
75
76 int
77 keyMatches(struct afsconf_typedKey *typedKey,
78            afsconf_keyType type, int kvno, int subType,
79            void *keyMaterial, size_t keyLen)
80 {
81     afsconf_keyType keyType;
82     int keyKvno;
83     int keySubType;
84     struct rx_opaque *buffer;
85
86     afsconf_typedKey_values(typedKey, &keyType, &keyKvno, &keySubType,
87                             &buffer);
88
89     return (keyType == type && keyKvno == kvno && keySubType == subType &&
90             buffer->len == keyLen &&
91             memcmp(keyMaterial, buffer->val, buffer->len) == 0);
92 }
93
94 int main(int argc, char **argv)
95 {
96     struct afsconf_dir *dir;
97     struct afsconf_keys keys;
98     struct ktc_encryptionKey key;
99     struct rx_opaque *keyMaterial;
100     struct afsconf_typedKey *typedKey;
101     struct afsconf_typedKeyList *typedKeyList;
102     char *dirname;
103     char *keyfile;
104     char *keyfilesrc;
105     afs_int32 kvno;
106     int code;
107     int i;
108
109     plan(134);
110
111     /* Create a temporary afs configuration directory */
112
113     dirname = afstest_BuildTestConfig();
114
115     if (asprintf(&keyfile, "%s/KeyFile", dirname) == -1)
116         goto out;
117
118     /* Work out the path to our KeyFile. If the test harness hasn't set
119      * the SOURCE environment variable, then assume it is in our CWD */
120     if (getenv("SOURCE") == NULL) {
121         keyfilesrc = strdup("KeyFile");
122     } else {
123         if (asprintf(&keyfilesrc, "%s/auth/KeyFile", getenv("SOURCE")) == -1)
124             goto out;
125     }
126
127     /* First, copy in a known keyfile */
128     code = copy(keyfilesrc, keyfile);
129     free(keyfilesrc);
130     if (code)
131         goto out;
132
133     /* Start with a blank configuration directory */
134     dir = afsconf_Open(dirname);
135     ok(dir != NULL, "Sucessfully re-opened config directory");
136     if (dir == NULL)
137         goto out;
138
139     /* Verify that GetKeys returns the entire set of keys correctly */
140     code = afsconf_GetKeys(dir, &keys);
141     is_int(0, code, "afsconf_GetKeys returns successfully");
142     is_int(3, keys.nkeys, "... and returns the right number of keys");
143     is_int(1, keys.key[0].kvno, " ... first key number is correct");
144     is_int(2, keys.key[1].kvno, " ... second key number is correct");
145     is_int(4, keys.key[2].kvno, " ... third key number is correct");
146     ok(memcmp(keys.key[0].key, "\x01\x02\x04\x08\x10\x20\x40\x80", 8) == 0,
147        " ... first key matches");
148     ok(memcmp(keys.key[1].key, "\x04\x04\x04\x04\x04\x04\x04\x04", 8) == 0,
149        " ... second key matches");
150     ok(memcmp(keys.key[2].key, "\x19\x16\xfe\xe6\xba\x77\x2f\xfd", 8) == 0,
151        " ... third key matches");
152
153     /* Verify that GetLatestKey returns the newest key */
154     code = afsconf_GetLatestKey(dir, &kvno, &key);
155     is_int(0, code, "afsconf_GetLatestKey returns sucessfully");
156     is_int(4, kvno, " ... with correct key number");
157     ok(memcmp(&key, "\x19\x16\xfe\xe6\xba\x77\x2f\xfd", 8) == 0,
158        " ... and correct key");
159
160     /* Check that GetLatestKey works if called with NULL parameters */
161     code = afsconf_GetLatestKey(dir, NULL, NULL);
162     is_int(0, code, "afsconf_GetLatestKey works if parameters are NULL");
163
164     /* Verify that random access using GetKey works properly */
165     code = afsconf_GetKey(dir, 2, &key);
166     is_int(0, code, "afsconf_GetKey returns successfully");
167     ok(memcmp(&key, "\x04\x04\x04\x04\x04\x04\x04\x04", 8) == 0,
168        " ... and with correct key");
169
170     /* And that it fails if the key number doesn't exist */
171     code = afsconf_GetKey(dir, 3, &key);
172     is_int(code, AFSCONF_NOTFOUND,
173            "afsconf_GetKey returns not found for missing key");
174
175     /* Check that AddKey can be used to add a new 'newest' key */
176     code = afsconf_AddKey(dir, 5, "\x08\x08\x08\x08\x08\x08\x08\x08", 0);
177     is_int(0, code, "afsconf_AddKey sucessfully adds a new key");
178
179     /* And that we can get it back with GetKeys, GetLatestKey and GetKey */
180     code = afsconf_GetKeys(dir, &keys);
181     is_int(0, code, " ... and GetKeys still works");
182     is_int(4, keys.nkeys, "... and has the correct number of keys");
183     is_int(5, keys.key[3].kvno, " ... and the fourth key has the correct kvno");
184     ok(memcmp(keys.key[3].key, "\x08\x08\x08\x08\x08\x08\x08\x08", 8) == 0,
185        " ... and is the correct key");
186
187     code = afsconf_GetLatestKey(dir, &kvno, &key);
188     is_int(0, code, " ... and GetLatestKey returns successfully");
189     is_int(5, kvno, " ... with the correct key number");
190     ok(memcmp(&key, "\x08\x08\x08\x08\x08\x08\x08\x08", 8) == 0,
191        " ... and the correct key");
192
193     code = afsconf_GetKey(dir, 5, &key);
194     is_int(0, code, " ... and GetKey still works");
195     ok(memcmp(&key, "\x08\x08\x08\x08\x08\x08\x08\x08", 8) == 0,
196        " ... and returns the correct key");
197
198     /* Check that AddKey without the overwrite flag won't overwrite an existing
199      * key */
200     code = afsconf_AddKey(dir, 5, "\x10\x10\x10\x10\x10\x10\x10", 0);
201     is_int(AFSCONF_KEYINUSE, code, "AddKey won't overwrite without being told to");
202
203     /* Check with GetKey that it didn't */
204     code = afsconf_GetKey(dir, 5, &key);
205     is_int(0, code, " ... and GetKey still works");
206     ok(memcmp(&key, "\x08\x08\x08\x08\x08\x08\x08\x08", 8) == 0,
207        " ... and key hasn't been overwritten");
208
209     /* Check that AddKey with the overwrite flag will overwrite an existing key */
210     code = afsconf_AddKey(dir, 5, "\x10\x10\x10\x10\x10\x10\x10\x10", 1);
211     is_int(0, code, "AddKey overwrites when asked");
212
213     /* Use GetKey to check that it did so */
214     code = afsconf_GetKey(dir, 5, &key);
215     is_int(0, code, " ... and GetKey still works");
216     ok(memcmp(&key, "\x10\x10\x10\x10\x10\x10\x10\x10", 8) == 0,
217        " ... and key has been overwritten");
218
219     /* Check that deleting a key that doesn't exist fails */
220     code = afsconf_DeleteKey(dir, 6);
221     is_int(AFSCONF_NOTFOUND, code,
222            "afsconf_DeleteKey returns NOTFOUND if key doesn't exist");
223
224     /* Check that we can delete a key using afsconf_DeleteKey */
225     code = afsconf_DeleteKey(dir, 2);
226     is_int(0, code, "afsconf_DeleteKey can delete a key");
227     code = afsconf_GetKey(dir, 2, &key);
228     is_int(AFSCONF_NOTFOUND, code, " ... and afsconf_GetKey can't find it");
229
230     /* Check that deleting it doesn't leave a hole in what GetKeys returns */
231     code = afsconf_GetKeys(dir, &keys);
232     is_int(0, code, "... and afsconf_GetKeys returns it");
233     is_int(3, keys.nkeys, "... and returns the right number of keys");
234     is_int(1, keys.key[0].kvno, " ... first key number is correct");
235     is_int(4, keys.key[1].kvno, " ... second key number is correct");
236     is_int(5, keys.key[2].kvno, " ... third key number is correct");
237
238     /* Make sure that if we drop the dir structure, and then rebuild it, we
239      * still have the same KeyFile */
240     afsconf_Close(dir);
241
242     dir = afsconf_Open(dirname);
243     ok(dir != NULL, "Sucessfully re-opened config directory");
244     if (dir == NULL)
245         goto out;
246
247     code = afsconf_GetKeys(dir, &keys);
248     is_int(0, code, "afsconf_GetKeys still works");
249     is_int(3, keys.nkeys, "... and returns the right number of keys");
250     is_int(1, keys.key[0].kvno, " ... first key number is correct");
251     is_int(4, keys.key[1].kvno, " ... second key number is correct");
252     is_int(5, keys.key[2].kvno, " ... third key number is correct");
253
254     /* Now check that we're limited to 8 keys */
255     for (i=0; i<5; i++) {
256         code = afsconf_AddKey(dir, 10+i, "\x10\x10\x10\x10\x10\x10\x10\x10",
257                               0);
258         is_int(0, code, "Adding %dth key with AddKey works", i+4);
259     }
260     code = afsconf_AddKey(dir, 20, "\x10\x10\x10\x10\x10\x10\x10\x10",0);
261     is_int(AFSCONF_FULL, code, "afsconf_AddKey fails once we've got 8 keys");
262
263     /* Check that the new interface also fails when we've got too many
264      * keys */
265     keyMaterial = rx_opaque_new("\x10\x10\x10\x10\x10\x10\x10\x10", 8);
266     typedKey = afsconf_typedKey_new(afsconf_rxkad, 20, 0, keyMaterial);
267     rx_opaque_free(&keyMaterial);
268     code = afsconf_AddTypedKey(dir, typedKey, 0);
269     afsconf_typedKey_put(&typedKey);
270     is_int(AFSCONF_FULL, code,
271            "afsconf_AddTypedKey fails for rxkad once we've got 8 keys");
272
273     /* Check the new accessors work for rxkad keys */
274     code = afsconf_GetKeyByTypes(dir, afsconf_rxkad, 4, 0, &typedKey);
275     is_int(0, code,
276            "afsconf_GetKeyByTypes works for rxkad");
277     ok(keyMatches(typedKey, afsconf_rxkad, 4, 0,
278                   "\x19\x16\xfe\xe6\xba\x77\x2f\xfd", 8),
279        " ... and returned key matches");
280
281     afsconf_typedKey_put(&typedKey);
282
283     code = afsconf_GetKeysByType(dir, afsconf_rxkad, 4, &typedKeyList);
284     is_int(0, code,
285            "afsconf_GetKeysByType works for rxkad");
286     is_int(1, typedKeyList->nkeys,
287            " ... and returns 1 key, as expected");
288     ok(keyMatches(typedKeyList->keys[0], afsconf_rxkad, 4, 0,
289                   "\x19\x16\xfe\xe6\xba\x77\x2f\xfd", 8),
290        " ... and returned key matches");
291
292     afsconf_PutTypedKeyList(&typedKeyList);
293
294     code = afsconf_GetLatestKeyByTypes(dir, afsconf_rxkad, 0, &typedKey);
295     is_int(0, code,
296            "afsconf_GetLatestKeyByTypes works for rxkad");
297     ok(keyMatches(typedKey, afsconf_rxkad, 14, 0,
298                   "\x10\x10\x10\x10\x10\x10\x10\x10", 8),
299        " ... and returned key matches");
300
301     afsconf_typedKey_put(&typedKey);
302
303     code = afsconf_GetLatestKeysByType(dir, afsconf_rxkad, &typedKeyList);
304     is_int(0, code,
305            "afsconf_GetLatestKeysByType works for rxkad");
306     is_int(1, typedKeyList->nkeys,
307            " ... and returns 1 key, as expected");
308     ok(keyMatches(typedKeyList->keys[0], afsconf_rxkad, 14, 0,
309                  "\x10\x10\x10\x10\x10\x10\x10\x10", 8),
310        " ... and returned key matches");
311     afsconf_PutTypedKeyList(&typedKeyList);
312
313     /* Check that we can't delete a key that doesn't exist */
314     code = afsconf_DeleteKeyByType(dir, afsconf_rxkad, 6);
315     is_int(AFSCONF_NOTFOUND, code,
316            "afsconf_DeleteKeyByType returns NOTFOUND if key doesn't exist");
317     code = afsconf_DeleteKeyBySubType(dir, afsconf_rxkad, 6, 0);
318     is_int(AFSCONF_NOTFOUND, code,
319            "afsconf_DeleteKeyBySubType returns NOTFOUND if key doesn't exist");
320     code = afsconf_DeleteKeyBySubType(dir, afsconf_rxkad, 14, 1);
321     is_int(AFSCONF_NOTFOUND, code,
322            "afsconf_DeleteKeyBySubType doesn't delete with wrong subtype");
323     code = afsconf_GetKeyByTypes(dir, afsconf_rxkad, 14, 0, &typedKey);
324     is_int(0, code, " ... and key is still there!");
325     afsconf_typedKey_put(&typedKey);
326
327     /* Check that we can delete a key that does */
328     code = afsconf_DeleteKeyByType(dir, afsconf_rxkad, 13);
329     is_int(0, code, "afsconf_DeleteKeyByType works");
330     code = afsconf_GetKeysByType(dir, afsconf_rxkad, 13, &typedKeyList);
331     is_int(AFSCONF_NOTFOUND, code, " ... and is really gone");
332
333     code = afsconf_DeleteKeyBySubType(dir, afsconf_rxkad, 14, 0);
334     is_int(0, code, "afsconf_DeleteKeyBySubType works");
335     code = afsconf_GetKeyByTypes(dir, afsconf_rxkad, 14, 0, &typedKey);
336     is_int(AFSCONF_NOTFOUND, code, " ... and is really gone");
337
338     /* Unlink the KeyFile */
339     unlink(keyfile);
340
341     /* Force a rebuild of the directory structure, just in case */
342     afsconf_Close(dir);
343
344     dir = afsconf_Open(dirname);
345     ok(dir != NULL, "Sucessfully re-opened config directory");
346     if (dir == NULL)
347         goto out;
348
349     /* Check that all of the various functions work properly if the file
350      * isn't there */
351     code = afsconf_GetKeys(dir, &keys);
352     is_int(0, code, "afsconf_GetKeys works with an empty KeyFile");
353     is_int(0, keys.nkeys, " ... and returns the right number of keys");
354     code = afsconf_GetKey(dir, 1, &key);
355     is_int(AFSCONF_NOTFOUND, code,
356            "afsconf_GetKey returns NOTFOUND with an empty KeyFile");
357     code = afsconf_DeleteKey(dir, 1);
358     is_int(AFSCONF_NOTFOUND, code,
359            "afsconf_DeleteKey returns NOTFOUND with an empty KeyFile");
360     code = afsconf_GetLatestKey(dir, &kvno, &key);
361     is_int(AFSCONF_NOTFOUND, code,
362            "afsconf_GetLatestKey returns NOTFOUND with an empty KeyFile");
363     code = afsconf_GetKeysByType(dir, afsconf_rxkad, 1, &typedKeyList);
364     is_int(AFSCONF_NOTFOUND, code,
365            "afsconf_GetKeysByType returns NOTFOUND with an empty KeyFile");
366     code = afsconf_GetKeyByTypes(dir, afsconf_rxkad, 1, 0, &typedKey);
367     is_int(AFSCONF_NOTFOUND, code,
368            "afsconf_GetKeyByTypes returns NOTFOUND with an empty KeyFile");
369     code = afsconf_GetLatestKeysByType(dir, afsconf_rxkad, &typedKeyList);
370     is_int(AFSCONF_NOTFOUND, code,
371            "afsconf_GetLatestKeysByType returns NOTFOUND with empty KeyFile");
372     code = afsconf_GetLatestKeyByTypes(dir, afsconf_rxkad, 0, &typedKey);
373     is_int(AFSCONF_NOTFOUND, code,
374            "afsconf_GetLatestKeyByTypes returns NOTFOUND with empty KeyFile");
375
376     /* Now try adding a key to an empty file */
377     code = afsconf_AddKey(dir, 1, "\x10\x10\x10\x10\x10\x10\x10\x10", 1);
378     is_int(0, code, "afsconf_AddKey succeeds with an empty KeyFile");
379     code = afsconf_GetLatestKey(dir, &kvno, &key);
380     is_int(0, code, " ... and afsconf_GetLatestKey succeeds");
381     is_int(1, kvno, " ... with correct kvno");
382     ok(memcmp(&key, "\x10\x10\x10\x10\x10\x10\x10\x10", 8) == 0,
383        " ... and key");
384
385     /* And adding a key using the new interface */
386
387     keyMaterial = rx_opaque_new("\x20\x20\x20\x20\x20\x20\x20\x20", 8);
388     typedKey = afsconf_typedKey_new(afsconf_rxkad, 2, 0, keyMaterial);
389     rx_opaque_free(&keyMaterial);
390     code = afsconf_AddTypedKey(dir, typedKey, 0);
391     afsconf_typedKey_put(&typedKey);
392     is_int(0, code, "afsconf_AddTypedKey works");
393     code = afsconf_GetLatestKey(dir, &kvno, &key);
394     is_int(0, code, " ... and afsconf_GetLatestKey succeeds");
395     is_int(2, kvno, " ... with correct kvno");
396     ok(memcmp(&key, "\x20\x20\x20\x20\x20\x20\x20\x20", 8) == 0,
397        " ... and key");
398     code = afsconf_GetLatestKeyByTypes(dir, afsconf_rxkad, 0, &typedKey);
399     is_int(0, code, " ... and so does afsconf_GetLatestKeyByTypes");
400     ok(keyMatches(typedKey, afsconf_rxkad, 2, 0,
401                   "\x20\x20\x20\x20\x20\x20\x20\x20", 8),
402        " ... with correct key");
403     afsconf_typedKey_put(&typedKey);
404
405     /* And that we can't add a key to an existing kvno and type */
406     keyMaterial = rx_opaque_new("\x30\x30\x30\x30\x30\x30\x30\x30", 8);
407     typedKey = afsconf_typedKey_new(afsconf_rxkad, 2, 0, keyMaterial);
408     rx_opaque_free(&keyMaterial);
409     code = afsconf_AddTypedKey(dir, typedKey, 0);
410     afsconf_typedKey_put(&typedKey);
411     is_int(AFSCONF_KEYINUSE, code,
412            "afsconf_AddTypedKey won't overwrite without being told to");
413     code = afsconf_GetKeyByTypes(dir, afsconf_rxkad, 2, 0, &typedKey);
414     is_int(0, code, " ... and key still exists");
415     ok(keyMatches(typedKey, afsconf_rxkad, 2, 0,
416                   "\x20\x20\x20\x20\x20\x20\x20\x20", 8),
417        " ... and hasn't changed");
418     afsconf_typedKey_put(&typedKey);
419
420     /* But we can if we force */
421     keyMaterial = rx_opaque_new("\x30\x30\x30\x30\x30\x30\x30\x30", 8);
422     typedKey = afsconf_typedKey_new(afsconf_rxkad, 2, 0, keyMaterial);
423     rx_opaque_free(&keyMaterial);
424     code = afsconf_AddTypedKey(dir, typedKey, 1);
425     afsconf_typedKey_put(&typedKey);
426     is_int(0, code,  "afsconf_AddTypedKey overwrites when asked");
427     code = afsconf_GetKeyByTypes(dir, afsconf_rxkad, 2, 0, &typedKey);
428     is_int(0, code, " ... and GetKeyByTypes retrieves new key");
429     ok(keyMatches(typedKey, afsconf_rxkad, 2, 0,
430                   "\x30\x30\x30\x30\x30\x30\x30\x30", 8),
431        " ... and it is the new key");
432
433     /* Check that we can't add bad rxkad keys */
434     keyMaterial = rx_opaque_new("\x30\x30\x30\x30\x30\x30\x30", 7);
435     typedKey = afsconf_typedKey_new(afsconf_rxkad, 3, 0, keyMaterial);
436     rx_opaque_free(&keyMaterial);
437     code = afsconf_AddTypedKey(dir, typedKey, 1);
438     afsconf_typedKey_put(&typedKey);
439     is_int(AFSCONF_BADKEY, code,
440            "afsconf_AddTypedKey won't add short rxkad keys");
441     keyMaterial = rx_opaque_new("\x30\x30\x30\x30\x30\x30\x30\x30\x30", 9);
442     typedKey = afsconf_typedKey_new(afsconf_rxkad, 3, 0, keyMaterial);
443     rx_opaque_free(&keyMaterial);
444     code = afsconf_AddTypedKey(dir, typedKey, 1);
445     afsconf_typedKey_put(&typedKey);
446     is_int(AFSCONF_BADKEY, code,
447            "afsconf_AddTypedKey won't add long rxkad keys");
448     keyMaterial = rx_opaque_new("\x30\x30\x30\x30\x30\x30\x30\x30", 8);
449     typedKey = afsconf_typedKey_new(afsconf_rxkad, 3, 1, keyMaterial);
450     rx_opaque_free(&keyMaterial);
451     code = afsconf_AddTypedKey(dir, typedKey, 1);
452     afsconf_typedKey_put(&typedKey);
453     is_int(AFSCONF_BADKEY, code,
454            "afsconf_AddTypedKey won't add rxkad keys with non-zero subtype");
455
456     /* Now, test things with other key types. */
457
458     /* Add a different key type, but with same kvno as rxkad */
459     keyMaterial = rx_opaque_new("\x01", 1);
460     typedKey = afsconf_typedKey_new(1, 2, 0, keyMaterial);
461     code = afsconf_AddTypedKey(dir, typedKey, 0);
462     afsconf_typedKey_put(&typedKey);
463     is_int(0, code,
464            "afsconf_AddTypedKey can add keys with different key type");
465
466     /* Add a different subtype, with same kvno */
467     keyMaterial = rx_opaque_new("\x02\x03", 2);
468     typedKey = afsconf_typedKey_new(1, 2, 1, keyMaterial);
469     code = afsconf_AddTypedKey(dir, typedKey, 0);
470     afsconf_typedKey_put(&typedKey);
471     is_int(0, code,
472            "afsconf_AddTypedKey can add keys with different sub type");
473
474     /* Check the GetKeyByTypes returns one of the keys */
475     code = afsconf_GetKeyByTypes(dir, 1, 2, 1, &typedKey);
476     is_int(0, code, "afsconf_GetKeyByTypes returns");
477     ok(keyMatches(typedKey, 1, 2, 1, "\x02\x03", 2),
478        " ... with the right key");
479
480     /* Check that GetKeysByType returns both of the keys */
481     code = afsconf_GetKeysByType(dir, 1, 2, &typedKeyList);
482     is_int(0, code, "afsconf_GetKeysByType returns");
483     is_int(2, typedKeyList->nkeys, " ... with correct number of keys");
484     ok(keyMatches(typedKeyList->keys[0], 1, 2, 0, "\x01", 1),
485        " ... with the right key in slot 0");
486     ok(keyMatches(typedKeyList->keys[1], 1, 2, 1, "\x02\x03", 2),
487        " ... with the right key in slot 1");
488     afsconf_PutTypedKeyList(&typedKeyList);
489
490     /* Add another key, before these ones, so we can check that
491      * latest really works */
492     keyMaterial = rx_opaque_new("\x03", 1);
493     typedKey = afsconf_typedKey_new(1, 1, 0, keyMaterial);
494     code = afsconf_AddTypedKey(dir, typedKey, 0);
495     afsconf_typedKey_put(&typedKey);
496     is_int(0, code, "afsconf_AddTypedKey worked again");
497
498     /* Check that GetLatestKeyByTypes returns one */
499     code = afsconf_GetLatestKeyByTypes(dir, 1, 1, &typedKey);
500     is_int(0, code, "afsconf_GetLatestKeyByTypes returns");
501     ok(keyMatches(typedKey, 1, 2, 1, "\x02\x03", 2),
502        " ... with the right key");
503
504     /* Check that GetLatestKeysByType returns both */
505     code = afsconf_GetLatestKeysByType(dir, 1, &typedKeyList);
506     is_int(0, code, "afsconf_GetLatestKeysByType returns");
507         is_int(2, typedKeyList->nkeys, " ... with correct number of keys");
508     ok(keyMatches(typedKeyList->keys[0], 1, 2, 0, "\x01", 1),
509        " ... with the right key in slot 0");
510     ok(keyMatches(typedKeyList->keys[1], 1, 2, 1, "\x02\x03", 2),
511        " ... with the right key in slot 1");
512     afsconf_PutTypedKeyList(&typedKeyList);
513
514     /* Check that closing this instance, and reopening, still has all of
515      * the required keys
516      */
517     afsconf_Close(dir);
518
519     dir = afsconf_Open(dirname);
520     ok(dir != NULL, "Sucessfully re-opened config directory");
521     if (dir == NULL)
522         goto out;
523
524     /* Check that GetKeysByType returns all of the keys */
525     code = afsconf_GetKeysByType(dir, 1, 1, &typedKeyList);
526     is_int(0, code, "afsconf_GetKeysByType returns after reopening");
527     is_int(1, typedKeyList->nkeys, " ... First kvno has correct number of keys");
528     ok(keyMatches(typedKeyList->keys[0], 1, 1, 0, "\x03", 1),
529        " ... and key material is correct");
530     afsconf_PutTypedKeyList(&typedKeyList);
531
532     code = afsconf_GetKeysByType(dir, 1, 2, &typedKeyList);
533     is_int(0, code, "afsconf_GetKeysByType returns after reopening");
534     is_int(2, typedKeyList->nkeys, " ... with correct number of keys");
535     ok(keyMatches(typedKeyList->keys[0], 1, 2, 0, "\x01", 1),
536        " ... with the right key in slot 0");
537     ok(keyMatches(typedKeyList->keys[1], 1, 2, 1, "\x02\x03", 2),
538        " ... with the right key in slot 1");
539     afsconf_PutTypedKeyList(&typedKeyList);
540
541     /* Check that GetAllKeys works as expected */
542     code = afsconf_GetAllKeys(dir, &typedKeyList);
543     is_int(0, code, "afsconf_GetAllKeys returns success");
544     is_int(5, typedKeyList->nkeys, " ... with the correct number of keys");
545     ok(keyMatches(typedKeyList->keys[0], afsconf_rxkad, 1, 0,
546                   "\x10\x10\x10\x10\x10\x10\x10\x10", 8),
547        " ... with right key in slot 0");
548     ok(keyMatches(typedKeyList->keys[1], afsconf_rxkad, 2, 0,
549                    "\x30\x30\x30\x30\x30\x30\x30\x30", 8),
550        " ... with right key in slot 1");
551     ok(keyMatches(typedKeyList->keys[2], 1, 1, 0, "\x03", 1),
552        " ... with right key in slot 2");
553     ok(keyMatches(typedKeyList->keys[3], 1, 2, 0, "\x01", 1),
554        " ... with right key in slot 3");
555     ok(keyMatches(typedKeyList->keys[4], 1, 2, 1, "\x02\03", 2),
556        " ... with right key in slot 4");
557
558     afsconf_Close(dir);
559
560     afstest_UnlinkTestConfig(dirname);
561     free(dirname);
562     free(keyfile);
563
564     /* Start a new test configuration */
565     dirname = afstest_BuildTestConfig();
566     dir = afsconf_Open(dirname);
567     ok(dir != NULL, "Sucessfully opened brand new config directory");
568     if (dir == NULL)
569         goto out;
570
571     /* Check that directories with just new style keys work */
572     keyMaterial = rx_opaque_new("\x02\x03", 2);
573     typedKey = afsconf_typedKey_new(1, 2, 1, keyMaterial);
574     code = afsconf_AddTypedKey(dir, typedKey, 0);
575     afsconf_typedKey_put(&typedKey);
576     is_int(0, code,
577            "afsconf_AddTypedKey can add keys with different sub type");
578
579     /* Check the GetKeyByTypes returns one of the keys */
580     code = afsconf_GetKeyByTypes(dir, 1, 2, 1, &typedKey);
581     is_int(0, code, "afsconf_GetKeyByTypes returns it");
582     ok(keyMatches(typedKey, 1, 2, 1, "\x02\x03", 2),
583        " ... with the right key");
584
585 out:
586     afstest_UnlinkTestConfig(dirname);
587
588     return 0;
589 }