Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / kauth / test / test_rxkad_free.c
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13
14 #include <afs/stds.h>
15 #include <sys/types.h>
16 #include <sys/time.h>
17 #include <sys/resource.h>
18 #include <stdio.h>
19 #include <netinet/in.h>
20 #include <netdb.h>
21 #include <rx/rx.h>
22 #include <ubik.h>
23 #include <pwd.h>
24 #include <afs/auth.h>
25 #include <afs/cellconfig.h>
26 #include <afs/cmd.h>
27 #include <afs/com_err.h>
28
29 #include "kauth.h"
30 #include "kautils.h"
31
32
33 char *whoami = "test_rxkad_free";
34
35 static void
36 PrintRxkadStats()
37 {
38 printf("New Objects client %d, server %d. Destroyed objects %d.\n",
39 rxkad_stats.clientObjects, rxkad_stats.serverObjects,
40 rxkad_stats.destroyObject);
41 printf("client conns: %d %d %d, destroyed client %d.\n",
42 rxkad_stats.connections[0], rxkad_stats.connections[1],
43 rxkad_stats.connections[2], rxkad_stats.destroyClient);
44 printf("server challenges %d, responses %d %d %d\n",
45 rxkad_stats.challengesSent, rxkad_stats.responses[0],
46 rxkad_stats.responses[1], rxkad_stats.responses[2]);
47 printf("server conns %d %d %d unused %d, unauth %d\n",
48 rxkad_stats.destroyConn[0], rxkad_stats.destroyConn[1],
49 rxkad_stats.destroyConn[2], rxkad_stats.destroyUnused,
50 rxkad_stats.destroyUnauth);
51 }
52
53 static int
54 Main(struct cmd_syndesc *as, void *arock)
55 {
56 int code;
57 char name[MAXKTCNAMELEN];
58 char instance[MAXKTCNAMELEN];
59 char newCell[MAXKTCREALMLEN];
60 char *cell;
61
62 long serverList[MAXSERVERS];
63 extern struct passwd *getpwuid();
64
65 struct passwd *pw;
66 struct ktc_encryptionKey key;
67
68 char passwd[BUFSIZ];
69
70 int cellSpecified;
71 int i;
72 int verbose = (as->parms[1].items != 0);
73 int hostUsage = (as->parms[2].items != 0);
74 int waitReap = (as->parms[4].items != 0);
75 int doAuth = (as->parms[5].items != 0);
76 int number; /* number of iterations */
77 int callsPerSecond; /* to allow conn GC to run */
78
79 unsigned long lo, hi; /* mem usage */
80 unsigned long highWater; /* mem usage after reap period */
81 unsigned long lastWater; /* mem usage after last msg */
82 int serversUse[MAXSERVERS]; /* usage of each server */
83 long serversHost[MAXSERVERS]; /* host addr */
84 unsigned long startTime;
85 unsigned long now;
86
87 lo = 0;
88 whoami = as->a0name;
89 newCell[0] = 0;
90
91 if (as->parms[0].items)
92 number = atoi(as->parms[0].items->data);
93 else
94 number = 100;
95 if (as->parms[3].items)
96 callsPerSecond = atoi(as->parms[3].items->data);
97 else
98 callsPerSecond = 1;
99 if (doAuth && hostUsage) {
100 fprintf(stderr,
101 "Can't report host usage when calling UserAuthenticate\n");
102 return -1;
103 }
104
105 if (as->parms[12].items) { /* if username specified */
106 code =
107 ka_ParseLoginName(as->parms[12].items->data, name, instance,
108 newCell);
109 if (code) {
110 afs_com_err(whoami, code, "parsing user's name '%s'",
111 as->parms[12].items->data);
112 return code;
113 }
114 if (strlen(newCell) > 0)
115 cellSpecified = 1;
116 } else {
117 /* No explicit name provided: use Unix uid. */
118 pw = getpwuid(getuid());
119 if (pw == 0) {
120 printf("Can't figure out your name from your user id.\n");
121 return KABADCMD;
122 }
123 strncpy(name, pw->pw_name, sizeof(name));
124 strcpy(instance, "");
125 strcpy(newCell, "");
126 }
127 if (strcmp(as->parms[14].name, "-cell") == 0) {
128 if (as->parms[14].items) { /* if cell specified */
129 if (cellSpecified)
130 printf("Duplicate cell specification not allowed\n");
131 else
132 strncpy(newCell, as->parms[14].items->data, sizeof(newCell));
133 }
134 }
135
136 code = ka_ExpandCell(newCell, newCell, 0 /*local */ );
137 if (code) {
138 afs_com_err(whoami, code, "Can't expand cell name");
139 return code;
140 }
141 cell = newCell;
142
143 if (as->parms[13].items) { /* if password specified */
144 strncpy(passwd, as->parms[13].items->data, sizeof(passwd));
145 memset(as->parms[13].items->data, 0,
146 strlen(as->parms[13].items->data));
147 } else {
148 char msg[sizeof(name) + 15];
149 if (as->parms[12].items)
150 strcpy(msg, "Admin Password: ");
151 else
152 sprintf(msg, "Password for %s: ", name);
153 code = read_pw_string(passwd, sizeof(passwd), msg, 0);
154 if (code)
155 code = KAREADPW;
156 else if (strlen(passwd) == 0)
157 code = KANULLPASSWORD;
158 if (code) {
159 afs_com_err(whoami, code, "reading password");
160 return code;
161 }
162 }
163 if (as->parms[15].items) {
164 struct cmd_item *ip;
165 char *ap[MAXSERVERS + 2];
166
167 for (ip = as->parms[15].items, i = 2; ip; ip = ip->next, i++)
168 ap[i] = ip->data;
169 ap[0] = "";
170 ap[1] = "-servers";
171 code = ubik_ParseClientList(i, ap, serverList);
172 if (code) {
173 afs_com_err(whoami, code, "could not parse server list");
174 return code;
175 }
176 ka_ExplicitCell(cell, serverList);
177 }
178
179 if (!doAuth) {
180 ka_StringToKey(passwd, cell, &key);
181 memset(passwd, 0, sizeof(passwd));
182 }
183 if (hostUsage) {
184 memset(serversUse, 0, sizeof(serversUse));
185 memset(serversHost, 0, sizeof(serversHost));
186 }
187
188 startTime = time(0);
189 for (i = 0; i < number; i++) {
190 if (doAuth) {
191 char *reason;
192 code =
193 ka_UserAuthenticateLife(0, name, instance, cell, passwd, 0,
194 &reason);
195 if (code) {
196 fprintf(stderr, "Unable to authenticate to AFS because %s.\n",
197 reason);
198 return code;
199 }
200 } else {
201 struct ktc_token token;
202 struct ktc_token *pToken;
203 struct ubik_client *ubikConn;
204 struct kaentryinfo tentry;
205 int c;
206
207 code =
208 ka_GetAdminToken(name, instance, cell, &key, 3600, &token,
209 1 /*new */ );
210 if (code) {
211 afs_com_err(whoami, code, "getting admin token");
212 return code;
213 }
214 pToken = &token;
215 if (token.ticketLen == 0) {
216 fprintf("Can't get admin token\n");
217 return -1;
218 }
219
220 code =
221 ka_AuthServerConn(cell, KA_MAINTENANCE_SERVICE, pToken,
222 &ubikConn);
223 if (code) {
224 afs_com_err(whoami, code, "Getting AuthServer ubik conn");
225 return code;
226 }
227
228 if (verbose)
229 for (c = 0; c < MAXSERVERS; c++) {
230 struct rx_connection *rxConn =
231 ubik_GetRPCConn(ubikConn, c);
232 struct rx_peer *peer;
233
234 if (rxConn == 0)
235 break;
236 peer = rx_PeerOf(rxConn);
237 printf("conn to %s:%d secObj:%x\n",
238 inet_ntoa(rx_HostOf(peer)), ntohs(rx_PortOf(peer)),
239 rxConn->securityObject);
240 }
241
242 code =
243 ubik_Call(KAM_GetEntry, ubikConn, 0, name, instance,
244 KAMAJORVERSION, &tentry);
245 if (code) {
246 afs_com_err(whoami, code, "getting information for %s.%s", name,
247 instance);
248 return code;
249 }
250
251 for (c = 0; c < MAXSERVERS; c++) {
252 struct rx_connection *rxConn = ubik_GetRPCConn(ubikConn, c);
253 int d;
254 if (rxConn == 0)
255 break;
256 if (rxConn->serial > 0) {
257 long host = rx_HostOf(rx_PeerOf(rxConn));
258 for (d = 0; d < MAXSERVERS; d++) {
259 if (serversHost[d] == 0)
260 serversHost[d] = host;
261 if (host == serversHost[d]) {
262 serversUse[d]++;
263 break;
264 }
265 }
266 }
267 if (verbose)
268 printf("serial is %d\n", rxConn->serial);
269 }
270 ubik_ClientDestroy(ubikConn);
271 }
272
273 now = time(0);
274 if (!lo)
275 lo = sbrk(0);
276 if (i && ((i & 0x3f) == 0)) {
277 unsigned long this = sbrk(0);
278 printf(" mem after %d: lo=%x, cur=%x => %d (@ %d)\n", i, lo,
279 this, this - lo, (this - lo) / i);
280 if (highWater && (lastWater != this)) {
281 lastWater = this;
282 printf(" core leaking (after %d) should be %x, is %x\n", i,
283 highWater, this);
284 }
285 }
286 if ((highWater == 0) && ((now - startTime) > 61)) {
287 highWater = sbrk(0);
288 lastWater = highWater;
289 printf(" mem highWater mark (after %d) should be %x\n", i,
290 highWater);
291 }
292 if (callsPerSecond) {
293 long target;
294 if (callsPerSecond > 0)
295 target = i / callsPerSecond;
296 else /* if negative interpret as seconds per call */
297 target = i * (-callsPerSecond);
298 target = (startTime + target) - now;
299 if (target > 0)
300 IOMGR_Sleep(target);
301 }
302 }
303 printf("calling finalize\n");
304 rx_Finalize();
305 hi = sbrk(0);
306 if (hostUsage) {
307 int total = 0;
308 for (i = 0; i < MAXSERVERS; i++) {
309 total += serversUse[i];
310 if (serversHost[i] == 0)
311 break;
312 printf("host %s used %d times (%2g%%)\n",
313 inet_ntoa(serversHost[i]), serversUse[i],
314 100.0 * serversUse[i] / (double)number);
315 }
316 if (total > number)
317 printf(" %2g%% retries\n",
318 100.0 * (total - number) / (double)number);
319 }
320 PrintRxkadStats();
321 printf("mem usage: lo=%x, hi=%x => %d (@ %d)\n", lo, hi, hi - lo,
322 (hi - lo) / number);
323 if (waitReap) {
324 unsigned long mediumHi;
325 printf("Waiting 61 seconds for all connections to be reaped\n");
326 IOMGR_Sleep(61);
327 PrintRxkadStats();
328 mediumHi = hi;
329 hi = sbrk(0);
330 if (mediumHi != hi)
331 printf("mem usage: lo=%x, hi=%x => %d (@ %d)\n", lo, hi, hi - lo,
332 (hi - lo) / number);
333 }
334 /* most of these checks are sure to fail w/o waiting for reap */
335 if (waitReap
336 && ((rxkad_stats_clientObjects != rxkad_stats.destroyObject)
337 || (rxkad_stats.connections[0] + rxkad_stats.connections[1] +
338 rxkad_stats.connections[2] != rxkad_stats.destroyClient)
339 || (rxkad_stats.responses[0] != rxkad_stats.destroyConn[0])
340 || (rxkad_stats.responses[1] != rxkad_stats.destroyConn[1])
341 || (rxkad_stats.responses[2] != rxkad_stats.destroyConn[2])
342 /* values of destroyUnused and destroyUnauth should be very small */
343 )) {
344 fprintf(stderr, "Some rxkad security storage not freed\n");
345 return 1;
346 }
347 if ((highWater != 0) && (highWater < hi)) {
348 /* We should reach steady state memory usage after 60 seconds (the Rx
349 * connection reap period). If we are still using memory, there must
350 * be a core leak. */
351 fprintf(stderr, "Core leak\n");
352 return 1;
353 }
354 return 0;
355 }
356
357 int
358 main(argc, argv)
359 IN int argc;
360 IN char *argv[];
361 {
362 struct cmd_syndesc *ts;
363 long code;
364
365 initialize_U_error_table();
366 initialize_CMD_error_table();
367 initialize_RXK_error_table();
368 initialize_KTC_error_table();
369 initialize_ACFG_error_table();
370 initialize_KA_error_table();
371
372 ts = cmd_CreateSyntax(NULL, Main, NULL, 0, "Main program");
373 /* 0 */ cmd_AddParm(ts, "-number", CMD_SINGLE, CMD_OPTIONAL,
374 "number of iterations");
375 /* 1 */ cmd_AddParm(ts, "-long", CMD_FLAG, CMD_OPTIONAL,
376 "long form of output");
377 /* 2 */ cmd_AddParm(ts, "-hostusage", CMD_FLAG, CMD_OPTIONAL,
378 "report distribution of host usage");
379 /* 3 */ cmd_AddParm(ts, "-rate", CMD_SINGLE, CMD_OPTIONAL,
380 "calls per second");
381 /* 4 */ cmd_AddParm(ts, "-waitforreap", CMD_FLAG, CMD_OPTIONAL,
382 "wait one reap time before exit");
383 /* 5 */ cmd_AddParm(ts, "-doauth", CMD_FLAG, CMD_OPTIONAL,
384 "call UserAuthenticate instead of GetEntry");
385 cmd_Seek(ts, 12);
386 /* 12 */ cmd_AddParm(ts, "-admin_username", CMD_SINGLE, CMD_OPTIONAL,
387 "admin principal to use for authentication");
388 /* 13 */ cmd_AddParm(ts, "-password_for_admin", CMD_SINGLE, CMD_OPTIONAL,
389 "admin password");
390 /* 14 */ cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
391 /* 15 */ cmd_AddParm(ts, "-servers", CMD_LIST, CMD_OPTIONAL,
392 "explicit list of authentication servers");
393 code = cmd_Dispatch(argc, argv);
394 return (code != 0);
395 }