auth: GetLatestKey should allow NULL return values
[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 <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     afs_int32 kvno;
105     int code;
106     int i;
107
108     plan(123);
109
110     /* Create a temporary afs configuration directory */
111
112     dirname = buildTestConfig();
113
114     if (asprintf(&keyfile, "%s/KeyFile", dirname) == -1)
115         goto out;
116
117     /* First, copy in a known keyfile */
118     code = copy("KeyFile", keyfile);
119     if (code)
120         goto out;
121
122     /* Start with a blank configuration directory */
123     dir = afsconf_Open(dirname);
124     ok(dir != NULL, "Sucessfully re-opened config directory");
125     if (dir == NULL)
126         goto out;
127
128     /* Verify that GetKeys returns the entire set of keys correctly */
129     code = afsconf_GetKeys(dir, &keys);
130     is_int(0, code, "afsconf_GetKeys returns successfully");
131     is_int(3, keys.nkeys, "... and returns the right number of keys");
132     is_int(1, keys.key[0].kvno, " ... first key number is correct");
133     is_int(2, keys.key[1].kvno, " ... second key number is correct");
134     is_int(4, keys.key[2].kvno, " ... third key number is correct");
135     ok(memcmp(keys.key[0].key, "\x01\x02\x04\x08\x10\x20\x40\x80", 8) == 0,
136        " ... first key matches");
137     ok(memcmp(keys.key[1].key, "\x04\x04\x04\x04\x04\x04\x04\x04", 8) == 0,
138        " ... second key matches");
139     ok(memcmp(keys.key[2].key, "\x19\x16\xfe\xe6\xba\x77\x2f\xfd", 8) == 0,
140        " ... third key matches");
141
142     /* Verify that GetLatestKey returns the newest key */
143     code = afsconf_GetLatestKey(dir, &kvno, &key);
144     is_int(0, code, "afsconf_GetLatestKey returns sucessfully");
145     is_int(4, kvno, " ... with correct key number");
146     ok(memcmp(&key, "\x19\x16\xfe\xe6\xba\x77\x2f\xfd", 8) == 0,
147        " ... and correct key");
148
149     /* Check that GetLatestKey works if called with NULL parameters */
150     code = afsconf_GetLatestKey(dir, NULL, NULL);
151     is_int(0, code, "afsconf_GetLatestKey works if parameters are NULL");
152
153     /* Verify that random access using GetKey works properly */
154     code = afsconf_GetKey(dir, 2, &key);
155     is_int(0, code, "afsconf_GetKey returns successfully");
156     ok(memcmp(&key, "\x04\x04\x04\x04\x04\x04\x04\x04", 8) == 0,
157        " ... and with correct key");
158
159     /* And that it fails if the key number doesn't exist */
160     code = afsconf_GetKey(dir, 3, &key);
161     is_int(code, AFSCONF_NOTFOUND,
162            "afsconf_GetKey returns not found for missing key");
163
164     /* Check that AddKey can be used to add a new 'newest' key */
165     code = afsconf_AddKey(dir, 5, "\x08\x08\x08\x08\x08\x08\x08\x08", 0);
166     is_int(0, code, "afsconf_AddKey sucessfully adds a new key");
167
168     /* And that we can get it back with GetKeys, GetLatestKey and GetKey */
169     code = afsconf_GetKeys(dir, &keys);
170     is_int(0, code, " ... and GetKeys still works");
171     is_int(4, keys.nkeys, "... and has the correct number of keys");
172     is_int(5, keys.key[3].kvno, " ... and the fourth key has the correct kvno");
173     ok(memcmp(keys.key[3].key, "\x08\x08\x08\x08\x08\x08\x08\x08", 8) == 0,
174        " ... and is the correct key");
175
176     code = afsconf_GetLatestKey(dir, &kvno, &key);
177     is_int(0, code, " ... and GetLatestKey returns successfully");
178     is_int(5, kvno, " ... with the correct key number");
179     ok(memcmp(&key, "\x08\x08\x08\x08\x08\x08\x08\x08", 8) == 0,
180        " ... and the correct key");
181
182     code = afsconf_GetKey(dir, 5, &key);
183     is_int(0, code, " ... and GetKey still works");
184     ok(memcmp(&key, "\x08\x08\x08\x08\x08\x08\x08\x08", 8) == 0,
185        " ... and returns the correct key");
186
187     /* Check that AddKey without the overwrite flag won't overwrite an existing
188      * key */
189     code = afsconf_AddKey(dir, 5, "\x10\x10\x10\x10\x10\x10\x10", 0);
190     is_int(AFSCONF_KEYINUSE, code, "AddKey won't overwrite without being told to");
191
192     /* Check with GetKey that it didn't */
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 key hasn't been overwritten");
197
198     /* Check that AddKey with the overwrite flag will overwrite an existing key */
199     code = afsconf_AddKey(dir, 5, "\x10\x10\x10\x10\x10\x10\x10\x10", 1);
200     is_int(0, code, "AddKey overwrites when asked");
201
202     /* Use GetKey to check that it did so */
203     code = afsconf_GetKey(dir, 5, &key);
204     is_int(0, code, " ... and GetKey still works");
205     ok(memcmp(&key, "\x10\x10\x10\x10\x10\x10\x10\x10", 8) == 0,
206        " ... and key has been overwritten");
207
208     /* Check that deleting a key that doesn't exist fails */
209     code = afsconf_DeleteKey(dir, 6);
210     is_int(AFSCONF_NOTFOUND, code,
211            "afsconf_DeleteKey returns NOTFOUND if key doesn't exist");
212
213     /* Check that we can delete a key using afsconf_DeleteKey */
214     code = afsconf_DeleteKey(dir, 2);
215     is_int(0, code, "afsconf_DeleteKey can delete a key");
216     code = afsconf_GetKey(dir, 2, &key);
217     is_int(AFSCONF_NOTFOUND, code, " ... and afsconf_GetKey can't find it");
218
219     /* Check that deleting it doesn't leave a hole in what GetKeys returns */
220     code = afsconf_GetKeys(dir, &keys);
221     is_int(0, code, "... and afsconf_GetKeys returns it");
222     is_int(3, keys.nkeys, "... and returns the right number of keys");
223     is_int(1, keys.key[0].kvno, " ... first key number is correct");
224     is_int(4, keys.key[1].kvno, " ... second key number is correct");
225     is_int(5, keys.key[2].kvno, " ... third key number is correct");
226
227     /* Make sure that if we drop the dir structure, and then rebuild it, we
228      * still have the same KeyFile */
229     afsconf_Close(dir);
230
231     dir = afsconf_Open(dirname);
232     ok(dir != NULL, "Sucessfully re-opened config directory");
233     if (dir == NULL)
234         goto out;
235
236     code = afsconf_GetKeys(dir, &keys);
237     is_int(0, code, "afsconf_GetKeys still works");
238     is_int(3, keys.nkeys, "... and returns the right number of keys");
239     is_int(1, keys.key[0].kvno, " ... first key number is correct");
240     is_int(4, keys.key[1].kvno, " ... second key number is correct");
241     is_int(5, keys.key[2].kvno, " ... third key number is correct");
242
243     /* Now check that we're limited to 8 keys */
244     for (i=0; i<5; i++) {
245         code = afsconf_AddKey(dir, 10+i, "\x10\x10\x10\x10\x10\x10\x10\x10",
246                               0);
247         is_int(0, code, "Adding %dth key with AddKey works", i+4);
248     }
249     code = afsconf_AddKey(dir, 20, "\x10\x10\x10\x10\x10\x10\x10\x10",0);
250     is_int(AFSCONF_FULL, code, "afsconf_AddKey fails once we've got 8 keys");
251
252     /* Check that the new interface also fails when we've got too many
253      * keys */
254     keyMaterial = rx_opaque_new("\x10\x10\x10\x10\x10\x10\x10\x10", 8);
255     typedKey = afsconf_typedKey_new(afsconf_rxkad, 20, 0, keyMaterial);
256     rx_opaque_free(&keyMaterial);
257     code = afsconf_AddTypedKey(dir, typedKey, 0);
258     afsconf_typedKey_put(&typedKey);
259     is_int(AFSCONF_FULL, code,
260            "afsconf_AddTypedKey fails for rxkad once we've got 8 keys");
261
262     /* Check the new accessors work for rxkad keys */
263     code = afsconf_GetKeyByTypes(dir, afsconf_rxkad, 4, 0, &typedKey);
264     is_int(0, code,
265            "afsconf_GetKeyByTypes works for rxkad");
266     ok(keyMatches(typedKey, afsconf_rxkad, 4, 0,
267                   "\x19\x16\xfe\xe6\xba\x77\x2f\xfd", 8),
268        " ... and returned key matches");
269
270     afsconf_typedKey_put(&typedKey);
271
272     code = afsconf_GetKeysByType(dir, afsconf_rxkad, 4, &typedKeyList);
273     is_int(0, code,
274            "afsconf_GetKeysByType works for rxkad");
275     is_int(1, typedKeyList->nkeys,
276            " ... and returns 1 key, as expected");
277     ok(keyMatches(typedKeyList->keys[0], afsconf_rxkad, 4, 0,
278                   "\x19\x16\xfe\xe6\xba\x77\x2f\xfd", 8),
279        " ... and returned key matches");
280
281     afsconf_PutTypedKeyList(&typedKeyList);
282
283     code = afsconf_GetLatestKeyByTypes(dir, afsconf_rxkad, 0, &typedKey);
284     is_int(0, code,
285            "afsconf_GetLatestKeyByTypes works for rxkad");
286     ok(keyMatches(typedKey, afsconf_rxkad, 14, 0,
287                   "\x10\x10\x10\x10\x10\x10\x10\x10", 8),
288        " ... and returned key matches");
289
290     afsconf_typedKey_put(&typedKey);
291
292     code = afsconf_GetLatestKeysByType(dir, afsconf_rxkad, &typedKeyList);
293     is_int(0, code,
294            "afsconf_GetLatestKeysByType works for rxkad");
295     is_int(1, typedKeyList->nkeys,
296            " ... and returns 1 key, as expected");
297     ok(keyMatches(typedKeyList->keys[0], afsconf_rxkad, 14, 0,
298                  "\x10\x10\x10\x10\x10\x10\x10\x10", 8),
299        " ... and returned key matches");
300     afsconf_PutTypedKeyList(&typedKeyList);
301
302     /* Check that we can't delete a key that doesn't exist */
303     code = afsconf_DeleteKeyByType(dir, afsconf_rxkad, 6);
304     is_int(AFSCONF_NOTFOUND, code,
305            "afsconf_DeleteKeyByType returns NOTFOUND if key doesn't exist");
306     code = afsconf_DeleteKeyBySubType(dir, afsconf_rxkad, 6, 0);
307     is_int(AFSCONF_NOTFOUND, code,
308            "afsconf_DeleteKeyBySubType returns NOTFOUND if key doesn't exist");
309     code = afsconf_DeleteKeyBySubType(dir, afsconf_rxkad, 14, 1);
310     is_int(AFSCONF_NOTFOUND, code,
311            "afsconf_DeleteKeyBySubType doesn't delete with wrong subtype");
312     code = afsconf_GetKeyByTypes(dir, afsconf_rxkad, 14, 0, &typedKey);
313     is_int(0, code, " ... and key is still there!");
314     afsconf_typedKey_put(&typedKey);
315
316     /* Check that we can delete a key that does */
317     code = afsconf_DeleteKeyByType(dir, afsconf_rxkad, 13);
318     is_int(0, code, "afsconf_DeleteKeyByType works");
319     code = afsconf_GetKeysByType(dir, afsconf_rxkad, 13, &typedKeyList);
320     is_int(AFSCONF_NOTFOUND, code, " ... and is really gone");
321
322     code = afsconf_DeleteKeyBySubType(dir, afsconf_rxkad, 14, 0);
323     is_int(0, code, "afsconf_DeleteKeyBySubType works");
324     code = afsconf_GetKeyByTypes(dir, afsconf_rxkad, 14, 0, &typedKey);
325     is_int(AFSCONF_NOTFOUND, code, " ... and is really gone");
326
327     /* Unlink the KeyFile */
328     unlink(keyfile);
329
330     /* Force a rebuild of the directory structure, just in case */
331     afsconf_Close(dir);
332
333     dir = afsconf_Open(dirname);
334     ok(dir != NULL, "Sucessfully re-opened config directory");
335     if (dir == NULL)
336         goto out;
337
338     /* Check that all of the various functions work properly if the file
339      * isn't there */
340     code = afsconf_GetKeys(dir, &keys);
341     is_int(0, code, "afsconf_GetKeys works with an empty KeyFile");
342     is_int(0, keys.nkeys, " ... and returns the right number of keys");
343     code = afsconf_GetKey(dir, 1, &key);
344     is_int(AFSCONF_NOTFOUND, code,
345            "afsconf_GetKey returns NOTFOUND with an empty KeyFile");
346     code = afsconf_DeleteKey(dir, 1);
347     is_int(AFSCONF_NOTFOUND, code,
348            "afsconf_DeleteKey returns NOTFOUND with an empty KeyFile");
349     code = afsconf_GetLatestKey(dir, &kvno, &key);
350     is_int(AFSCONF_NOTFOUND, code,
351            "afsconf_GetLatestKey returns NOTFOUND with an empty KeyFile");
352     code = afsconf_GetKeysByType(dir, afsconf_rxkad, 1, &typedKeyList);
353     is_int(AFSCONF_NOTFOUND, code,
354            "afsconf_GetKeysByType returns NOTFOUND with an empty KeyFile");
355     code = afsconf_GetKeyByTypes(dir, afsconf_rxkad, 1, 0, &typedKey);
356     is_int(AFSCONF_NOTFOUND, code,
357            "afsconf_GetKeyByTypes returns NOTFOUND with an empty KeyFile");
358     code = afsconf_GetLatestKeysByType(dir, afsconf_rxkad, &typedKeyList);
359     is_int(AFSCONF_NOTFOUND, code,
360            "afsconf_GetLatestKeysByType returns NOTFOUND with empty KeyFile");
361     code = afsconf_GetLatestKeyByTypes(dir, afsconf_rxkad, 0, &typedKey);
362     is_int(AFSCONF_NOTFOUND, code,
363            "afsconf_GetLatestKeyByTypes returns NOTFOUND with empty KeyFile");
364
365     /* Now try adding a key to an empty file */
366     code = afsconf_AddKey(dir, 1, "\x10\x10\x10\x10\x10\x10\x10\x10", 1);
367     is_int(0, code, "afsconf_AddKey succeeds with an empty KeyFile");
368     code = afsconf_GetLatestKey(dir, &kvno, &key);
369     is_int(0, code, " ... and afsconf_GetLatestKey succeeds");
370     is_int(1, kvno, " ... with correct kvno");
371     ok(memcmp(&key, "\x10\x10\x10\x10\x10\x10\x10\x10", 8) == 0,
372        " ... and key");
373
374     /* And adding a key using the new interface */
375
376     keyMaterial = rx_opaque_new("\x20\x20\x20\x20\x20\x20\x20\x20", 8);
377     typedKey = afsconf_typedKey_new(afsconf_rxkad, 2, 0, keyMaterial);
378     rx_opaque_free(&keyMaterial);
379     code = afsconf_AddTypedKey(dir, typedKey, 0);
380     afsconf_typedKey_put(&typedKey);
381     is_int(0, code, "afsconf_AddTypedKey works");
382     code = afsconf_GetLatestKey(dir, &kvno, &key);
383     is_int(0, code, " ... and afsconf_GetLatestKey succeeds");
384     is_int(2, kvno, " ... with correct kvno");
385     ok(memcmp(&key, "\x20\x20\x20\x20\x20\x20\x20\x20", 8) == 0,
386        " ... and key");
387     code = afsconf_GetLatestKeyByTypes(dir, afsconf_rxkad, 0, &typedKey);
388     is_int(0, code, " ... and so does afsconf_GetLatestKeyByTypes");
389     ok(keyMatches(typedKey, afsconf_rxkad, 2, 0,
390                   "\x20\x20\x20\x20\x20\x20\x20\x20", 8),
391        " ... with correct key");
392     afsconf_typedKey_put(&typedKey);
393
394     /* And that we can't add a key to an existing kvno and type */
395     keyMaterial = rx_opaque_new("\x30\x30\x30\x30\x30\x30\x30\x30", 8);
396     typedKey = afsconf_typedKey_new(afsconf_rxkad, 2, 0, keyMaterial);
397     rx_opaque_free(&keyMaterial);
398     code = afsconf_AddTypedKey(dir, typedKey, 0);
399     afsconf_typedKey_put(&typedKey);
400     is_int(AFSCONF_KEYINUSE, code,
401            "afsconf_AddTypedKey won't overwrite without being told to");
402     code = afsconf_GetKeyByTypes(dir, afsconf_rxkad, 2, 0, &typedKey);
403     is_int(0, code, " ... and key still exists");
404     ok(keyMatches(typedKey, afsconf_rxkad, 2, 0,
405                   "\x20\x20\x20\x20\x20\x20\x20\x20", 8),
406        " ... and hasn't changed");
407     afsconf_typedKey_put(&typedKey);
408
409     /* But we can if we force */
410     keyMaterial = rx_opaque_new("\x30\x30\x30\x30\x30\x30\x30\x30", 8);
411     typedKey = afsconf_typedKey_new(afsconf_rxkad, 2, 0, keyMaterial);
412     rx_opaque_free(&keyMaterial);
413     code = afsconf_AddTypedKey(dir, typedKey, 1);
414     afsconf_typedKey_put(&typedKey);
415     is_int(0, code,  "afsconf_AddTypedKey overwrites when asked");
416     code = afsconf_GetKeyByTypes(dir, afsconf_rxkad, 2, 0, &typedKey);
417     is_int(0, code, " ... and GetKeyByTypes retrieves new key");
418     ok(keyMatches(typedKey, afsconf_rxkad, 2, 0,
419                   "\x30\x30\x30\x30\x30\x30\x30\x30", 8),
420        " ... and it is the new key");
421
422     /* Check that we can't add bad rxkad keys */
423     keyMaterial = rx_opaque_new("\x30\x30\x30\x30\x30\x30\x30", 7);
424     typedKey = afsconf_typedKey_new(afsconf_rxkad, 3, 0, keyMaterial);
425     rx_opaque_free(&keyMaterial);
426     code = afsconf_AddTypedKey(dir, typedKey, 1);
427     afsconf_typedKey_put(&typedKey);
428     is_int(AFSCONF_BADKEY, code,
429            "afsconf_AddTypedKey won't add short rxkad keys");
430     keyMaterial = rx_opaque_new("\x30\x30\x30\x30\x30\x30\x30\x30\x30", 9);
431     typedKey = afsconf_typedKey_new(afsconf_rxkad, 3, 0, keyMaterial);
432     rx_opaque_free(&keyMaterial);
433     code = afsconf_AddTypedKey(dir, typedKey, 1);
434     afsconf_typedKey_put(&typedKey);
435     is_int(AFSCONF_BADKEY, code,
436            "afsconf_AddTypedKey won't add long rxkad keys");
437     keyMaterial = rx_opaque_new("\x30\x30\x30\x30\x30\x30\x30\x30", 8);
438     typedKey = afsconf_typedKey_new(afsconf_rxkad, 3, 1, keyMaterial);
439     rx_opaque_free(&keyMaterial);
440     code = afsconf_AddTypedKey(dir, typedKey, 1);
441     afsconf_typedKey_put(&typedKey);
442     is_int(AFSCONF_BADKEY, code,
443            "afsconf_AddTypedKey won't add rxkad keys with non-zero subtype");
444
445     /* Now, test things with other key types. */
446
447     /* Add a different key type, but with same kvno as rxkad */
448     keyMaterial = rx_opaque_new("\x01", 1);
449     typedKey = afsconf_typedKey_new(1, 2, 0, keyMaterial);
450     code = afsconf_AddTypedKey(dir, typedKey, 0);
451     afsconf_typedKey_put(&typedKey);
452     is_int(0, code,
453            "afsconf_AddTypedKey can add keys with different key type");
454
455     /* Add a different subtype, with same kvno */
456     keyMaterial = rx_opaque_new("\x02\x03", 2);
457     typedKey = afsconf_typedKey_new(1, 2, 1, keyMaterial);
458     code = afsconf_AddTypedKey(dir, typedKey, 0);
459     afsconf_typedKey_put(&typedKey);
460     is_int(0, code,
461            "afsconf_AddTypedKey can add keys with different sub type");
462
463     /* Check the GetKeyByTypes returns one of the keys */
464     code = afsconf_GetKeyByTypes(dir, 1, 2, 1, &typedKey);
465     is_int(0, code, "afsconf_GetKeyByTypes returns");
466     ok(keyMatches(typedKey, 1, 2, 1, "\x02\x03", 2),
467        " ... with the right key");
468
469     /* Check that GetKeysByType returns both of the keys */
470     code = afsconf_GetKeysByType(dir, 1, 2, &typedKeyList);
471     is_int(0, code, "afsconf_GetKeysByType returns");
472     is_int(2, typedKeyList->nkeys, " ... with correct number of keys");
473     ok(keyMatches(typedKeyList->keys[0], 1, 2, 0, "\x01", 1),
474        " ... with the right key in slot 0");
475     ok(keyMatches(typedKeyList->keys[1], 1, 2, 1, "\x02\x03", 2),
476        " ... with the right key in slot 1");
477     afsconf_PutTypedKeyList(&typedKeyList);
478
479     /* Add another key, before these ones, so we can check that
480      * latest really works */
481     keyMaterial = rx_opaque_new("\x03", 1);
482     typedKey = afsconf_typedKey_new(1, 1, 0, keyMaterial);
483     code = afsconf_AddTypedKey(dir, typedKey, 0);
484     afsconf_typedKey_put(&typedKey);
485     is_int(0, code, "afsconf_AddTypedKey worked again");
486
487     /* Check that GetLatestKeyByTypes returns one */
488     code = afsconf_GetLatestKeyByTypes(dir, 1, 1, &typedKey);
489     is_int(0, code, "afsconf_GetLatestKeyByTypes returns");
490     ok(keyMatches(typedKey, 1, 2, 1, "\x02\x03", 2),
491        " ... with the right key");
492
493     /* Check that GetLatestKeysByType returns both */
494     code = afsconf_GetLatestKeysByType(dir, 1, &typedKeyList);
495     is_int(0, code, "afsconf_GetLatestKeysByType returns");
496         is_int(2, typedKeyList->nkeys, " ... with correct number of keys");
497     ok(keyMatches(typedKeyList->keys[0], 1, 2, 0, "\x01", 1),
498        " ... with the right key in slot 0");
499     ok(keyMatches(typedKeyList->keys[1], 1, 2, 1, "\x02\x03", 2),
500        " ... with the right key in slot 1");
501     afsconf_PutTypedKeyList(&typedKeyList);
502
503     /* Check that closing this instance, and reopening, still has all of
504      * the required keys
505      */
506     afsconf_Close(dir);
507
508     dir = afsconf_Open(dirname);
509     ok(dir != NULL, "Sucessfully re-opened config directory");
510     if (dir == NULL)
511         goto out;
512
513     /* Check that GetKeysByType returns all of the keys */
514     code = afsconf_GetKeysByType(dir, 1, 1, &typedKeyList);
515     is_int(0, code, "afsconf_GetKeysByType returns after reopening");
516     is_int(1, typedKeyList->nkeys, " ... First kvno has correct number of keys");
517     ok(keyMatches(typedKeyList->keys[0], 1, 1, 0, "\x03", 1),
518        " ... and key material is correct");
519     afsconf_PutTypedKeyList(&typedKeyList);
520
521     code = afsconf_GetKeysByType(dir, 1, 2, &typedKeyList);
522     is_int(0, code, "afsconf_GetKeysByType returns after reopening");
523     is_int(2, typedKeyList->nkeys, " ... with correct number of keys");
524     ok(keyMatches(typedKeyList->keys[0], 1, 2, 0, "\x01", 1),
525        " ... with the right key in slot 0");
526     ok(keyMatches(typedKeyList->keys[1], 1, 2, 1, "\x02\x03", 2),
527        " ... with the right key in slot 1");
528     afsconf_PutTypedKeyList(&typedKeyList);
529
530 out:
531     unlinkTestConfig(dirname);
532
533     return 0;
534 }