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