backport to buster
[hcoop/debian/openafs.git] / src / ptserver / testpt.c
CommitLineData
805e021f
CE
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#include <roken.h>
14#include <afs/opr.h>
15
16#include <ctype.h>
17#include <math.h>
18
19#ifdef AFS_NT40_ENV
20#include <WINNT/afsevent.h>
21#endif
22
23#include <rx/rx.h>
24#include <rx/xdr.h>
25#include <afs/rxgen_consts.h>
26#include <afs/cmd.h>
27#include <afs/auth.h>
28#include <afs/cellconfig.h>
29#include <afs/afsutil.h>
30#include <afs/com_err.h>
31
32#include "ptclient.h"
33#include "pterror.h"
34#include "ptuser.h"
35#include "ptprototypes.h"
36
37static char *whoami = "testpr";
38static struct afsconf_dir *conf; /* cell info, set by MyBeforeProc */
39static char conf_dir[100];
40static char lcell[MAXCELLCHARS];
41
42int
43ListUsedIds(struct cmd_syndesc *as, void *arock)
44{
45 afs_int32 code;
46 namelist lnames;
47 idlist lids;
48 int i, j;
49 int group = 0; /* check groups */
50 int unused = 0; /* print unused */
51 int number = 100; /* check 100 ids */
52 afs_int32 startId = 1;
53 afs_int32 maxId;
54 int range;
55
56 if (as->parms[0].items)
57 startId = atoi(as->parms[0].items->data);
58 if (as->parms[1].items)
59 number = atoi(as->parms[1].items->data);
60 if (as->parms[2].items)
61 unused = 1;
62
63 code = pr_Initialize(1, conf_dir, NULL);
64 if (code) {
65 afs_com_err(whoami, code, "initializing pruser");
66 exit(1);
67 }
68 if (startId < 0) {
69 group = 1;
70 code = pr_ListMaxGroupId(&maxId);
71 if (code) {
72 bad_max:
73 afs_com_err(whoami, code, "getting maximum id");
74 exit(2);
75 }
76 if (startId < maxId) {
77 fprintf(stderr, "Max group id is only %d.\n", maxId);
78 exit(3);
79 }
80 } else {
81 code = pr_ListMaxUserId(&maxId);
82 if (code)
83 goto bad_max;
84 if (startId > maxId) {
85 fprintf(stderr, "Max user id is only %d.\n", maxId);
86 exit(3);
87 }
88 }
89 range = abs(startId - maxId);
90 range++; /* number that can be printed */
91 if (range < number) {
92 fprintf(stderr, "Only %d ids to be checked.\n", range);
93 number = range;
94 }
95
96 printf("Checking for %d %sused ids starting at %d.\n", number,
97 (unused ? "un" : ""), startId);
98#define NUM 100
99 lids.idlist_val = malloc(sizeof(afs_int32) * NUM);
100 lnames.namelist_len = 0;
101 lnames.namelist_val = 0;
102 while (number) {
103 if (number < NUM)
104 i = number;
105 else
106 i = NUM;
107 for (j = 0; j < i; j++) {
108 lids.idlist_val[j] = startId;
109 if (group)
110 startId--;
111 else
112 startId++;
113 }
114 lids.idlist_len = i;
115 code = pr_IdToName(&lids, &lnames);
116 if (code) {
117 afs_com_err(whoami, code, "converting id to name");
118 exit(2);
119 }
120 for (j = 0; j < lnames.namelist_len; j++) {
121 if (lids.idlist_val[j] == atoi(lnames.namelist_val[j])) {
122 if (unused)
123 printf("%s is free\n", lnames.namelist_val[j]);
124 } else {
125 if (!unused)
126 printf("%s is id %d\n", lnames.namelist_val[j],
127 lids.idlist_val[j]);
128 }
129 }
130 number -= i;
131 }
132 if (lids.idlist_val)
133 free(lids.idlist_val);
134 if (lnames.namelist_val)
135 free(lnames.namelist_val);
136 return 0;
137}
138
139/* TestManyMembers - called with a number N. Try creating N users and N groups
140 * and put all the users on one of the groups and one of the users on all the
141 * groups. Also put many users on many groups.
142 *
143 * To keep track of this create an NxN matrix of membership and fill it in with
144 * a function that looks like a quarter of a circle. That makes the first
145 * group contain every user and the first user be a member of every group. */
146
147int verbose;
148char callerName[PR_MAXNAMELEN];
149afs_int32 callerId;
150afs_int32 lastGroup; /* id of last group created */
151afs_int32 ownerUser; /* first created user */
152char ownerUserName[PR_MAXNAMELEN]; /* " " " name */
153int steepDropOff; /* precentage decreate in GroupLimit */
154char *createPrefix; /* prefix for naming users&groups */
155extern struct ubik_client *pruclient; /* initialized by pr_Initialize */
156
157/* These variables form the state if this test */
158int number; /* max number of members */
159char *population; /* matrix of memberships */
160afs_int32 *users; /* ids of users */
161afs_int32 *groups; /* ids of groups */
162afs_int32 *groupOwners; /* ids of owners of groups */
163
164/* statistics */
165int nUsers, nGroups, nAdds, nRems, nUDels, nGDels;
166
167int
168IdCmp(const void *a, const void *b)
169{
170 if (*(afs_int32 *)a > *(afs_int32 *)b) {
171 return 1;
172 } else if (*(afs_int32 *)a == *(afs_int32 *)b) {
173 return 0;
174 } else /* (*a < *b) */ {
175 return -1;
176 }
177}
178
179static int
180sqr(int n)
181{
182 return n * n;
183}
184
185static int
186GetGroupLimit(int N, int x)
187{
188 int y;
189
190 if ((x >= N) || (x < 0)) {
191 printf("GetGroupLimit: input value out of range %d (%d)\n", x, N);
192 exit(10);
193 }
194 if (steepDropOff) { /* Use exponential decrease */
195 int i;
196 y = N;
197 for (i = 0; i < x; i++) {
198 y = (y * steepDropOff) / 100; /* parameter is a percentage */
199 if (y == 0) {
200 y = 1; /* with a floor of 1 */
201 break;
202 }
203 }
204 } else { /* Use a circle's third quadrant */
205 y = sqr(N - 1) - sqr(N - 1 - x);
206 y = (int)(sqrt((double)y) + 0.5); /* round off */
207 y = N - y;
208 }
209 if ((y > N) || (y < 1)) {
210 printf("filling value out of range: %d (%d) => %d\n", x, N, y);
211 exit(11);
212 }
213 return y;
214}
215
216void
217CreateUser(int u)
218{
219 afs_int32 code;
220 char name[16];
221 afs_int32 id;
222
223 sprintf(name, "%s%d", createPrefix, u);
224 id = 0;
225 code = pr_CreateUser(name, &id);
226 if (code) {
227 if (code == PREXIST) {
228 code = pr_Delete(name);
229 if (code == 0) {
230 nUDels++;
231 code = pr_CreateUser(name, &id);
232 if (code == 0) {
233 if (verbose)
234 printf("RE-");
235 goto done;
236 }
237 }
238 }
239 afs_com_err(whoami, code, "couldn't create %s", name);
240 exit(12);
241 }
242 done:
243 if (verbose)
244 printf("Creating user %s (%di)\n", name, id);
245 users[u] = id;
246 nUsers++;
247
248 if (ownerUser == 0) {
249 ownerUser = id;
250 strcpy(ownerUserName, name);
251 }
252}
253
254void
255CreateGroup(int g)
256{
257 afs_int32 code;
258 char name[16];
259 afs_int32 id = 0;
260 afs_int32 owner = 0;
261 char *ownerName = NULL;
262 int ownerType; /* type of ownership */
263 static char *lastGroupPrefix; /* prefix used for type==2 */
264
265 /* At least 50 groups should be owned by another group to test long owner
266 * chains during deletion. Also let's create some long owners of owners
267 * lists. */
268 ownerType = random() % 3;
269
270 if (!ownerUser)
271 ownerType = 0;
272 if (!lastGroup)
273 ownerType = 0;
274 switch (ownerType) {
275 case 0:
276 owner = callerId;
277 ownerName = callerName;
278 break;
279 case 1:
280 owner = ownerUser;
281 ownerName = ownerUserName;
282 break;
283 case 2:
284 owner = lastGroup;
285 ownerName = lastGroupPrefix;
286 break;
287 }
288
289 sprintf(name, "%s:%s%d", ownerName, createPrefix, g);
290 code = ubik_PR_NewEntry(pruclient, 0, name, PRGRP, owner, &id);
291 if (code) {
292 if (code == PREXIST) {
293 code = pr_Delete(name);
294 if (code == 0) {
295 nGDels++;
296 code =
297 ubik_PR_NewEntry(pruclient, 0, name, PRGRP, owner,
298 &id);
299 if (code == 0) {
300 if (verbose)
301 printf("RE-");
302 goto done;
303 }
304 }
305 }
306 afs_com_err(whoami, code, "couldn't create %s w/ owner=%d", name, owner);
307 exit(13);
308 }
309 done:
310 if (verbose)
311 printf("Creating group %s (%di)\n", name, id);
312 groups[g] = id;
313 groupOwners[g] = owner;
314 nGroups++;
315 if (!lastGroup || (ownerType == 2)) {
316 lastGroup = id;
317 lastGroupPrefix = ownerName;
318 }
319}
320
321int
322DeleteRandomId(afs_int32 *list)
323{
324 afs_int32 code;
325 afs_int32 id;
326 int j, k;
327 int m;
328
329 k = random(); /* random starting point */
330 for (j = 0; j < number; j++) { /* find an undeleted id */
331 m = (k + j) % number;
332 if ((id = list[m])) {
333 code = ubik_PR_Delete(pruclient, 0, id);
334 if (code) {
335 afs_com_err(whoami, code, "Couldn't delete %di", id);
336 exit(22);
337 }
338 list[m] = 0;
339 if (list == users)
340 nUDels++;
341 else
342 nGDels++;
343 return 0;
344 }
345 }
346 return -1; /* none left */
347}
348
349void
350AddUser(int u, int g)
351{
352 afs_int32 code;
353 afs_int32 ui, gi;
354
355 if (users[u] == 0) /* create if necessary */
356 CreateUser(u);
357 if (groups[g] == 0) /* create group if necessary */
358 CreateGroup(g);
359 ui = users[u];
360 gi = groups[g];
361 code = ubik_PR_AddToGroup(pruclient, 0, ui, gi);
362 if (code) {
363 afs_com_err(whoami, code, "couldn't add %d to %d", ui, gi);
364 exit(14);
365 }
366 if (verbose)
367 printf("Adding user (%di) to group (%di)\n", ui, gi);
368 population[u * number + g]++;
369 nAdds++;
370}
371
372void
373RemUser(int u, int g)
374{
375 afs_int32 code;
376 afs_int32 ui, gi;
377
378 ui = users[u];
379 gi = groups[g];
380 code = ubik_PR_RemoveFromGroup(pruclient, 0, ui, gi);
381 if (code) {
382 afs_com_err(whoami, code, "couldn't remove %d from %d", ui, gi);
383 exit(14);
384 }
385 if (verbose)
386 printf("Removing user (%di) from group (%di)\n", ui, gi);
387 population[u * number + g]--;
388 nRems++;
389}
390
391int
392TestManyMembers(struct cmd_syndesc *as, void *arock)
393{
394 char *filled; /* users filled up */
395 char *cleaned; /* users cleaned up */
396
397 int nFilled, nCleaned;
398 int u, g, i, j, n;
399 int seed; /* random number generator seed */
400
401 afs_int32 *glist; /* membership list */
402
403 afs_int32 code;
404
405 code = pr_Initialize(1, conf_dir, NULL);
406 if (code) {
407 afs_com_err(whoami, code, "initializing pruser");
408 exit(1);
409 }
410 /* get name of person running command */
411 {
412 struct ktc_principal afs, user;
413 struct ktc_token token;
414
415 strcpy(afs.name, "afs");
416 strcpy(afs.instance, "");
417 code = afsconf_GetLocalCell(conf, afs.cell, sizeof(afs.cell));
418 if (code)
419 exit(2);
420 code = ktc_GetToken(&afs, &token, sizeof(token), &user);
421 if (code) {
422 afs_com_err(whoami, code, "getting afs tokens");
423 exit(3);
424 }
425 if (strlen(user.instance) > 0) {
426 fprintf(stderr, "can't handle non-null instance %s.%s\n",
427 user.name, user.cell);
428 exit(4);
429 }
430 if (strncmp(user.name, "AFS ID ", 7) == 0) {
431 callerId = atoi(user.name + 7);
432 code = pr_SIdToName(callerId, callerName);
433 if (code) {
434 afs_com_err(whoami, code, "call get name for id %d", callerId);
435 exit(6);
436 }
437 } else {
438 strcpy(callerName, user.name);
439 code = pr_SNameToId(callerName, &callerId);
440 if ((code == 0) && (callerId == ANONYMOUSID))
441 code = PRNOENT;
442 }
443#if 0 /* don't create user */
444 if (code == PRNOENT) {
445 callerId = 0;
446 code = pr_CreateUser(callerName, &callerId);
447 if (code) {
448 afs_com_err(whoami, code, "can't create caller %s", callerName);
449 exit(5);
450 }
451 printf("Creating caller %s (%di)\n", callerName, callerId);
452 }
453 /* else */
454#endif
455 if (code) {
456 afs_com_err(whoami, code, "can't find caller %s", callerName);
457 exit(6);
458 } else
459 printf("Assuming caller is %s (%di)\n", callerName, callerId);
460 }
461
462 /* Parse arguments */
463 if (as->parms[0].items)
464 number = atoi(as->parms[0].items->data);
465 if (as->parms[1].items) {
466 steepDropOff = atoi(as->parms[1].items->data);
467 if ((steepDropOff < 0) || (steepDropOff > 100)) {
468 fprintf(stderr,
469 "Illegal value for dropoff: %d, must be between 0 and 100, inclusive.\n",
470 steepDropOff);
471 exit(7);
472 }
473 } else
474 steepDropOff = 0; /* use quadratic dropoff */
475 if (as->parms[2].items)
476 createPrefix = as->parms[2].items->data;
477 else
478 createPrefix = "u";
479 if (as->parms[3].items)
480 verbose = 1;
481 else
482 verbose = 0;
483 if (as->parms[4].items)
484 seed = atoi(as->parms[4].items->data);
485 else
486 seed = 1;
487
488 srandom(seed);
489
490 users = calloc(number, sizeof(afs_int32));
491 groups = calloc(number, sizeof(afs_int32));
492 filled = calloc(number, sizeof(char));
493 cleaned = calloc(number, sizeof(char));
494 population = calloc(sqr(number), sizeof(char));
495
496 nFilled = 0;
497 nCleaned = 0;
498
499 ownerUser = lastGroup = 0;
500 groupOwners = malloc(number * sizeof(afs_int32));
501 nUsers = nGroups = nAdds = nRems = nUDels = nGDels = 0;
502
503 while ((nFilled < number) || (nCleaned < number)) {
504 /* pick a user at random, using */
505 u = random() % number;
506 if (!filled[u]) {
507 n = GetGroupLimit(number, u); /* get group limit for that user */
508 g = random() % (n + 1); /* pick a random group */
509 if (g == n) { /* in a few cases create any user */
510 n = number; /* in the whole range */
511 g = random() % n;
512 }
513 for (i = 0; i < n; i++) { /* rotate until unused one found */
514 j = (g + i) % n;
515 if (!population[u * number + j]) {
516 /* add this user/group membership */
517 AddUser(u, j);
518 goto added;
519 }
520 }
521 filled[u]++;
522 nFilled++;
523 added:;
524 }
525 if (!cleaned[u]) {
526 int base;
527 if (filled[u]) { /* only clean above GroupLimit */
528 base = GetGroupLimit(number, u);
529 n = number - base;
530 if (n == 0)
531 goto iscleaned;
532 g = random() % n;
533 } else {
534 base = 0;
535 n = number; /* pick a group from the whole range */
536 g = random() % 2 * n; /* at random for removal */
537 if (g >= n)
538 goto remed; /* but half the time do nothing */
539 }
540 for (i = 0; i < n; i++) { /* rotate until used one found */
541 j = (g + i) % n + base;
542 if (population[u * number + j]) {
543 /* remove this user/group membership */
544 RemUser(u, j);
545 goto remed;
546 }
547 }
548 if (filled[u]) { /* track finished ones */
549 iscleaned:
550 cleaned[u]++;
551 nCleaned++;
552 }
553 remed:;
554 }
555 }
556
557 /* check the membership list of all users for correctness */
558 printf("Starting check of memberships\n");
559 glist = malloc(number * sizeof(afs_int32));
560 for (u = 0; u < number; u++) {
561 afs_int32 ui = users[u];
562 if (ui) {
563 int i;
564 int ng; /* number groups */
565 int over;
566 int (*proc)(struct ubik_client *, afs_int32, afs_int32, prlist *,
567 afs_int32 *);
568 prlist alist;
569
570 alist.prlist_len = 0;
571 alist.prlist_val = 0;
572 if (random() & 4) {
573 proc = ubik_PR_ListElements;
574 } else {
575 proc = ubik_PR_GetCPS;
576 }
577 code = (*proc)(pruclient, 0, ui, &alist, &over);
578 if (code) {
579 afs_com_err(whoami, code,
580 "getting membership list of (%di) using %s", ui,
581 (proc == ubik_PR_ListElements?"ListElements":"GetCPS"));
582 exit(24);
583 }
584 if (over) {
585 fprintf(stderr, "membership list for id %di too long\n", ui);
586 }
587 ng = 0;
588 for (i = 0; i < number; i++)
589 if (population[u * number + i])
590 glist[ng++] = groups[i];
591 qsort(glist, ng, sizeof(afs_int32), IdCmp);
592 if (ng != (alist.prlist_len - ((proc == ubik_PR_GetCPS) ? 3 : 0))) {
593 fprintf(stderr,
594 "Membership list for %di of unexpected length: was %d but expected %d\n",
595 ui, alist.prlist_len, ng);
596 exit(20);
597 }
598 /* all the extra entries for the CPS should be at the end. */
599 code = 0;
600 for (i = 0; i < ng; i++)
601 if (alist.prlist_val[i] != glist[i]) {
602 fprintf(stderr,
603 "membership for %di not correct: was %di but expected %di\n",
604 ui, alist.prlist_val[i], glist[i]);
605 code++;
606 }
607 if (code)
608 exit(21);
609 if (proc == ubik_PR_GetCPS) {
610 if ((alist.prlist_val[i /* =ng */ ] != AUTHUSERID) ||
611 (alist.prlist_val[++i] != ANYUSERID)
612 || (alist.prlist_val[++i] != ui)) {
613 fprintf(stderr, "CPS doesn't have extra entries\n");
614 exit(27);
615 }
616 }
617 if (alist.prlist_val)
618 free(alist.prlist_val);
619
620 /* User 0 is a member of all groups all of which should also be on
621 * the owner list of the caller or the ownerUser, although there
622 * may also be others. Check this. */
623 if (u == 0) {
624 prlist callerList;
625 prlist ownerList;
626 prlist lastGroupList;
627 int i, j, k, l;
628
629 if (ng != number) {
630 fprintf(stderr, "User 0 not a member of all groups\n");
631 exit(26);
632 }
633#define GETOWNED(xlist,xid) \
634 (xlist).prlist_val = 0; (xlist).prlist_len = 0; \
635 code = ubik_PR_ListOwned(pruclient, 0, (xid), &(xlist), &over); \
636 if (code) { \
637 afs_com_err (whoami, code, "getting owner list of (%di)", (xid)); \
638 exit (23); } \
639 if (over) \
640 { fprintf (stderr, "membership of id %di too long\n", (xid)); }
641
642 GETOWNED(callerList, callerId);
643 GETOWNED(ownerList, ownerUser);
644
645 /* look for every entry in glist, in all the owner lists */
646 for (i = j = k = l = 0; i < number; i++) {
647 while ((j < callerList.prlist_len)
648 && (callerList.prlist_val[j] < glist[i]))
649 j++;
650 while ((k < ownerList.prlist_len)
651 && (ownerList.prlist_val[k] < glist[i]))
652 k++;
653#define PRLISTCMP(l,i) \
654 (((l).prlist_len == 0) || (glist[i] != (l).prlist_val[(i)]))
655 if (PRLISTCMP(callerList, j) && PRLISTCMP(ownerList, k)) {
656 for (l = 0; l < number; l++) {
657 if (groups[l] == glist[i]) {
658 if ((groupOwners[l] != callerId)
659 && (groupOwners[l] != ownerUser)) {
660 GETOWNED(lastGroupList, groupOwners[l]);
661 if ((lastGroupList.prlist_len != 1)
662 || (lastGroupList.prlist_val[0] !=
663 glist[i])) {
664 fprintf(stderr,
665 "Group (%di) not on any owner list\n",
666 glist[i]);
667 exit(25);
668 }
669 }
670 goto foundLast;
671 }
672 }
673 fprintf(stderr, "unexpected group %di\n", glist[i]);
674 foundLast:;
675 }
676 }
677 if (callerList.prlist_val)
678 free(callerList.prlist_val);
679 if (ownerList.prlist_val)
680 free(ownerList.prlist_val);
681 if (lastGroupList.prlist_val)
682 free(lastGroupList.prlist_val);
683 }
684 }
685 }
686
687 /* cleanup by deleting all the users and groups */
688 printf("Starting deletion of users and groups\n");
689 for (i = 0; i < number; i++) {
690 DeleteRandomId(users);
691 DeleteRandomId(groups);
692 }
693
694 printf
695 ("Created/deleted %d/%d users and %d/%d groups; added %d and removed %d.\n",
696 nUsers, nUDels, nGroups, nGDels, nAdds, nRems);
697 return 0;
698}
699
700/* from ka_ConvertBytes included here to avoid circularity */
701/* Converts a byte string to ascii. Return the number of unconverted bytes. */
702
703static int
704ka_ConvertBytes(char *ascii, /* output buffer */
705 int alen, /* buffer length */
706 char bs[], /* byte string */
707 int bl) /* number of bytes */
708{
709 int i;
710 unsigned char c;
711
712 alen--; /* make room for termination */
713 for (i = 0; i < bl; i++) {
714 c = bs[i];
715 if (alen <= 0)
716 return bl - i;
717 if (isalnum(c) || ispunct(c))
718 (*ascii++ = c), alen--;
719 else {
720 if (alen <= 3)
721 return bl - i;
722 *ascii++ = '\\';
723 *ascii++ = (c >> 6) + '0';
724 *ascii++ = (c >> 3 & 7) + '0';
725 *ascii++ = (c & 7) + '0';
726 alen -= 4;
727 }
728 }
729 *ascii = 0; /* terminate string */
730 return 0;
731}
732
733/* This runs various tests on the server. It creates, then deletes, a bunch of
734 * users and groups, so it would be safest to run it on a test database.
735 *
736 * These are the things I check for:
737 * User names longer than PR_MAXNAMELEN - strlen(cellname).
738 * Group names longer than PR_MAXNAMELEN.
739 * User names containing all legal 8-bit ascii characters. This excludes
740 * only ':', '@', and '\n'.
741 * Group names as above, but at least one colon is required, and the owner
742 * must be correct.
743 */
744
745int
746TestPrServ(struct cmd_syndesc *as, void *arock)
747{
748 afs_int32 id;
749 char name[PR_MAXNAMELEN + 1];
750 char creator[PR_MAXNAMELEN]; /* our name */
751 struct prcheckentry ent;
752 afs_int32 code;
753 int i, j;
754 int maxLen = PR_MAXNAMELEN - 1 - strlen(lcell) - 1;
755
756 code = pr_Initialize(1, conf_dir, NULL);
757 if (code) {
758 afs_com_err(whoami, code, "initializing pruser");
759 exit(1);
760 }
761
762 for (i = 0; i < maxLen; i++)
763 name[i] = 'a';
764 name[i] = 'a'; /* too long a name... */
765 name[i + 1] = 0;
766 id = 0;
767 code = pr_CreateUser(name, &id);
768 if ((code != RXGEN_CC_MARSHAL) && (code != PRBADNAM)) {
769 afs_com_err(whoami, code, "succeeded creating %s", name);
770 exit(2);
771 }
772 name[i] = 0;
773 id = 0;
774 code = pr_CreateUser(name, &id);
775 if (code == PREXIST) {
776 fprintf(stderr, "group already exists, skipping\n");
777 pr_SNameToId(name, &id);
778 } else if (code) {
779 afs_com_err(whoami, code, "failed creating %s", name);
780 exit(3);
781 }
782 if ((code = pr_ListEntry(id, &ent))
783 || (code = pr_SIdToName(ent.creator, creator))) {
784 afs_com_err(whoami, code, "getting creator's name");
785 exit(5);
786 }
787 code = pr_DeleteByID(id);
788 if (code) {
789 afs_com_err(whoami, code, "deleting %s", name);
790 exit(6);
791 }
792 /* now make sure the illegal chars are detected */
793 {
794 char *illegalChars;
795 for (illegalChars = "@:\n"; *illegalChars; illegalChars++) {
796 name[10] = *illegalChars;
797 id = 0;
798 code = pr_CreateUser(name, &id);
799 if (code != PRBADNAM) {
800 afs_com_err(whoami, code, "succeeded creating %s", name);
801 exit(8);
802 }
803 }
804 }
805
806 for (i = 1; i <= 255;) { /* for all 8-bit ascii... */
807 j = 0; /* build a new name */
808 while ((j < maxLen) && (i <= 255)) {
809 if (!((i == ':') || (i == '@') || (i == '\n')))
810 name[j++] = i;
811 i++;
812 }
813 name[j] = 0; /* terminate string */
814 id = 0;
815 code = pr_CreateUser(name, &id);
816 if (code == PREXIST) {
817 fprintf(stderr, "user already exists, skipping\n");
818 pr_SNameToId(name, &id);
819 } else if (code) {
820 char ascii[BUFSIZ];
821 ka_ConvertBytes(ascii, sizeof(ascii), name, strlen(name));
822 afs_com_err(whoami, code, "failed creating %s", ascii);
823 exit(4);
824 }
825 code = pr_DeleteByID(id);
826 if (code) {
827 afs_com_err(whoami, code, "deleting %s", name);
828 exit(7);
829 }
830 }
831
832 /* now check group names */
833 strcpy(name, creator);
834 strcat(name, ":abcdefghijklmnopqrstuvwxyz");
835 name[0] = 1; /* bash the owner name */
836 id = 0;
837 code = pr_CreateGroup(name, creator, &id);
838 if (code != PRNOENT) { /* owner doesn't exist */
839 afs_com_err(whoami, code, "succeeded creating %s", name);
840 exit(9);
841 }
842 name[0] = creator[0]; /* fix owner */
843 /* Make sure the illegal chars are detected */
844 {
845 char *illegalChars;
846 for (illegalChars = ":@\n"; *illegalChars; illegalChars++) {
847 name[strlen(creator) + 10] = *illegalChars;
848 id = 0;
849 code = pr_CreateGroup(name, creator, &id);
850 if (code != PRBADNAM) {
851 afs_com_err(whoami, code, "succeeded creating %s", name);
852 exit(10);
853 }
854 }
855 }
856 for (i = 1; i <= 255;) { /* for all 8-bit ascii... */
857 j = strlen(creator) + 1; /* build a new name */
858 while ((j < PR_MAXNAMELEN - 1) && (i <= 255)) {
859 if (!((i == ':') || (i == '@') || (i == '\n')))
860 name[j++] = i;
861 i++;
862 }
863 name[j] = 0; /* terminate string */
864 id = 0;
865 code = pr_CreateGroup(name, creator, &id);
866 if (code == PREXIST) {
867 fprintf(stderr, "group already exists, skipping\n");
868 pr_SNameToId(name, &id);
869 } else if (code) {
870 char ascii[BUFSIZ];
871 ka_ConvertBytes(ascii, sizeof(ascii), name, strlen(name));
872 afs_com_err(whoami, code, "failed creating %s", ascii);
873 exit(4);
874 }
875 code = pr_DeleteByID(id);
876 if (code) {
877 afs_com_err(whoami, code, "deleting %s", name);
878 exit(7);
879 }
880 }
881
882 printf("All OK\n");
883 return 0;
884}
885
886static char tmp_conf_dir[128] = "";
887static char tmp_conf_file[128] = "";
888static char tmp_cell_file[128] = "";
889static char tmp_noauth_file[128] = "";
890
891static int
892MyAfterProc(struct cmd_syndesc *as, void *arock)
893{
894 if (strlen(tmp_conf_file))
895 unlink(tmp_conf_file);
896 if (strlen(tmp_cell_file))
897 unlink(tmp_cell_file);
898 if (strlen(tmp_noauth_file))
899 unlink(tmp_noauth_file);
900 if (strlen(tmp_conf_dir))
901 rmdir(tmp_conf_dir);
902 return 0;
903}
904
905static int
906MyBeforeProc(struct cmd_syndesc *as, void *arock)
907{
908 afs_int32 code;
909 int i;
910 char *cdir = 0;
911 int noAuth = 0;
912 struct cmd_item *serverList = 0;
913 struct afsconf_dir *local_conf = 0; /* so we can default stuff nicely */
914 struct afsconf_cell cellinfo;
915
916 if (as->parms[12].items) { /* if conf dir specified */
917 cdir = as->parms[12].items->data;
918 if (as->parms[13].items || as->parms[14].items || as->parms[15].items) {
919 printf("Can't specify conf dir and other cell parameters\n");
920 return AFSCONF_SYNTAX;
921 }
922 }
923
924 /* if we need to default cell name or cell servers, get local conf info */
925
926 if (!(local_conf = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH))
927 && !(local_conf = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH))) {
928 printf("** Can't local configuration!\n");
929 return AFSCONF_NOCELL;
930 }
931
932 if (as->parms[13].items) { /* if cell name specified */
933 lcstring(lcell, as->parms[13].items->data, sizeof(lcell));
934 code = afsconf_GetCellInfo(local_conf, lcell, 0, &cellinfo);
935 if (code == 0)
936 strncpy(lcell, cellinfo.name, sizeof(lcell));
937 } else {
938 code = afsconf_GetLocalCell(local_conf, lcell, sizeof(lcell));
939 if (code)
940 return code;
941 }
942
943 if (as->parms[14].items) { /* noauth flag */
944 noAuth = 1;
945 }
946
947 if (as->parms[15].items) { /* servers list */
948 serverList = as->parms[15].items;
949 for (i = 0; serverList; i++, serverList = serverList->next) {
950 struct hostent *th;
951 if (i >= MAXHOSTSPERCELL)
952 return AFSCONF_FULL;
953 strncpy(cellinfo.hostName[i], serverList->data, MAXHOSTCHARS);
954 th = gethostbyname(cellinfo.hostName[i]);
955 if (!th)
956 return UBADHOST;
957 memcpy(&cellinfo.hostAddr[i].sin_addr, th->h_addr,
958 sizeof(afs_int32));
959 cellinfo.hostAddr[i].sin_family = AF_INET;
960 cellinfo.hostAddr[i].sin_port = 0;
961#ifdef STRUCT_SOCKADDR_HAS_SA_LEN
962 cellinfo.hostAddr[i].sin_len = sizeof(struct sockaddr_in);
963#endif
964 }
965 cellinfo.numServers = i;
966 strcpy(cellinfo.name, lcell);
967 } else {
968 code = afsconf_GetCellInfo(local_conf, lcell, 0, &cellinfo);
969 if (code)
970 return code;
971 }
972
973 if (local_conf)
974 afsconf_Close(local_conf);
975
976 if (cdir == 0) {
977 FILE *f;
978
979 sprintf(tmp_conf_dir, "%s/afsconf.%lu", gettmpdir(),
980 (unsigned long)getpid());
981 code = mkdir(tmp_conf_dir, 0777);
982 if ((code < 0) && (errno != EEXIST)) {
983 afs_com_err(whoami, errno, "can't create temporary afsconf dir: %s",
984 cdir);
985 return errno;
986 }
987
988 strcompose(tmp_conf_file, 128, tmp_conf_dir, "/",
989 AFSDIR_CELLSERVDB_FILE, (char *)NULL);
990 f = fopen(tmp_conf_file, "w");
991 if (f == 0) {
992 cantcreate:
993 afs_com_err(whoami, errno, "can't create conf file %s",
994 tmp_conf_file);
995 return errno;
996 }
997 fprintf(f, ">%s\n", lcell);
998 for (i = 0; i < cellinfo.numServers; i++) {
999 unsigned char *tp =
1000 (unsigned char *)&cellinfo.hostAddr[i].sin_addr;
1001 fprintf(f, "%d.%d.%d.%d\t#%s\n", tp[0], tp[1], tp[2], tp[3],
1002 cellinfo.hostName[i]);
1003 }
1004 if (fclose(f) == EOF) {
1005 cantclose:
1006 afs_com_err(whoami, errno, "can't write to conf file %s",
1007 tmp_conf_file);
1008 return errno;
1009 }
1010
1011 strcompose(tmp_cell_file, 128, tmp_conf_dir, "/",
1012 AFSDIR_THISCELL_FILE, (char *)NULL);
1013 f = fopen(tmp_cell_file, "w");
1014 if (f == 0)
1015 goto cantcreate;
1016 fprintf(f, "%s", lcell);
1017 if (fclose(f) == EOF)
1018 goto cantclose;
1019
1020 strcompose(tmp_noauth_file, 128, tmp_conf_dir, "/",
1021 AFSDIR_NOAUTH_FILE, (char *)NULL);
1022 if (noAuth) {
1023 code = creat(tmp_noauth_file, 0777);
1024 if (code && (errno != EEXIST))
1025 return errno;
1026 } else { /* make sure file doesn't exist */
1027 code = unlink(tmp_noauth_file);
1028 if (code && (errno != ENOENT))
1029 return errno;
1030 }
1031 }
1032
1033 strncpy(conf_dir, tmp_conf_dir, sizeof(conf_dir));
1034 conf = afsconf_Open(conf_dir);
1035 if (conf == 0)
1036 return AFSCONF_NOTFOUND;
1037 return 0;
1038}
1039
1040static void
1041add_std_args(struct cmd_syndesc *ts)
1042{
1043 cmd_Seek(ts, 12);
1044 cmd_AddParm(ts, "-confdir", CMD_SINGLE, CMD_OPTIONAL,
1045 "AFS Conf dir pathname");
1046 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "Cell name");
1047 cmd_AddParm(ts, "-noauth", CMD_FLAG, CMD_OPTIONAL, "Don't authenticate");
1048 cmd_AddParm(ts, "-servers", CMD_LIST, CMD_OPTIONAL, "Server config");
1049}
1050
1051int
1052osi_audit(void)
1053{
1054/* OK, this REALLY sucks bigtime, but I can't tell who is calling
1055 * afsconf_CheckAuth easily, and only *SERVERS* should be calling osi_audit
1056 * anyway. It's gonna give somebody fits to debug, I know, I know.
1057 */
1058 return 0;
1059}
1060
1061#include "AFS_component_version_number.c"
1062
1063int
1064main(int argc, char *argv[])
1065{
1066 afs_int32 code;
1067 struct cmd_syndesc *ts; /* ptr to parsed command line syntax */
1068
1069 whoami = argv[0];
1070 initialize_CMD_error_table();
1071 initialize_ACFG_error_table();
1072 initialize_KTC_error_table();
1073 initialize_U_error_table();
1074 initialize_PT_error_table();
1075 initialize_RXK_error_table();
1076
1077#ifdef AFS_NT40_ENV
1078 /* initialize winsock */
1079 if (afs_winsockInit() < 0) {
1080 fprintf(stderr, "%s: couldn't initialize winsock. \n", whoami);
1081 exit(1);
1082 }
1083#endif
1084
1085 cmd_SetBeforeProc(MyBeforeProc, NULL);
1086 cmd_SetAfterProc(MyAfterProc, NULL);
1087
1088 ts = cmd_CreateSyntax("usedIds", ListUsedIds, NULL, 0,
1089 "Find used (or unused) user (or group) ids");
1090 cmd_AddParm(ts, "-startId", CMD_SINGLE, CMD_OPTIONAL,
1091 "id to start checking");
1092 cmd_AddParm(ts, "-number", CMD_SINGLE, CMD_OPTIONAL,
1093 "number of ids to check");
1094 cmd_AddParm(ts, "-unused", CMD_FLAG, CMD_OPTIONAL, "print unused ids");
1095 add_std_args(ts);
1096
1097 ts = cmd_CreateSyntax("initcmd", TestPrServ, NULL, 0, "test the prserver");
1098 add_std_args(ts);
1099
1100 ts = cmd_CreateSyntax("testmanymembers", TestManyMembers, NULL, 0,
1101 "test creating users and groups w/ many members");
1102 cmd_AddParm(ts, "-number", CMD_SINGLE, 0,
1103 "number of users/groups to create");
1104 cmd_AddParm(ts, "-dropoff", CMD_SINGLE, CMD_OPTIONAL,
1105 "precentage for exponential dropoff");
1106 cmd_AddParm(ts, "-prefix", CMD_SINGLE, CMD_OPTIONAL, "naming prefix");
1107 cmd_AddParm(ts, "-long", CMD_FLAG, CMD_OPTIONAL, "show progress");
1108 cmd_AddParm(ts, "-seed", CMD_SINGLE, CMD_OPTIONAL, "random number seed");
1109 add_std_args(ts);
1110 cmd_CreateAlias(ts, "mm");
1111
1112
1113 code = cmd_Dispatch(argc, argv);
1114 if (code)
1115 afs_com_err(whoami, code, "calling cmd_Dispatch");
1116 exit(code);
1117}