7ca0af54b245d902df0c6715dd788cb2cb6d9896
[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 static int
40 copy(char *inFile, char *outFile)
41 {
42     int in, out;
43     int code, written;
44     char *block;
45     size_t len;
46
47     in = open(inFile, O_RDONLY);
48     if (in<0)
49         return EIO;
50
51     out = open(outFile, O_WRONLY | O_CREAT, 0600);
52     if (out<0)
53         return EIO;
54
55     block = malloc(1024);
56     do {
57         len = read(in, block, 1024);
58         if (len > 0)
59             write(out, block, len);
60     } while (len > 0);
61     free(block);
62
63     close(in);
64     close(out);
65
66     if (len == -1)
67         return EIO;
68
69     return 0;
70 }
71
72 int main(int argc, char **argv)
73 {
74     struct afsconf_dir *dir;
75     struct afsconf_keys keys;
76     struct ktc_encryptionKey key;
77     char buffer[1024];
78     char *dirEnd;
79     FILE *file;
80     afs_int32 kvno;
81     int code;
82     int i;
83
84     plan(61);
85
86     /* Create a temporary afs configuration directory */
87     snprintf(buffer, sizeof(buffer), "%s/afs_XXXXXX", gettmpdir());
88     mkdtemp(buffer);
89     dirEnd = buffer + strlen(buffer);
90
91     /* Create a CellServDB file */
92     strcpy(dirEnd, "/CellServDB");
93     file = fopen(buffer, "w");
94     fprintf(file, ">example.org # An example cell\n");
95     fprintf(file, "127.0.0.1 #test.example.org\n");
96     fclose(file);
97
98     /* Create a ThisCell file */
99     strcpy(dirEnd, "/ThisCell");
100     file = fopen(buffer, "w");
101     fprintf(file, "example.org\n");
102     fclose(file);
103
104     /* Firstly, copy in a known keyfile. */
105     strcpy(dirEnd, "/KeyFile");
106     code = copy("KeyFile", buffer);
107     if (code)
108         goto out;
109
110     *dirEnd='\0';
111
112     /* Start with a blank configuration directory */
113     dir = afsconf_Open(strdup(buffer));
114     ok(dir != NULL, "Sucessfully re-opened config directory");
115     if (dir == NULL)
116         goto out;
117
118     /* Verify that GetKeys returns the entire set of keys correctly */
119     code = afsconf_GetKeys(dir, &keys);
120     is_int(0, code, "afsconf_GetKeys returns successfully");
121     is_int(3, keys.nkeys, "... and returns the right number of keys");
122     is_int(1, keys.key[0].kvno, " ... first key number is correct");
123     is_int(2, keys.key[1].kvno, " ... second key number is correct");
124     is_int(4, keys.key[2].kvno, " ... third key number is correct");
125     ok(memcmp(keys.key[0].key, "\x01\x02\x04\x08\x10\x20\x40\x80", 8) == 0,
126        " ... first key matches");
127     ok(memcmp(keys.key[1].key, "\x04\x04\x04\x04\x04\x04\x04\x04", 8) == 0,
128        " ... second key matches");
129     ok(memcmp(keys.key[2].key, "\x19\x16\xfe\xe6\xba\x77\x2f\xfd", 8) == 0,
130        " ... third key matches");
131
132     /* Verify that GetLatestKey returns the newest key */
133     code = afsconf_GetLatestKey(dir, &kvno, &key);
134     is_int(0, code, "afsconf_GetLatestKey returns sucessfully");
135     is_int(4, kvno, " ... with correct key number");
136     ok(memcmp(&key, "\x19\x16\xfe\xe6\xba\x77\x2f\xfd", 8) == 0,
137        " ... and correct key");
138
139     /* Verify that random access using GetKey works properly */
140     code = afsconf_GetKey(dir, 2, &key);
141     is_int(0, code, "afsconf_GetKey returns successfully");
142     ok(memcmp(&key, "\x04\x04\x04\x04\x04\x04\x04\x04", 8) == 0,
143        " ... and with correct key");
144
145     /* And that it fails if the key number doesn't exist */
146     code = afsconf_GetKey(dir, 3, &key);
147     is_int(code, AFSCONF_NOTFOUND,
148            "afsconf_GetKey returns not found for missing key");
149
150     /* Check that AddKey can be used to add a new 'newest' key */
151     code = afsconf_AddKey(dir, 5, "\x08\x08\x08\x08\x08\x08\x08\x08", 0);
152     is_int(0, code, "afsconf_AddKey sucessfully adds a new key");
153
154     /* And that we can get it back with GetKeys, GetLatestKey and GetKey */
155     code = afsconf_GetKeys(dir, &keys);
156     is_int(0, code, " ... and GetKeys still works");
157     is_int(4, keys.nkeys, "... and has the correct number of keys");
158     is_int(5, keys.key[3].kvno, " ... and the fourth key has the correct kvno");
159     ok(memcmp(keys.key[3].key, "\x08\x08\x08\x08\x08\x08\x08\x08", 8) == 0,
160        " ... and is the correct key");
161
162     code = afsconf_GetLatestKey(dir, &kvno, &key);
163     is_int(0, code, " ... and GetLatestKey returns successfully");
164     is_int(5, kvno, " ... with the correct key number");
165     ok(memcmp(&key, "\x08\x08\x08\x08\x08\x08\x08\x08", 8) == 0,
166        " ... and the correct key");
167
168     code = afsconf_GetKey(dir, 5, &key);
169     is_int(0, code, " ... and GetKey still works");
170     ok(memcmp(&key, "\x08\x08\x08\x08\x08\x08\x08\x08", 8) == 0,
171        " ... and returns the correct key");
172
173     /* Check that AddKey without the overwrite flag won't overwrite an existing
174      * key */
175     code = afsconf_AddKey(dir, 5, "\x10\x10\x10\x10\x10\x10\x10", 0);
176     is_int(AFSCONF_KEYINUSE, code, "AddKey won't overwrite without being told to");
177
178     /* Check with GetKey that it didn't */
179     code = afsconf_GetKey(dir, 5, &key);
180     is_int(0, code, " ... and GetKey still works");
181     ok(memcmp(&key, "\x08\x08\x08\x08\x08\x08\x08\x08", 8) == 0,
182        " ... and key hasn't been overwritten");
183
184     /* Check that AddKey with the overwrite flag will overwrite an existing key */
185     code = afsconf_AddKey(dir, 5, "\x10\x10\x10\x10\x10\x10\x10\x10", 1);
186     is_int(0, code, "AddKey overwrites when asked");
187
188     /* Use GetKey to check that it did so */
189     code = afsconf_GetKey(dir, 5, &key);
190     is_int(0, code, " ... and GetKey still works");
191     ok(memcmp(&key, "\x10\x10\x10\x10\x10\x10\x10\x10", 8) == 0,
192        " ... and key has been overwritten");
193
194     /* Check that deleting a key that doesn't exist fails */
195     code = afsconf_DeleteKey(dir, 6);
196     is_int(AFSCONF_NOTFOUND, code,
197            "afsconf_DeleteKey returns NOTFOUND if key doesn't exist");
198
199     /* Check that we can delete a key using afsconf_DeleteKey */
200     code = afsconf_DeleteKey(dir, 2);
201     is_int(0, code, "afsconf_DeleteKey can delete a key");
202     code = afsconf_GetKey(dir, 2, &key);
203     is_int(AFSCONF_NOTFOUND, code, " ... and afsconf_GetKey can't find it");
204
205     /* Check that deleting it doesn't leave a hole in what GetKeys returns */
206     code = afsconf_GetKeys(dir, &keys);
207     is_int(0, code, "... and afsconf_GetKeys returns it");
208     is_int(3, keys.nkeys, "... and returns the right number of keys");
209     is_int(1, keys.key[0].kvno, " ... first key number is correct");
210     is_int(4, keys.key[1].kvno, " ... second key number is correct");
211     is_int(5, keys.key[2].kvno, " ... third key number is correct");
212
213     /* Make sure that if we drop the dir structure, and then rebuild it, we
214      * still have the same KeyFile */
215     afsconf_Close(dir);
216
217     *dirEnd='\0';
218     dir = afsconf_Open(strdup(buffer));
219     ok(dir != NULL, "Sucessfully re-opened config directory");
220     if (dir == NULL)
221         goto out;
222
223     code = afsconf_GetKeys(dir, &keys);
224     is_int(0, code, "afsconf_GetKeys still works");
225     is_int(3, keys.nkeys, "... and returns the right number of keys");
226     is_int(1, keys.key[0].kvno, " ... first key number is correct");
227     is_int(4, keys.key[1].kvno, " ... second key number is correct");
228     is_int(5, keys.key[2].kvno, " ... third key number is correct");
229
230     /* Now check that we're limited to 8 keys */
231     for (i=0; i<5; i++) {
232         code = afsconf_AddKey(dir, 10+i, "\x10\x10\x10\x10\x10\x10\x10\x10",
233                               0);
234         is_int(0, code, "Adding %dth key with AddKey works", i+4);
235     }
236     code = afsconf_AddKey(dir, 20, "\x10\x10\x10\x10\x10\x10\x10\x10",0);
237     is_int(AFSCONF_FULL, code, "afsconf_AddKey fails once we've got 8 keys");
238
239     /* Unlink the KeyFile */
240     strcpy(dirEnd, "/KeyFile");
241     unlink(buffer);
242
243     /* Force a rebuild of the directory structure, just in case */
244     afsconf_Close(dir);
245
246     *dirEnd='\0';
247     dir = afsconf_Open(strdup(buffer));
248     ok(dir != NULL, "Sucessfully re-opened config directory");
249     if (dir == NULL)
250         goto out;
251
252     /* Check that all of the various functions work properly if the file
253      * isn't there */
254     code = afsconf_GetKeys(dir, &keys);
255     is_int(0, code, "afsconf_GetKeys works with an empty KeyFile");
256     is_int(0, keys.nkeys, " ... and returns the right number of keys");
257     code = afsconf_GetKey(dir, 1, &key);
258     is_int(AFSCONF_NOTFOUND, code,
259            "afsconf_GetKey returns NOTFOUND with an empty KeyFile");
260     code = afsconf_DeleteKey(dir, 1);
261     is_int(AFSCONF_NOTFOUND, code,
262            "afsconf_DeleteKey returns NOTFOUND with an empty KeyFile");
263     code = afsconf_GetLatestKey(dir, &kvno, &key);
264     is_int(AFSCONF_NOTFOUND, code,
265            "afsconf_GetLatestKey returns NOTFOUND with an empty KeyFile");
266
267     /* Now try adding a key to an empty file */
268     code = afsconf_AddKey(dir, 1, "\x10\x10\x10\x10\x10\x10\x10\x10", 1);
269     is_int(0, code, "afsconf_AddKey succeeds with an empty KeyFile");
270     code = afsconf_GetLatestKey(dir, &kvno, &key);
271     is_int(0, code, " ... and afsconf_GetLatestKey succeeds");
272     is_int(1, kvno, " ... with correct kvno");
273     ok(memcmp(&key, "\x10\x10\x10\x10\x10\x10\x10\x10", 8) == 0,
274        " ... and key");
275
276 out:
277     strcpy(dirEnd, "/KeyFile");
278     unlink(buffer);
279     strcpy(dirEnd, "/CellServDB");
280     unlink(buffer);
281     strcpy(dirEnd, "/ThisCell");
282     unlink(buffer);
283     strcpy(dirEnd, "/UserList");
284     unlink(buffer);
285     *dirEnd='\0';
286     rmdir(buffer);
287 }