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 <hcrypto/des.h>
45 #include <tests/tap/basic.h>
50 #define TEST_PORT 1234
53 testOriginalIterator(struct afsconf_dir
*dir
, int num
, char *user
) {
56 ok((afsconf_GetNthUser(dir
, num
, buffer
, sizeof buffer
) == 0),
57 "User %d successfully returned as %s", num
, buffer
);
59 ok(strcmp(user
, buffer
) == 0,
60 "User %d matches", num
);
64 testNewIterator(struct afsconf_dir
*dir
, int num
, struct rx_identity
*id
) {
65 struct rx_identity
*fileId
;
67 ok((afsconf_GetNthIdentity(dir
, num
, &fileId
) == 0),
68 "Identity %d successfully returned", num
);
70 ok(rx_identity_match(fileId
, id
), "Identity %d matches", num
);
72 rx_identity_free(&fileId
);
77 startClient(char *configPath
)
79 struct afsconf_dir
*dir
;
80 struct rx_identity
*testId
, *anotherId
, *extendedId
, *dummy
;
81 struct rx_securityClass
*class;
82 struct rx_connection
*conn
;
94 dir
= afsconf_Open(configPath
);
96 "Configuration directory opened sucessfully by client");
98 /* Add a normal user to the super user file */
99 ok(afsconf_AddUser(dir
, "test") == 0,
100 "Adding a simple user works");
102 testId
= rx_identity_new(RX_ID_KRB4
, "test", "test", strlen("test"));
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");
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");
114 ok(afsconf_AddUser(dir
, "test") == EEXIST
,
115 "Adding a user that already exists fails");
117 ok(afsconf_AddIdentity(dir
, testId
) == EEXIST
,
118 "Adding an identity that already exists fails");
120 anotherId
= rx_identity_new(RX_ID_KRB4
, "another",
121 "another", strlen("another"));
123 /* Add another normal user, but using the extended interface */
124 ok(afsconf_AddIdentity(dir
, anotherId
) == 0,
125 "Adding a KRB4 identity works");
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");
131 ok(afsconf_AddIdentity(dir
, anotherId
) == EEXIST
,
132 "Adding a KRB4 identity that already exists fails");
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);
138 ok(afsconf_AddIdentity(dir
, extendedId
) == 0,
139 "Adding a GSSAPI identity works");
141 /* Check that they are now special */
142 ok(afsconf_IsSuperIdentity(dir
, extendedId
),
143 "Added GSSAPI identity is a super user");
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");
151 ok(afsconf_AddIdentity(dir
, extendedId
) == EEXIST
,
152 "Adding GSSAPI identity twice fails");
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");
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");
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");
173 ok(afsconf_DeleteUser(dir
, "notthere") != 0,
174 "Deleting a user that doesn't exist fails");
176 /* Delete the normal user */
177 ok(afsconf_DeleteUser(dir
, "another") == 0,
178 "Deleting normal user works");
180 ok(!afsconf_IsSuperIdentity(dir
, anotherId
),
181 "Deleted user is no longer super user");
183 ok(afsconf_IsSuperIdentity(dir
, testId
) &&
184 afsconf_IsSuperIdentity(dir
, extendedId
),
185 "Other identities still are");
187 ok(afsconf_DeleteIdentity(dir
, extendedId
) == 0,
188 "Deleting identity works");
190 ok(!afsconf_IsSuperIdentity(dir
, extendedId
),
191 "Deleted identity is no longer special");
193 /* Now, what happens if we're doing something over the network instead */
196 is_int(code
, 0, "Initialised RX");
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");
202 /* Start a connection to our test service with it */
203 he
= gethostbyname("localhost");
205 printf("Couldn't look up server hostname");
209 memcpy(&addr
, he
->h_addr
, sizeof(afs_uint32
));
211 conn
= rx_NewConnection(addr
, htons(TEST_PORT
), TEST_SERVICE_ID
,
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");
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");
222 xdr_free((xdrproc_t
)xdr_string
, &string
);
224 /* Throw away this connection and security class */
225 rx_DestroyConnection(conn
);
228 /* Now fake an rx ticket for a normal user. We have to do more work by hand
231 startTime
= time(NULL
);
232 class = afstest_FakeRxkadClass(dir
, "rpctest", "", "", startTime
,
235 conn
= rx_NewConnection(addr
, htons(TEST_PORT
), TEST_SERVICE_ID
, class,
238 code
= TEST_CanI(conn
, &result
);
240 "Running RPC as non-super user fails as expected");
241 code
= TEST_NewCanI(conn
, &result
);
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
);
247 "Running RPC returning string fails as expected");
248 code
= TEST_NewWhoAmI(conn
, &string
);
249 xdr_free((xdrproc_t
)xdr_string
, &string
);
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
);
269 /* Now try with an admin principal */
270 startTime
= time(NULL
);
271 class = afstest_FakeRxkadClass(dir
, "rpctest", "admin", "", startTime
,
274 conn
= rx_NewConnection(addr
, htons(TEST_PORT
), TEST_SERVICE_ID
, class,
277 code
= TEST_CanI(conn
, &result
);
279 "Running RPC as non-super user fails as expected");
280 code
= TEST_NewCanI(conn
, &result
);
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
);
286 "Running RPC returning string fails as expected");
287 code
= TEST_NewWhoAmI(conn
, &string
);
288 xdr_free((xdrproc_t
)xdr_string
, &string
);
290 "Running new interface RPC returning string fails as expected");
292 ok(afsconf_AddUser(dir
, "rpctest.admin") == 0,
293 "Adding %s user works", "rpctest.admin");
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",
306 is_string("rpctest.admin", string
,
307 "Returned user string from new interface matches");
308 xdr_free((xdrproc_t
)xdr_string
, &string
);
310 rx_DestroyConnection(conn
);
314 /**********************************************************************
316 **********************************************************************/
318 struct afsconf_dir
*globalDir
;
321 STEST_CanI(struct rx_call
*call
, afs_int32
*result
)
324 if (!afsconf_SuperUser(globalDir
, call
, NULL
)) {
331 STEST_NewCanI(struct rx_call
*call
, afs_int32
*result
)
334 if (!afsconf_SuperIdentity(globalDir
, call
, NULL
)) {
341 STEST_WhoAmI(struct rx_call
*call
, char **result
)
343 char string
[MAXKTCNAMELEN
];
345 if (!afsconf_SuperUser(globalDir
, call
, string
)) {
346 *result
= strdup("");
349 *result
= strdup(string
);
355 STEST_NewWhoAmI(struct rx_call
*call
, char **result
)
357 struct rx_identity
*id
;
359 if (!afsconf_SuperIdentity(globalDir
, call
, &id
)) {
360 *result
= strdup("");
363 *result
= strdup(id
->displayName
);
368 int main(int argc
, char **argv
)
370 struct afsconf_dir
*dir
;
372 int serverPid
, clientPid
, waited
, stat
;
376 afstest_SkipTestsIfBadHostname();
378 /* Start the client and the server if requested */
381 if (strcmp(argv
[1], "-server") == 0) {
382 globalDir
= afsconf_Open(argv
[2]);
383 afstest_StartTestRPCService(argv
[2], TEST_PORT
, TEST_SERVICE_ID
,
384 TEST_ExecuteRequest
);
386 } else if (strcmp(argv
[1], "-client") == 0) {
387 startClient(argv
[2]);
390 printf("Bad option %s\n", argv
[1]);
395 /* Otherwise, do the basic configuration, then start the client and
398 dirname
= afstest_BuildTestConfig();
400 dir
= afsconf_Open(dirname
);
402 fprintf(stderr
, "Unable to configure directory.\n");
407 code
= afstest_AddDESKeyFile(dir
);
409 afs_com_err("superuser-t", code
, "while adding new key\n");
414 printf("Config directory is %s\n", dirname
);
416 if (serverPid
== -1) {
418 } else if (serverPid
== 0) {
419 execl(argv
[0], argv
[0], "-server", dirname
, NULL
);
424 if (clientPid
== -1) {
425 kill(serverPid
, SIGTERM
);
426 waitpid(serverPid
, &stat
, 0);
429 } else if (clientPid
== 0) {
430 execl(argv
[0], argv
[0], "-client", dirname
, NULL
);
434 waited
= waitpid(0, &stat
, 0);
435 } while(waited
== -1 && errno
== EINTR
);
437 if (waited
== serverPid
) {
438 kill(clientPid
, SIGTERM
);
439 } else if (waited
== clientPid
) {
440 kill(serverPid
, SIGTERM
);
442 waitpid(0, &stat
, 0);
445 /* Client and server are both done, so cleanup after everything */
446 afstest_UnlinkTestConfig(dirname
);