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 <hcrypto/des.h>
45 #include <rx/rx_identity.h>
47 #include <tap/basic.h>
52 #define TEST_PORT 1234
55 testOriginalIterator(struct afsconf_dir *dir, int num, char *user) {
58 ok((afsconf_GetNthUser(dir, num, buffer, sizeof buffer) == 0),
59 "User %d successfully returned as %s", num, buffer);
61 ok(strcmp(user, buffer) == 0,
62 "User %d matches", num);
66 testNewIterator(struct afsconf_dir *dir, int num, struct rx_identity *id) {
67 struct rx_identity *fileId;
69 ok((afsconf_GetNthIdentity(dir, num, &fileId) == 0),
70 "Identity %d successfully returned", num);
72 ok(rx_identity_match(fileId, id), "Identity %d matches", num);
74 rx_identity_free(&fileId);
77 struct rx_securityClass *
78 fakeRXKADClass(struct afsconf_dir *dir,
79 char *name, char *instance, char *realm,
80 afs_uint32 startTime, afs_uint32 endTime)
84 struct ktc_encryptionKey key, session;
87 struct rx_securityClass *class = NULL;
89 code = afsconf_GetLatestKey(dir, &kvno, &key);
93 DES_init_random_number_generator((DES_cblock *) &key);
94 code = DES_new_random_key((DES_cblock *) &session);
98 ticketLen = sizeof(buffer);
99 memset(buffer, 0, sizeof(buffer));
100 startTime = time(NULL);
101 endTime = startTime + 60 * 60;
103 code = tkt_MakeTicket(buffer, &ticketLen, &key, name, instance, realm,
104 startTime, endTime, &session, 0, "afs", "");
108 class = rxkad_NewClientSecurityObject(rxkad_clear, &session, kvno,
116 startClient(char *configPath)
118 struct afsconf_dir *dir;
119 struct rx_identity *testId, *anotherId, *extendedId, *dummy;
120 struct rx_securityClass *class;
121 struct rx_connection *conn;
122 afs_uint32 startTime;
124 afs_int32 classIndex;
133 dir = afsconf_Open(configPath);
135 "Configuration directory opened sucessfully by client");
137 /* Add a normal user to the super user file */
138 ok(afsconf_AddUser(dir, "test") == 0,
139 "Adding a simple user works");
141 testId = rx_identity_new(RX_ID_KRB4, "test", "test", strlen("test"));
143 /* Check that they are a super user */
144 ok(afsconf_IsSuperIdentity(dir, testId),
145 "User added with old i/face is identitifed as super user");
147 /* Check that nobody else is */
148 ok(!afsconf_IsSuperIdentity(dir,
149 rx_identity_new(RX_ID_KRB4, "testy",
150 "testy", strlen("testy"))),
151 "Additional users are not super users");
153 ok(afsconf_AddUser(dir, "test") == EEXIST,
154 "Adding a user that already exists fails");
156 ok(afsconf_AddIdentity(dir, testId) == EEXIST,
157 "Adding an identity that already exists fails");
159 anotherId = rx_identity_new(RX_ID_KRB4, "another",
160 "another", strlen("another"));
162 /* Add another normal user, but using the extended interface */
163 ok(afsconf_AddIdentity(dir, anotherId) == 0,
164 "Adding a KRB4 identity works");
166 /* Check that they are a super user */
167 ok(afsconf_IsSuperIdentity(dir, anotherId),
168 "User added with new i/face is identitifed as super user");
170 ok(afsconf_AddIdentity(dir, anotherId) == EEXIST,
171 "Adding a KRB4 identity that already exists fails");
173 /* Add an extended user to the super user file */
174 extendedId = rx_identity_new(RX_ID_GSS, "sxw@INF.ED.AC.UK",
175 "\x04\x01\x00\x0B\x06\x09\x2A\x86\x48\x86\xF7\x12\x01\x02\x02\x00\x00\x00\x10sxw@INF.ED.AC.UK", 35);
177 ok(afsconf_AddIdentity(dir, extendedId) == 0,
178 "Adding a GSSAPI identity works");
180 /* Check that they are now special */
181 ok(afsconf_IsSuperIdentity(dir, extendedId),
182 "Added GSSAPI identity is a super user");
184 /* Check that display name isn't used for matches */
185 ok(!afsconf_IsSuperIdentity(dir,
186 rx_identity_new(RX_ID_GSS, "sxw@INF.ED.AC.UK",
187 "abcdefghijklmnopqrstuvwxyz123456789", 35)),
188 "Display name is not used for extended matches");
190 ok(afsconf_AddIdentity(dir, extendedId) == EEXIST,
191 "Adding GSSAPI identity twice fails");
193 /* Add a final normal user, so we can check that iteration works */
194 /* Add a normal user to the super user file */
195 ok(afsconf_AddUser(dir, "test2") == 0,
196 "Adding another simple user works");
198 testOriginalIterator(dir, 0, "test");
199 testOriginalIterator(dir, 1, "another");
200 testOriginalIterator(dir, 2, "test2");
201 ok(afsconf_GetNthUser(dir, 3, ubuffer, sizeof ubuffer) != 0,
202 "Reading past the end of the superuser list fails");
204 testNewIterator(dir, 0, testId);
205 testNewIterator(dir, 1, anotherId);
206 testNewIterator(dir, 2, extendedId);
207 testNewIterator(dir, 3, rx_identity_new(RX_ID_KRB4, "test2",
208 "test2", strlen("test2")));
209 ok(afsconf_GetNthIdentity(dir, 4, &dummy) != 0,
210 "Reading past the end of the superuser list fails");
212 ok(afsconf_DeleteUser(dir, "notthere") != 0,
213 "Deleting a user that doesn't exist fails");
215 /* Delete the normal user */
216 ok(afsconf_DeleteUser(dir, "another") == 0,
217 "Deleting normal user works");
219 ok(!afsconf_IsSuperIdentity(dir, anotherId),
220 "Deleted user is no longer super user");
222 ok(afsconf_IsSuperIdentity(dir, testId) &&
223 afsconf_IsSuperIdentity(dir, extendedId),
224 "Other identities still are");
226 ok(afsconf_DeleteIdentity(dir, extendedId) == 0,
227 "Deleting identity works");
229 ok(!afsconf_IsSuperIdentity(dir, extendedId),
230 "Deleted identity is no longer special");
232 /* Now, what happens if we're doing something over the network instead */
235 is_int(code, 0, "Initialised RX");
237 /* Fake up an rx ticket. Note that this will be for the magic 'superuser' */
238 code = afsconf_ClientAuth(dir, &class, &classIndex);
239 is_int(code, 0, "Can successfully create superuser token");
241 /* Start a connection to our test service with it */
242 he = gethostbyname("localhost");
244 printf("Couldn't look up server hostname");
248 memcpy(&addr, he->h_addr, sizeof(afs_uint32));
250 conn = rx_NewConnection(addr, htons(TEST_PORT), TEST_SERVICE_ID,
253 /* There's nothing in the list, so this just succeeds because we can */
254 code = TEST_CanI(conn, &result);
255 is_int(0, code, "Can run a simple RPC");
257 code = TEST_WhoAmI(conn, &string);
258 is_int(0, code, "Can get identity back");
259 is_string("<LocalAuth>", string, "Forged token is super user");
261 xdr_free((xdrproc_t)xdr_string, &string);
263 /* Throw away this connection and security class */
264 rx_DestroyConnection(conn);
267 /* Now fake an rx ticket for a normal user. We have to do more work by hand
270 startTime = time(NULL);
271 class = fakeRXKADClass(dir, "rpctest", "", "", startTime, startTime + 60* 60);
273 conn = rx_NewConnection(addr, htons(TEST_PORT), TEST_SERVICE_ID, class,
276 code = TEST_CanI(conn, &result);
278 "Running RPC as non-super user fails as expected");
279 code = TEST_NewCanI(conn, &result);
281 "Running new interface RPC as non-super user fails as expected");
282 code = TEST_WhoAmI(conn, &string);
283 xdr_free((xdrproc_t)xdr_string, &string);
285 "Running RPC returning string fails as expected");
286 code = TEST_NewWhoAmI(conn, &string);
287 xdr_free((xdrproc_t)xdr_string, &string);
289 "Running new interface RPC returning string fails as expected");
290 ok(afsconf_AddUser(dir, "rpctest") == 0,
291 "Adding %s user works", "rpctest");
292 code = TEST_CanI(conn, &result);
293 is_int(0, code, "Running RPC as rpctest works");
294 code = TEST_NewCanI(conn, &result);
295 is_int(0, code, "Running new interface RPC as rpctest works");
296 code = TEST_WhoAmI(conn, &string);
297 is_int(0, code, "Running RPC returning string as %s works", "rpctest");
298 is_string("rpctest", string, "Returned user string matches");
299 xdr_free((xdrproc_t)xdr_string, &string);
300 code = TEST_NewWhoAmI(conn, &string);
301 is_int(0, code, "Running new RPC returning string as %s works", "rpctest");
302 is_string("rpctest", string, "Returned user string for new interface matches");
303 xdr_free((xdrproc_t)xdr_string, &string);
304 rx_DestroyConnection(conn);
307 /* Now try with an admin principal */
308 startTime = time(NULL);
309 class = fakeRXKADClass(dir, "rpctest", "admin", "", startTime,
312 conn = rx_NewConnection(addr, htons(TEST_PORT), TEST_SERVICE_ID, class,
315 code = TEST_CanI(conn, &result);
317 "Running RPC as non-super user fails as expected");
318 code = TEST_NewCanI(conn, &result);
320 "Running new interface RPC as non-super user fails as expected");
321 code = TEST_WhoAmI(conn, &string);
322 xdr_free((xdrproc_t)xdr_string, &string);
324 "Running RPC returning string fails as expected");
325 code = TEST_NewWhoAmI(conn, &string);
326 xdr_free((xdrproc_t)xdr_string, &string);
328 "Running new interface RPC returning string fails as expected");
330 ok(afsconf_AddUser(dir, "rpctest.admin") == 0,
331 "Adding %s user works", "rpctest.admin");
333 code = TEST_CanI(conn, &result);
334 is_int(0, code, "Running RPC as %s works", "rpctest/admin");
335 code = TEST_NewCanI(conn, &result);
336 is_int(0, code, "Running new interface RPC as %s works", "rpctest/admin");
337 code = TEST_WhoAmI(conn, &string);
338 is_int(0, code, "Running RPC returning string as %s works", "rpctest/admin");
339 is_string("rpctest.admin", string, "Returned user string matches");
340 xdr_free((xdrproc_t)xdr_string, &string);
341 code = TEST_NewWhoAmI(conn, &string);
342 is_int(0, code, "Running new interface RPC returning string as %s works",
344 is_string("rpctest.admin", string,
345 "Returned user string from new interface matches");
346 xdr_free((xdrproc_t)xdr_string, &string);
348 rx_DestroyConnection(conn);
352 /**********************************************************************
354 **********************************************************************/
356 struct afsconf_dir *globalDir;
359 STEST_CanI(struct rx_call *call, afs_int32 *result)
362 if (!afsconf_SuperUser(globalDir, call, NULL)) {
369 STEST_NewCanI(struct rx_call *call, afs_int32 *result)
372 if (!afsconf_SuperIdentity(globalDir, call, NULL)) {
379 STEST_WhoAmI(struct rx_call *call, char **result)
381 char string[MAXKTCNAMELEN];
383 if (!afsconf_SuperUser(globalDir, call, string)) {
384 *result = strdup("");
387 *result = strdup(string);
393 STEST_NewWhoAmI(struct rx_call *call, char **result)
395 struct rx_identity *id;
397 if (!afsconf_SuperIdentity(globalDir, call, &id)) {
398 *result = strdup("");
401 *result = strdup(id->displayName);
407 startServer(char *configPath)
409 struct rx_securityClass **classes;
410 afs_int32 numClasses;
412 struct rx_service *service;
414 globalDir = afsconf_Open(configPath);
415 if (globalDir == NULL) {
416 fprintf(stderr, "Server: Unable to open config directory\n");
420 code = rx_Init(htons(TEST_PORT));
422 fprintf(stderr, "Server: Unable to initialise RX\n");
426 afsconf_BuildServerSecurityObjects(globalDir, &classes, &numClasses);
427 service = rx_NewService(0, TEST_SERVICE_ID, "test", classes, numClasses,
428 TEST_ExecuteRequest);
429 if (service == NULL) {
430 fprintf(stderr, "Server: Unable to start to test service\n");
437 int main(int argc, char **argv)
439 struct afsconf_dir *dir;
441 int serverPid, clientPid, waited, stat;
444 /* Start the client and the server if requested */
447 if (strcmp(argv[1], "-server") == 0) {
448 startServer(argv[2]);
450 } else if (strcmp(argv[1], "-client") == 0) {
451 startClient(argv[2]);
454 printf("Bad option %s\n", argv[1]);
459 /* Otherwise, do the basic configuration, then start the client and
462 dirname = afstest_BuildTestConfig();
464 dir = afsconf_Open(dirname);
466 fprintf(stderr, "Unable to configure directory.\n");
470 code = afstest_AddDESKeyFile(dir);
472 afs_com_err("superuser-t", code, "while adding new key\n");
476 printf("Config directory is %s\n", dirname);
478 if (serverPid == -1) {
480 } else if (serverPid == 0) {
481 execl(argv[0], argv[0], "-server", dirname, NULL);
485 if (clientPid == -1) {
486 kill(serverPid, SIGTERM);
487 waitpid(serverPid, &stat, 0);
489 } else if (clientPid == 0) {
490 execl(argv[0], argv[0], "-client", dirname, NULL);
494 waited = waitpid(0, &stat, 0);
495 } while(waited == -1 && errno == EINTR);
497 if (waited == serverPid) {
498 kill(clientPid, SIGTERM);
499 } else if (waited == clientPid) {
500 kill(serverPid, SIGTERM);
502 waitpid(0, &stat, 0);
504 /* Client and server are both done, so cleanup after everything */
506 /* unlinkTestConfig(dirname); */