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