cmd: Convert to using libtool
[openafs.git] / tests / auth / superuser-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 #include <afsconfig.h>
25 #include <afs/param.h>
26
27 #include <roken.h>
28
29 #ifdef HAVE_SYS_WAIT_H
30 #include <sys/wait.h>
31 #endif
32
33 #ifdef IGNORE_SOME_GCC_WARNINGS
34 # pragma GCC diagnostic warning "-Wdeprecated-declarations"
35 #endif
36
37 #include <afs/cellconfig.h>
38 #include <afs/afsutil.h>
39 #include <afs/com_err.h>
40
41 #include <rx/rxkad.h>
42 #include <rx/rx_identity.h>
43
44 #include <hcrypto/des.h>
45 #include <tests/tap/basic.h>
46
47 #include "test.h"
48 #include "common.h"
49
50 #define TEST_PORT 1234
51
52 static void
53 testOriginalIterator(struct afsconf_dir *dir, int num, char *user) {
54     char buffer[256];
55
56     ok((afsconf_GetNthUser(dir, num, buffer, sizeof buffer) == 0),
57        "User %d successfully returned as %s", num, buffer);
58
59     ok(strcmp(user, buffer) == 0,
60        "User %d matches", num);
61 }
62
63 static void
64 testNewIterator(struct afsconf_dir *dir, int num, struct rx_identity *id) {
65     struct rx_identity *fileId;
66
67     ok((afsconf_GetNthIdentity(dir, num, &fileId) == 0),
68        "Identity %d successfully returned", num);
69
70     ok(rx_identity_match(fileId, id), "Identity %d matches", num);
71
72     rx_identity_free(&fileId);
73 }
74
75
76 void
77 startClient(char *configPath)
78 {
79     struct afsconf_dir *dir;
80     struct rx_identity *testId, *anotherId, *extendedId, *dummy;
81     struct rx_securityClass *class;
82     struct rx_connection *conn;
83     afs_uint32 startTime;
84     char ubuffer[256];
85     afs_int32 classIndex;
86     int code;
87     struct hostent *he;
88     afs_uint32 addr;
89     afs_int32 result;
90     char *string = NULL;
91
92     plan(63);
93
94     dir = afsconf_Open(configPath);
95     ok(dir!=NULL,
96        "Configuration directory opened sucessfully by client");
97
98     /* Add a normal user to the super user file */
99     ok(afsconf_AddUser(dir, "test") == 0,
100        "Adding a simple user works");
101
102     testId = rx_identity_new(RX_ID_KRB4, "test", "test", strlen("test"));
103
104     /* Check that they are a super user */
105     ok(afsconf_IsSuperIdentity(dir, testId),
106        "User added with old i/face is identitifed as super user");
107
108     /* Check that nobody else is */
109     ok(!afsconf_IsSuperIdentity(dir,
110                                rx_identity_new(RX_ID_KRB4, "testy",
111                                                "testy", strlen("testy"))),
112        "Additional users are not super users");
113
114     ok(afsconf_AddUser(dir, "test") == EEXIST,
115        "Adding a user that already exists fails");
116
117     ok(afsconf_AddIdentity(dir, testId) == EEXIST,
118        "Adding an identity that already exists fails");
119
120     anotherId = rx_identity_new(RX_ID_KRB4, "another",
121                                             "another", strlen("another"));
122
123     /* Add another normal user, but using the extended interface */
124     ok(afsconf_AddIdentity(dir, anotherId) == 0,
125        "Adding a KRB4 identity works");
126
127     /* Check that they are a super user */
128     ok(afsconf_IsSuperIdentity(dir, anotherId),
129        "User added with new i/face is identitifed as super user");
130
131     ok(afsconf_AddIdentity(dir, anotherId) == EEXIST,
132        "Adding a KRB4 identity that already exists fails");
133
134     /* Add an extended user to the super user file */
135     extendedId = rx_identity_new(RX_ID_GSS, "sxw@INF.ED.AC.UK",
136                                  "\x04\x01\x00\x0B\x06\x09\x2A\x86\x48\x86\xF7\x12\x01\x02\x02\x00\x00\x00\x10sxw@INF.ED.AC.UK", 35);
137
138     ok(afsconf_AddIdentity(dir, extendedId) == 0,
139        "Adding a GSSAPI identity works");
140
141     /* Check that they are now special */
142     ok(afsconf_IsSuperIdentity(dir, extendedId),
143        "Added GSSAPI identity is a super user");
144
145     /* Check that display name isn't used for matches */
146     ok(!afsconf_IsSuperIdentity(dir,
147                                 rx_identity_new(RX_ID_GSS, "sxw@INF.ED.AC.UK",
148                                                 "abcdefghijklmnopqrstuvwxyz123456789", 35)),
149        "Display name is not used for extended matches");
150
151     ok(afsconf_AddIdentity(dir, extendedId) == EEXIST,
152        "Adding GSSAPI identity twice fails");
153
154     /* Add a final normal user, so we can check that iteration works */
155     /* Add a normal user to the super user file */
156     ok(afsconf_AddUser(dir, "test2") == 0,
157        "Adding another simple user works");
158
159     testOriginalIterator(dir, 0, "test");
160     testOriginalIterator(dir, 1, "another");
161     testOriginalIterator(dir, 2, "test2");
162     ok(afsconf_GetNthUser(dir, 3, ubuffer, sizeof ubuffer) != 0,
163        "Reading past the end of the superuser list fails");
164
165     testNewIterator(dir, 0, testId);
166     testNewIterator(dir, 1, anotherId);
167     testNewIterator(dir, 2, extendedId);
168     testNewIterator(dir, 3, rx_identity_new(RX_ID_KRB4, "test2",
169                                             "test2", strlen("test2")));
170     ok(afsconf_GetNthIdentity(dir, 4, &dummy) != 0,
171        "Reading past the end of the superuser list fails");
172
173     ok(afsconf_DeleteUser(dir, "notthere") != 0,
174        "Deleting a user that doesn't exist fails");
175
176     /* Delete the normal user */
177     ok(afsconf_DeleteUser(dir, "another") == 0,
178        "Deleting normal user works");
179
180     ok(!afsconf_IsSuperIdentity(dir, anotherId),
181        "Deleted user is no longer super user");
182
183     ok(afsconf_IsSuperIdentity(dir, testId) &&
184        afsconf_IsSuperIdentity(dir, extendedId),
185        "Other identities still are");
186
187     ok(afsconf_DeleteIdentity(dir, extendedId) == 0,
188        "Deleting identity works");
189
190     ok(!afsconf_IsSuperIdentity(dir, extendedId),
191        "Deleted identity is no longer special");
192
193     /* Now, what happens if we're doing something over the network instead */
194
195     code = rx_Init(0);
196     is_int(code, 0, "Initialised RX");
197
198     /* Fake up an rx ticket. Note that this will be for the magic 'superuser' */
199     code = afsconf_ClientAuth(dir, &class, &classIndex);
200     is_int(code, 0, "Can successfully create superuser token");
201
202     /* Start a connection to our test service with it */
203     he = gethostbyname("localhost");
204     if (!he) {
205         printf("Couldn't look up server hostname");
206         exit(1);
207     }
208
209     memcpy(&addr, he->h_addr, sizeof(afs_uint32));
210
211     conn = rx_NewConnection(addr, htons(TEST_PORT), TEST_SERVICE_ID,
212                             class, classIndex);
213
214     /* There's nothing in the list, so this just succeeds because we can */
215     code = TEST_CanI(conn, &result);
216     is_int(0, code, "Can run a simple RPC");
217
218     code = TEST_WhoAmI(conn, &string);
219     is_int(0, code, "Can get identity back");
220     is_string("<LocalAuth>", string, "Forged token is super user");
221
222     xdr_free((xdrproc_t)xdr_string, &string);
223
224     /* Throw away this connection and security class */
225     rx_DestroyConnection(conn);
226     rxs_Release(class);
227
228     /* Now fake an rx ticket for a normal user. We have to do more work by hand
229      * here, sadly */
230
231     startTime = time(NULL);
232     class = afstest_FakeRxkadClass(dir, "rpctest", "", "", startTime,
233                                    startTime + 60* 60);
234
235     conn = rx_NewConnection(addr, htons(TEST_PORT), TEST_SERVICE_ID, class,
236                             RX_SECIDX_KAD);
237
238     code = TEST_CanI(conn, &result);
239     is_int(EPERM, code,
240            "Running RPC as non-super user fails as expected");
241     code = TEST_NewCanI(conn, &result);
242     is_int(EPERM, code,
243            "Running new interface RPC as non-super user fails as expected");
244     code = TEST_WhoAmI(conn, &string);
245     xdr_free((xdrproc_t)xdr_string, &string);
246     is_int(EPERM, code,
247            "Running RPC returning string fails as expected");
248     code = TEST_NewWhoAmI(conn, &string);
249     xdr_free((xdrproc_t)xdr_string, &string);
250     is_int(EPERM, code,
251            "Running new interface RPC returning string fails as expected");
252     ok(afsconf_AddUser(dir, "rpctest") == 0,
253        "Adding %s user works", "rpctest");
254     code = TEST_CanI(conn, &result);
255     is_int(0, code, "Running RPC as rpctest works");
256     code = TEST_NewCanI(conn, &result);
257     is_int(0, code, "Running new interface RPC as rpctest works");
258     code = TEST_WhoAmI(conn, &string);
259     is_int(0, code, "Running RPC returning string as %s works", "rpctest");
260     is_string("rpctest", string, "Returned user string matches");
261     xdr_free((xdrproc_t)xdr_string, &string);
262     code = TEST_NewWhoAmI(conn, &string);
263     is_int(0, code, "Running new RPC returning string as %s works", "rpctest");
264     is_string("rpctest", string, "Returned user string for new interface matches");
265     xdr_free((xdrproc_t)xdr_string, &string);
266     rx_DestroyConnection(conn);
267     rxs_Release(class);
268
269     /* Now try with an admin principal */
270     startTime = time(NULL);
271     class = afstest_FakeRxkadClass(dir, "rpctest", "admin", "", startTime,
272                                    startTime + 60* 60);
273
274     conn = rx_NewConnection(addr, htons(TEST_PORT), TEST_SERVICE_ID, class,
275                             RX_SECIDX_KAD);
276
277     code = TEST_CanI(conn, &result);
278     is_int(EPERM, code,
279            "Running RPC as non-super user fails as expected");
280     code = TEST_NewCanI(conn, &result);
281     is_int(EPERM, code,
282            "Running new interface RPC as non-super user fails as expected");
283     code = TEST_WhoAmI(conn, &string);
284     xdr_free((xdrproc_t)xdr_string, &string);
285     is_int(EPERM, code,
286            "Running RPC returning string fails as expected");
287     code = TEST_NewWhoAmI(conn, &string);
288     xdr_free((xdrproc_t)xdr_string, &string);
289     is_int(EPERM, code,
290            "Running new interface RPC returning string fails as expected");
291
292     ok(afsconf_AddUser(dir, "rpctest.admin") == 0,
293        "Adding %s user works", "rpctest.admin");
294
295     code = TEST_CanI(conn, &result);
296     is_int(0, code, "Running RPC as %s works", "rpctest/admin");
297     code = TEST_NewCanI(conn, &result);
298     is_int(0, code, "Running new interface RPC as %s works", "rpctest/admin");
299     code = TEST_WhoAmI(conn, &string);
300     is_int(0, code, "Running RPC returning string as %s works", "rpctest/admin");
301     is_string("rpctest.admin", string, "Returned user string matches");
302     xdr_free((xdrproc_t)xdr_string, &string);
303     code = TEST_NewWhoAmI(conn, &string);
304     is_int(0, code, "Running new interface RPC returning string as %s works",
305            "rpctest/admin");
306     is_string("rpctest.admin", string,
307               "Returned user string from new interface matches");
308     xdr_free((xdrproc_t)xdr_string, &string);
309
310     rx_DestroyConnection(conn);
311     rxs_Release(class);
312 }
313
314 /**********************************************************************
315  * Server
316  **********************************************************************/
317
318 struct afsconf_dir *globalDir;
319
320 int
321 STEST_CanI(struct rx_call *call, afs_int32 *result)
322 {
323     *result = 0;
324     if (!afsconf_SuperUser(globalDir, call, NULL)) {
325         return EPERM;
326     }
327     return 0;
328 }
329
330 int
331 STEST_NewCanI(struct rx_call *call, afs_int32 *result)
332 {
333     *result = 0;
334     if (!afsconf_SuperIdentity(globalDir, call, NULL)) {
335         return EPERM;
336     }
337     return 0;
338 }
339
340 int
341 STEST_WhoAmI(struct rx_call *call, char **result)
342 {
343    char string[MAXKTCNAMELEN];
344
345    if (!afsconf_SuperUser(globalDir, call, string)) {
346         *result = strdup("");
347         return EPERM;
348    }
349    *result = strdup(string);
350
351    return 0;
352 }
353
354 int
355 STEST_NewWhoAmI(struct rx_call *call, char **result)
356 {
357    struct rx_identity *id;
358
359    if (!afsconf_SuperIdentity(globalDir, call, &id)) {
360         *result = strdup("");
361         return EPERM;
362    }
363    *result = strdup(id->displayName);
364
365    return 0;
366 }
367
368 int main(int argc, char **argv)
369 {
370     struct afsconf_dir *dir;
371     char *dirname;
372     int serverPid, clientPid, waited, stat;
373     int code;
374
375     /* Start the client and the server if requested */
376
377     if (argc == 3 ) {
378         if (strcmp(argv[1], "-server") == 0) {
379             globalDir = afsconf_Open(argv[2]);
380             afstest_StartTestRPCService(argv[2], TEST_PORT, TEST_SERVICE_ID,
381                                         TEST_ExecuteRequest);
382             exit(0);
383         } else if (strcmp(argv[1], "-client") == 0) {
384             startClient(argv[2]);
385             exit(0);
386         } else {
387             printf("Bad option %s\n", argv[1]);
388             exit(1);
389         }
390     }
391
392     /* Otherwise, do the basic configuration, then start the client and
393      * server */
394
395     dirname = afstest_BuildTestConfig();
396
397     dir = afsconf_Open(dirname);
398     if (dir == NULL) {
399         fprintf(stderr, "Unable to configure directory.\n");
400         exit(1);
401     }
402
403     code = afstest_AddDESKeyFile(dir);
404     if (code) {
405         afs_com_err("superuser-t", code, "while adding new key\n");
406         exit(1);
407     }
408
409     printf("Config directory is %s\n", dirname);
410     serverPid = fork();
411     if (serverPid == -1) {
412         /* Bang */
413     } else if (serverPid == 0) {
414         execl(argv[0], argv[0], "-server", dirname, NULL);
415         exit(1);
416     }
417     clientPid = fork();
418     if (clientPid == -1) {
419         kill(serverPid, SIGTERM);
420         waitpid(serverPid, &stat, 0);
421         exit(1);
422     } else if (clientPid == 0) {
423         execl(argv[0], argv[0], "-client", dirname, NULL);
424     }
425
426     do {
427         waited = waitpid(0, &stat, 0);
428     } while(waited == -1 && errno == EINTR);
429
430     if (waited == serverPid) {
431         kill(clientPid, SIGTERM);
432     } else if (waited == clientPid) {
433         kill(serverPid, SIGTERM);
434     }
435     waitpid(0, &stat, 0);
436
437     /* Client and server are both done, so cleanup after everything */
438
439     /* unlinkTestConfig(dirname); */
440
441     return 0;
442 }