2 * Copyright (c) 2010 Your File System Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
24 #include <afsconfig.h>
25 #include <afs/param.h>
29 #ifdef HAVE_SYS_WAIT_H
33 #ifdef IGNORE_SOME_GCC_WARNINGS
34 # pragma GCC diagnostic warning "-Wdeprecated-declarations"
37 #include <afs/cellconfig.h>
38 #include <afs/afsutil.h>
39 #include <afs/com_err.h>
42 #include <rx/rx_identity.h>
44 #include <tap/basic.h>
48 #define TEST_PORT 1234
51 testOriginalIterator(struct afsconf_dir *dir, int num, char *user) {
54 ok((afsconf_GetNthUser(dir, num, buffer, sizeof buffer) == 0),
55 "User %d successfully returned as %s", num, buffer);
57 ok(strcmp(user, buffer) == 0,
58 "User %d matches", num);
62 testNewIterator(struct afsconf_dir *dir, int num, struct rx_identity *id) {
63 struct rx_identity *fileId;
65 ok((afsconf_GetNthIdentity(dir, num, &fileId) == 0),
66 "Identity %d successfully returned", num);
68 ok(rx_identity_match(fileId, id), "Identity %d matches", num);
70 rx_identity_free(&fileId);
73 struct rx_securityClass *
74 fakeRXKADClass(struct afsconf_dir *dir,
75 char *name, char *instance, char *realm,
76 afs_uint32 startTime, afs_uint32 endTime)
80 struct ktc_encryptionKey key, session;
83 struct rx_securityClass *class = NULL;
85 code = afsconf_GetLatestKey(dir, &kvno, &key);
89 DES_init_random_number_generator((DES_cblock *) &key);
90 code = DES_new_random_key((DES_cblock *) &session);
94 ticketLen = sizeof(buffer);
95 memset(buffer, 0, sizeof(buffer));
96 startTime = time(NULL);
97 endTime = startTime + 60 * 60;
99 code = tkt_MakeTicket(buffer, &ticketLen, &key, name, instance, realm,
100 startTime, endTime, &session, 0, "afs", "");
104 class = rxkad_NewClientSecurityObject(rxkad_clear, &session, kvno,
112 startClient(char *configPath)
114 struct afsconf_dir *dir;
115 struct rx_identity *testId, *anotherId, *extendedId, *dummy;
116 struct rx_securityClass *class;
117 struct rx_connection *conn;
118 afs_uint32 startTime;
120 afs_int32 classIndex;
129 dir = afsconf_Open(configPath);
131 "Configuration directory opened sucessfully by client");
133 /* Add a normal user to the super user file */
134 ok(afsconf_AddUser(dir, "test") == 0,
135 "Adding a simple user works");
137 testId = rx_identity_new(RX_ID_KRB4, "test", "test", strlen("test"));
139 /* Check that they are a super user */
140 ok(afsconf_IsSuperIdentity(dir, testId),
141 "User added with old i/face is identitifed as super user");
143 /* Check that nobody else is */
144 ok(!afsconf_IsSuperIdentity(dir,
145 rx_identity_new(RX_ID_KRB4, "testy",
146 "testy", strlen("testy"))),
147 "Additional users are not super users");
149 ok(afsconf_AddUser(dir, "test") == EEXIST,
150 "Adding a user that already exists fails");
152 ok(afsconf_AddIdentity(dir, testId) == EEXIST,
153 "Adding an identity that already exists fails");
155 anotherId = rx_identity_new(RX_ID_KRB4, "another",
156 "another", strlen("another"));
158 /* Add another normal user, but using the extended interface */
159 ok(afsconf_AddIdentity(dir, anotherId) == 0,
160 "Adding a KRB4 identity works");
162 /* Check that they are a super user */
163 ok(afsconf_IsSuperIdentity(dir, anotherId),
164 "User added with new i/face is identitifed as super user");
166 ok(afsconf_AddIdentity(dir, anotherId) == EEXIST,
167 "Adding a KRB4 identity that already exists fails");
169 /* Add an extended user to the super user file */
170 extendedId = rx_identity_new(RX_ID_GSS, "sxw@INF.ED.AC.UK",
171 "\x04\x01\x00\x0B\x06\x09\x2A\x86\x48\x86\xF7\x12\x01\x02\x02\x00\x00\x00\x10sxw@INF.ED.AC.UK", 35);
173 ok(afsconf_AddIdentity(dir, extendedId) == 0,
174 "Adding a GSSAPI identity works");
176 /* Check that they are now special */
177 ok(afsconf_IsSuperIdentity(dir, extendedId),
178 "Added GSSAPI identity is a super user");
180 /* Check that display name isn't used for matches */
181 ok(!afsconf_IsSuperIdentity(dir,
182 rx_identity_new(RX_ID_GSS, "sxw@INF.ED.AC.UK",
183 "abcdefghijklmnopqrstuvwxyz123456789", 35)),
184 "Display name is not used for extended matches");
186 ok(afsconf_AddIdentity(dir, extendedId) == EEXIST,
187 "Adding GSSAPI identity twice fails");
189 /* Add a final normal user, so we can check that iteration works */
190 /* Add a normal user to the super user file */
191 ok(afsconf_AddUser(dir, "test2") == 0,
192 "Adding another simple user works");
194 testOriginalIterator(dir, 0, "test");
195 testOriginalIterator(dir, 1, "another");
196 testOriginalIterator(dir, 2, "test2");
197 ok(afsconf_GetNthUser(dir, 3, ubuffer, sizeof ubuffer) != 0,
198 "Reading past the end of the superuser list fails");
200 testNewIterator(dir, 0, testId);
201 testNewIterator(dir, 1, anotherId);
202 testNewIterator(dir, 2, extendedId);
203 testNewIterator(dir, 3, rx_identity_new(RX_ID_KRB4, "test2",
204 "test2", strlen("test2")));
205 ok(afsconf_GetNthIdentity(dir, 4, &dummy) != 0,
206 "Reading past the end of the superuser list fails");
208 ok(afsconf_DeleteUser(dir, "notthere") != 0,
209 "Deleting a user that doesn't exist fails");
211 /* Delete the normal user */
212 ok(afsconf_DeleteUser(dir, "another") == 0,
213 "Deleting normal user works");
215 ok(!afsconf_IsSuperIdentity(dir, anotherId),
216 "Deleted user is no longer super user");
218 ok(afsconf_IsSuperIdentity(dir, testId) &&
219 afsconf_IsSuperIdentity(dir, extendedId),
220 "Other identities still are");
222 ok(afsconf_DeleteIdentity(dir, extendedId) == 0,
223 "Deleting identity works");
225 ok(!afsconf_IsSuperIdentity(dir, extendedId),
226 "Deleted identity is no longer special");
228 /* Now, what happens if we're doing something over the network instead */
231 is_int(code, 0, "Initialised RX");
233 /* Fake up an rx ticket. Note that this will be for the magic 'superuser' */
234 code = afsconf_ClientAuth(dir, &class, &classIndex);
235 is_int(code, 0, "Can successfully create superuser token");
237 /* Start a connection to our test service with it */
238 he = gethostbyname("localhost");
240 printf("Couldn't look up server hostname");
244 memcpy(&addr, he->h_addr, sizeof(afs_uint32));
246 conn = rx_NewConnection(addr, htons(TEST_PORT), TEST_SERVICE_ID,
249 /* There's nothing in the list, so this just succeeds because we can */
250 code = TEST_CanI(conn, &result);
251 is_int(0, code, "Can run a simple RPC");
253 code = TEST_WhoAmI(conn, &string);
254 is_int(0, code, "Can get identity back");
255 is_string("<LocalAuth>", string, "Forged token is super user");
257 /* Throw away this connection and security class */
258 rx_DestroyConnection(conn);
261 /* Now fake an rx ticket for a normal user. We have to do more work by hand
264 startTime = time(NULL);
265 class = fakeRXKADClass(dir, "rpctest", "", "", startTime, startTime + 60* 60);
267 conn = rx_NewConnection(addr, htons(TEST_PORT), TEST_SERVICE_ID, class,
270 code = TEST_CanI(conn, &result);
272 "Running RPC as non-super user fails as expected");
273 code = TEST_NewCanI(conn, &result);
275 "Running new interface RPC as non-super user fails as expected");
276 code = TEST_WhoAmI(conn, &string);
278 "Running RPC returning string fails as expected");
279 code = TEST_NewWhoAmI(conn, &string);
281 "Running new interface RPC returning string fails as expected");
282 ok(afsconf_AddUser(dir, "rpctest") == 0,
283 "Adding %s user works", "rpctest");
284 code = TEST_CanI(conn, &result);
285 is_int(0, code, "Running RPC as rpctest works");
286 code = TEST_NewCanI(conn, &result);
287 is_int(0, code, "Running new interface RPC as rpctest works");
288 code = TEST_WhoAmI(conn, &string);
289 is_int(0, code, "Running RPC returning string as %s works", "rpctest");
290 is_string("rpctest", string, "Returned user string matches");
291 code = TEST_NewWhoAmI(conn, &string);
292 is_int(0, code, "Running new RPC returning string as %s works", "rpctest");
293 is_string("rpctest", string, "Returned user string for new interface matches");
294 rx_DestroyConnection(conn);
297 /* Now try with an admin principal */
298 startTime = time(NULL);
299 class = fakeRXKADClass(dir, "rpctest", "admin", "", startTime,
302 conn = rx_NewConnection(addr, htons(TEST_PORT), TEST_SERVICE_ID, class,
305 code = TEST_CanI(conn, &result);
307 "Running RPC as non-super user fails as expected");
308 code = TEST_NewCanI(conn, &result);
310 "Running new interface RPC as non-super user fails as expected");
311 code = TEST_WhoAmI(conn, &string);
313 "Running RPC returning string fails as expected");
314 code = TEST_NewWhoAmI(conn, &string);
316 "Running new interface RPC returning string fails as expected");
318 ok(afsconf_AddUser(dir, "rpctest.admin") == 0,
319 "Adding %s user works", "rpctest.admin");
321 code = TEST_CanI(conn, &result);
322 is_int(0, code, "Running RPC as %s works", "rpctest/admin");
323 code = TEST_NewCanI(conn, &result);
324 is_int(0, code, "Running new interface RPC as %s works", "rpctest/admin");
325 code = TEST_WhoAmI(conn, &string);
326 is_int(0, code, "Running RPC returning string as %s works", "rpctest/admin");
327 is_string("rpctest.admin", string, "Returned user string matches");
328 code = TEST_NewWhoAmI(conn, &string);
329 is_int(0, code, "Running new interface RPC returning string as %s works",
331 is_string("rpctest.admin", string,
332 "Returned user string from new interface matches");
334 rx_DestroyConnection(conn);
338 /**********************************************************************
340 **********************************************************************/
342 struct afsconf_dir *globalDir;
345 STEST_CanI(struct rx_call *call, afs_int32 *result)
348 if (!afsconf_SuperUser(globalDir, call, NULL)) {
355 STEST_NewCanI(struct rx_call *call, afs_int32 *result)
358 if (!afsconf_SuperIdentity(globalDir, call, NULL)) {
365 STEST_WhoAmI(struct rx_call *call, char **result)
367 char string[MAXKTCNAMELEN];
369 if (!afsconf_SuperUser(globalDir, call, string)) {
370 *result = strdup("");
373 *result = strdup(string);
379 STEST_NewWhoAmI(struct rx_call *call, char **result)
381 struct rx_identity *id;
383 if (!afsconf_SuperIdentity(globalDir, call, &id)) {
384 *result = strdup("");
387 *result = strdup(id->displayName);
393 startServer(char *configPath)
395 struct rx_securityClass **classes;
396 afs_int32 numClasses;
398 struct rx_service *service;
400 globalDir = afsconf_Open(configPath);
401 if (globalDir == NULL) {
402 fprintf(stderr, "Server: Unable to open config directory\n");
406 code = rx_Init(htons(TEST_PORT));
408 fprintf(stderr, "Server: Unable to initialise RX\n");
412 afsconf_BuildServerSecurityObjects(globalDir, 0, &classes, &numClasses);
413 service = rx_NewService(0, TEST_SERVICE_ID, "test", classes, numClasses,
414 TEST_ExecuteRequest);
415 if (service == NULL) {
416 fprintf(stderr, "Server: Unable to start to test service\n");
423 int main(int argc, char **argv)
425 struct afsconf_dir *dir;
427 int serverPid, clientPid, waited, stat;
428 char keymaterial[]="\x19\x17\xff\xe6\xbb\x77\x2e\xfc";
433 /* Start the client and the server if requested */
436 if (strcmp(argv[1], "-server") == 0) {
437 startServer(argv[2]);
439 } else if (strcmp(argv[1], "-client") == 0) {
440 startClient(argv[2]);
443 printf("Bad option %s\n", argv[1]);
448 /* Otherwise, do the basic configuration, then start the client and
451 snprintf(buffer, sizeof(buffer), "%s/afs_XXXXXX", gettmpdir());
453 dirEnd = buffer + strlen(buffer);
455 /* Create a CellServDB file */
456 strcpy(dirEnd, "/CellServDB");
457 file = fopen(buffer, "w");
458 fprintf(file, ">example.org # An example cell\n");
459 fprintf(file, "127.0.0.1 #test.example.org\n");
462 /* Create a ThisCell file */
463 strcpy(dirEnd, "/ThisCell");
464 file = fopen(buffer, "w");
465 fprintf(file, "example.org\n");
469 /* Start with a blank configuration directory */
470 dir = afsconf_Open(strdup(buffer));
472 fprintf(stderr, "Unable to configure directory.\n");
476 DES_set_odd_parity((DES_cblock *)keymaterial);
478 /* Add a key to it so we can use it for connection tests */
479 code = afsconf_AddKey(dir, 1, keymaterial, 1);
481 afs_com_err("superuser-t", code, "while adding new key\n");
485 printf("Config directory is %s\n", buffer);
487 if (serverPid == -1) {
489 } else if (serverPid == 0) {
490 execl(argv[0], argv[0], "-server", buffer, NULL);
494 if (clientPid == -1) {
495 kill(serverPid, SIGTERM);
496 waitpid(serverPid, &stat, 0);
498 } else if (clientPid == 0) {
499 execl(argv[0], argv[0], "-client", buffer, NULL);
503 waited = waitpid(0, &stat, 0);
504 } while(waited == -1 && errno == EINTR);
506 if (waited == serverPid) {
507 kill(clientPid, SIGTERM);
508 } else if (waited == clientPid) {
509 kill(serverPid, SIGTERM);
511 waitpid(0, &stat, 0);
513 /* Client and server are both done, so cleanup after everything */
515 strcpy(dirEnd, "/KeyFile");
517 strcpy(dirEnd, "/CellServDB");
519 strcpy(dirEnd, "/ThisCell");
521 strcpy(dirEnd, "/UserList");