Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / ptserver / pts.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 #include <roken.h>
14
15 #include <ctype.h>
16
17 #ifdef AFS_NT40_ENV
18 #include <WINNT/afsevent.h>
19 #include <WINNT/afsreg.h>
20 #endif
21
22 #include <afs/cellconfig.h>
23 #include <afs/afsutil.h>
24 #include <afs/com_err.h>
25 #include <afs/cmd.h>
26 #include <rx/rx.h>
27 #include <rx/xdr.h>
28
29 #include "ptclient.h"
30 #include "ptuser.h"
31 #include "pterror.h"
32 #include "ptprototypes.h"
33
34 char *whoami;
35 int force = 0;
36
37 static int finished;
38 static FILE *source;
39 extern struct ubik_client *pruclient;
40
41 struct sourcestack {
42 struct sourcestack *s_next;
43 FILE *s_file;
44 } *shead;
45
46 struct authstate {
47 int sec;
48 const char *confdir;
49 char cell[MAXCELLCHARS];
50 };
51
52 static int CleanUp(struct cmd_syndesc *as, void *arock);
53
54 static int
55 pts_Interactive(struct cmd_syndesc *as, void *arock)
56 {
57 source = stdin;
58 finished = 0;
59 return 0;
60 }
61
62 static int
63 pts_Quit(struct cmd_syndesc *as, void *arock)
64 {
65 finished = 1;
66 return 0;
67 }
68
69 static int
70 pts_Source(struct cmd_syndesc *as, void *arock)
71 {
72 FILE *fd;
73 struct sourcestack *sp;
74
75 finished = 0;
76 if (!as->parms[0].items) {
77 /* can this happen? */
78 return 1;
79 }
80 fd = fopen(as->parms[0].items->data, "r");
81 if (!fd) {
82 perror(as->parms[0].items->data);
83 return errno;
84 }
85 sp = malloc(sizeof *sp);
86 if (!sp) {
87 return errno ? errno : ENOMEM;
88 } else {
89 sp->s_next = shead;
90 sp->s_file = source;
91 shead = sp;
92 source = fd;
93 }
94 return 0;
95 }
96
97 static int
98 pts_Sleep(struct cmd_syndesc *as, void *arock)
99 {
100 int delay;
101 if (!as->parms[0].items) {
102 /* can this happen? */
103 return 1;
104 }
105 delay = atoi(as->parms[0].items->data);
106 #ifdef AFS_PTHREAD_ENV
107 sleep(delay);
108 #else
109 IOMGR_Sleep(delay);
110 #endif
111 return 0;
112 }
113
114 static int
115 popsource(void)
116 {
117 struct sourcestack *sp;
118 if (!(sp = shead))
119 return 0;
120 if (source != stdin)
121 fclose(source);
122 source = sp->s_file;
123 shead = sp->s_next;
124 free(sp);
125 return 1;
126 }
127
128 int
129 osi_audit(void)
130 {
131 /* OK, this REALLY sucks bigtime, but I can't tell who is calling
132 * afsconf_CheckAuth easily, and only *SERVERS* should be calling osi_audit
133 * anyway. It's gonna give somebody fits to debug, I know, I know.
134 */
135 return 0;
136 }
137
138 #ifdef AFS_NT40_ENV
139 static DWORD
140 win32_enableCrypt(void)
141 {
142 HKEY parmKey;
143 DWORD dummyLen;
144 DWORD cryptall = 0;
145 DWORD code;
146
147 /* Look up configuration parameters in Registry */
148 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
149 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
150 if (code != ERROR_SUCCESS) {
151 dummyLen = sizeof(cryptall);
152 RegQueryValueEx(parmKey, "SecurityLevel", NULL, NULL,
153 (BYTE *) &cryptall, &dummyLen);
154 }
155 RegCloseKey (parmKey);
156
157 return cryptall;
158 }
159 #endif /* AFS_NT40_ENV */
160
161 static int
162 GetGlobals(struct cmd_syndesc *as, void *arock)
163 {
164 struct authstate *state = (struct authstate *) arock;
165 afs_int32 code;
166 char *cell = NULL;
167 afs_int32 sec;
168 int changed = 0;
169 const char* confdir;
170
171 whoami = as->a0name;
172
173 if (!strcmp(as->name, "help"))
174 return 0;
175
176 if (*state->cell) {
177 cell = state->cell;
178 }
179 sec = state->sec;
180
181 if (state->confdir == NULL) {
182 changed = 1;
183 }
184
185 if (as->parms[16].items) {
186 changed = 1;
187 cell = as->parms[16].items->data;
188 }
189 if (as->parms[17].items) { /* -noauth */
190 changed = 1;
191 sec = 0;
192 }
193 if (as->parms[20].items) { /* -localauth */
194 changed = 1;
195 sec = 2;
196 }
197 if (as->parms[21].items) { /* -auth */
198 changed = 1;
199 sec = 1;
200 }
201 if (as->parms[22].items /* -encrypt */
202 #ifdef AFS_NT40_ENV
203 || win32_enableCrypt()
204 #endif /* AFS_NT40_ENV */
205 ) {
206 changed = 1;
207 sec = 3;
208 }
209 if (as->parms[18].items || as->parms[20].items) { /* -test, -localauth */
210 changed = 1;
211 confdir = AFSDIR_SERVER_ETC_DIRPATH;
212 } else {
213 if (sec == 2)
214 confdir = AFSDIR_SERVER_ETC_DIRPATH;
215 else
216 confdir = AFSDIR_CLIENT_ETC_DIRPATH;
217 }
218
219 if (as->parms[23].items) { /* -config */
220 changed = 1;
221 confdir = as->parms[23].items->data;
222 }
223
224 if (changed) {
225 CleanUp(as, arock);
226 code = pr_Initialize(sec, confdir, cell);
227 } else {
228 code = 0;
229 }
230 if (code) {
231 afs_com_err(whoami, code, "while initializing");
232 return code;
233 }
234 state->sec = sec;
235 state->confdir = confdir;
236 if (cell && cell != state->cell)
237 strncpy(state->cell, cell, MAXCELLCHARS-1);
238
239 force = 0;
240 if (as->parms[19].items)
241 force = 1;
242
243 return code;
244 }
245
246 static int
247 CleanUp(struct cmd_syndesc *as, void *arock)
248 {
249 if (as && !strcmp(as->name, "help"))
250 return 0;
251 if (pruclient) {
252 /* Need to shutdown the ubik_client & other connections */
253 pr_End();
254 rx_Finalize();
255 }
256 return 0;
257 }
258
259 static int
260 CreateGroup(struct cmd_syndesc *as, void *arock)
261 {
262 afs_int32 code;
263 afs_int32 id;
264 char *owner;
265 struct cmd_item *namei;
266 struct cmd_item *idi;
267
268 namei = as->parms[0].items;
269 idi = as->parms[2].items;
270 if (as->parms[1].items)
271 owner = as->parms[1].items->data;
272 else
273 owner = NULL;
274
275 while (namei) {
276 if (idi) {
277 code = util_GetInt32(idi->data, &id);
278 if (code) {
279 afs_com_err(whoami, code, "because group id was: '%s'",
280 idi->data);
281 return code;
282 }
283 if (id == 0) {
284 fprintf(stderr, "0 isn't a valid group id; aborting\n");
285 return EINVAL;
286 }
287 if (id > 0) {
288 code = PRBADARG;
289 afs_com_err(whoami, code, "because group id %d was not negative",
290 id);
291 return code;
292 }
293
294 idi = idi->next;
295 } else
296 id = 0;
297
298 code = pr_CreateGroup(namei->data, owner, &id);
299 if (code) {
300 if (owner || id)
301 afs_com_err(whoami, code,
302 "; unable to create group %s with id %d%s%s%s%s",
303 namei->data, id, owner ? " owned by '" : "",
304 owner ? owner : "", owner ? "'" : "",
305 (force ? " (ignored)" : ""));
306 else
307 afs_com_err(whoami, code, "; unable to create group %s %s",
308 namei->data, (force ? "(ignored)" : ""));
309 if (!force)
310 return code;
311 }
312 printf("group %s has id %d\n", namei->data, id);
313 namei = namei->next;
314 }
315 return 0;
316 }
317
318 static int
319 CreateUser(struct cmd_syndesc *as, void *arock)
320 {
321 afs_int32 code;
322 afs_int32 id;
323 struct cmd_item *namei;
324 struct cmd_item *idi;
325
326 namei = as->parms[0].items;
327 idi = as->parms[1].items;
328
329 while (namei) {
330 if (idi) {
331 code = util_GetInt32(idi->data, &id);
332 if (code) {
333 afs_com_err(whoami, code, "because id was: '%s'", idi->data);
334 return code;
335 }
336 if (id == 0) {
337 fprintf(stderr, "0 isn't a valid user id; aborting\n");
338 return EINVAL;
339 }
340 if (id < 0) {
341 code = PRBADARG;
342 afs_com_err(whoami, code, "because user id %d was not positive",
343 id);
344 return code;
345 }
346 idi = idi->next;
347 } else
348 id = 0;
349
350 code = pr_CreateUser(namei->data, &id);
351 if (code) {
352 if (id)
353 afs_com_err(whoami, code,
354 "; unable to create user %s with id %d %s",
355 namei->data, id, (force ? "(ignored)" : ""));
356 else
357 afs_com_err(whoami, code, "; unable to create user %s %s",
358 namei->data, (force ? "(ignored)" : ""));
359 if (!force)
360 return code;
361 }
362 printf("User %s has id %d\n", namei->data, id);
363 namei = namei->next;
364 }
365 return 0;
366 }
367
368
369 #ifdef notdef
370 static int
371 GetNameOrId(struct cmd_syndesc *as, struct idlist *lids, struct namelist *lnames)
372 {
373 afs_int32 code = 0;
374 int n = 0;
375 struct cmd_item *i;
376 int goodCount;
377
378 if (!(as->parms[0].items || as->parms[1].items)) {
379 afs_com_err(whoami, 0, "must specify either a name or an id.");
380 return -1;
381 }
382 if (as->parms[0].items && as->parms[1].items) {
383 afs_com_err(whoami, 0, "can't specify both a name and id.");
384 return -1;
385 }
386
387 goodCount = 0;
388 lids->idlist_len = 0;
389 lids->idlist_val = 0;
390
391 if (as->parms[0].items) { /* name */
392 struct namelist names; /* local copy, if not ret. names */
393 struct namelist *nl;
394
395 names.namelist_val = 0; /* so it gets freed later if needed */
396 if (lnames)
397 nl = lnames;
398 else
399 nl = &names;
400
401 n = 0; /* count names */
402 for (i = as->parms[0].items; i; i = i->next)
403 n++;
404 nl->namelist_val = malloc(n * PR_MAXNAMELEN);
405 nl->namelist_len = n;
406 n = 0;
407 for (i = as->parms[0].items; i; i = i->next)
408 strncpy(nl->namelist_val[n++], i->data, PR_MAXNAMELEN);
409
410 code = pr_NameToId(nl, lids);
411 if (code)
412 afs_com_err(whoami, code, "so couldn't look up names");
413 else {
414 for (n = 0; n < lids->idlist_len; n++) {
415 if ((lids->idlist_val[n] == ANONYMOUSID)) {
416 afs_com_err(whoami, PRNOENT, "so couldn't look up id for %s",
417 nl->namelist_val[n]);
418 } else
419 goodCount++;
420 }
421 /* treat things as working if any of the lookups worked */
422 if (goodCount == 0)
423 code = PRNOENT;
424 }
425
426 if (names.namelist_val)
427 free(names.namelist_val);
428 } else if (as->parms[1].items) { /* id */
429 n = 0;
430 for (i = as->parms[1].items; i; i = i->next)
431 n++;
432 lids->idlist_val = malloc(n * sizeof(afs_int32));
433 lids->idlist_len = n;
434 n = 0;
435 for (i = as->parms[1].items; i; i = i->next) {
436 code = util_GetInt32(i->data, &lids->idlist_val[n]);
437 if (code)
438 afs_com_err(whoami, code =
439 PRNOENT, "because a bogus id '%s' was specified",
440 i->data);
441 n++;
442 }
443 if (!code && lnames) {
444 lnames->namelist_val = 0;
445 lnames->namelist_len = 0;
446 code = pr_IdToName(lids, lnames);
447 if (code)
448 afs_com_err(whoami, code, "translating ids");
449 }
450 }
451 if (code) {
452 if (lids->idlist_val)
453 free(lids->idlist_val);
454 return -1;
455 }
456 return 0;
457 }
458 #endif
459
460
461 static int
462 GetNameOrId(struct cmd_syndesc *as, struct idlist *lids,
463 struct namelist *lnames)
464 {
465 afs_int32 code = 0;
466 int n = 0, nd = 0, nm = 0, id, x;
467 struct cmd_item *i;
468 struct namelist names, tnames; /* local copy, if not ret. names */
469 struct idlist ids, tids; /* local copy, if not ret. ids */
470 int goodCount = 0;
471
472 /* Initialise our outputs */
473 memset(lids, 0, sizeof(struct idlist));
474 if (lnames)
475 memset(lnames, 0, sizeof(struct namelist));
476
477 for (i = as->parms[0].items; i; i = i->next)
478 n++;
479
480 /* Nothing to do, so bail */
481 if (n == 0)
482 return 0;
483
484 lids->idlist_val = malloc(n * sizeof(afs_int32));
485 lids->idlist_len = n;
486 ids.idlist_val = malloc(n * sizeof(afs_int32));
487 ids.idlist_len = n;
488 names.namelist_val = malloc(n * PR_MAXNAMELEN);
489 names.namelist_len = n;
490 if (lnames) {
491 lnames->namelist_val = malloc(n * PR_MAXNAMELEN);
492 lnames->namelist_len = 0;
493 }
494 for (i = as->parms[0].items; i; i = i->next) {
495 tnames.namelist_val = malloc(PR_MAXNAMELEN);
496 strncpy(tnames.namelist_val[0], i->data, PR_MAXNAMELEN);
497 tnames.namelist_len = 1;
498 tids.idlist_len = 0;
499 tids.idlist_val = 0;
500 code = pr_NameToId(&tnames, &tids);
501 if ((!code && (tids.idlist_val[0] != 32766))
502 || (code = util_GetInt32(i->data, &id))) {
503 /* Assume it's a name instead */
504 strncpy(names.namelist_val[nm++], i->data, PR_MAXNAMELEN);
505 } else {
506 ids.idlist_val[nd++] = id;
507 }
508 free(tnames.namelist_val);
509 }
510 names.namelist_len = nm;
511 ids.idlist_len = nd;
512 tids.idlist_len = nd = nm = 0;
513 tids.idlist_val = 0;
514 code = pr_NameToId(&names, &tids);
515 if (code)
516 afs_com_err(whoami, code, "so couldn't look up names");
517 else {
518 for (n = 0; n < tids.idlist_len; n++) {
519 if (tids.idlist_val[n] == ANONYMOUSID) {
520 afs_com_err(whoami, PRNOENT, "so couldn't look up id for %s",
521 names.namelist_val[n]);
522 } else
523 goodCount++;
524 lids->idlist_val[nd] = tids.idlist_val[n];
525 if (lnames)
526 strcpy(lnames->namelist_val[nd], names.namelist_val[n]);
527 nd++;
528 }
529 }
530 for (x = 0; x < ids.idlist_len; x++) {
531 lids->idlist_val[nd + x] = ids.idlist_val[x];
532 }
533 lids->idlist_len = nd + x;
534 if (!code && lnames) {
535 tnames.namelist_val = 0;
536 tnames.namelist_len = 0;
537 code = pr_IdToName(&ids, &tnames);
538 if (code)
539 afs_com_err(whoami, code, "translating ids");
540 else {
541 goodCount++;
542 if (lnames) {
543 for (x = 0; x < ids.idlist_len; x++)
544 strcpy(lnames->namelist_val[nd + x], tnames.namelist_val[x]);
545 lnames->namelist_len = nd + x;
546 }
547 }
548 }
549 /* treat things as working if any of the lookups worked */
550 if (goodCount == 0)
551 code = PRNOENT;
552 if (code) {
553 if (lids->idlist_val)
554 free(lids->idlist_val);
555 return -1;
556 }
557 return 0;
558 }
559
560
561 static int
562 AddToGroup(struct cmd_syndesc *as, void *arock)
563 {
564 afs_int32 code;
565 struct cmd_item *u, *g;
566
567 for (u = as->parms[0].items; u; u = u->next) {
568 for (g = as->parms[1].items; g; g = g->next) {
569 code = pr_AddToGroup(u->data, g->data);
570 if (code) {
571 afs_com_err(whoami, code,
572 "; unable to add user %s to group %s %s", u->data,
573 g->data, (force ? "(ignored)" : ""));
574 if (!force)
575 return code;
576 }
577 }
578 }
579 return 0;
580 }
581
582 static int
583 RemoveFromGroup(struct cmd_syndesc *as, void *arock)
584 {
585 afs_int32 code;
586 struct cmd_item *u, *g;
587
588 for (u = as->parms[0].items; u; u = u->next) {
589 for (g = as->parms[1].items; g; g = g->next) {
590 code = pr_RemoveUserFromGroup(u->data, g->data);
591 if (code) {
592 afs_com_err(whoami, code,
593 "; unable to remove user %s from group %s %s",
594 u->data, g->data, (force ? "(ignored)" : ""));
595 if (!force)
596 return code;
597 }
598 }
599 }
600 return 0;
601 }
602
603 static int
604 ListMembership(struct cmd_syndesc *as, void *arock)
605 {
606 afs_int32 code;
607 idlist ids;
608 namelist names;
609 int i;
610 namelist list;
611 int j;
612
613 if (GetNameOrId(as, &ids, &names))
614 return PRBADARG;
615
616 for (i = 0; i < ids.idlist_len; i++) {
617 afs_int32 id = ids.idlist_val[i];
618 char *name = names.namelist_val[i];
619
620 if (id == ANONYMOUSID)
621 continue; /* bad entry */
622
623 list.namelist_val = 0;
624 list.namelist_len = 0;
625 if (as->parms[2].items) { /* -expandgroups */
626 code = pr_IDListExpandedMembers(id, &list);
627 if (!code)
628 printf("Expanded ");
629 } else {
630 code = pr_IDListMembers(id, &list);
631 }
632 if (code) {
633 afs_com_err(whoami, code, "; unable to get membership of %s (id: %d)",
634 name, id);
635 continue;
636 }
637 if (id < 0)
638 printf("Members of %s (id: %d) are:\n", name, id);
639 else
640 printf("Groups %s (id: %d) is a member of:\n", name, id);
641
642 for (j = 0; j < list.namelist_len; j++)
643 printf(" %s\n", list.namelist_val[j]);
644 if (list.namelist_val)
645 free(list.namelist_val);
646 if (as->parms[1].items && id < 0) { /* -supergroups */
647 list.namelist_val = 0;
648 list.namelist_len = 0;
649 code = pr_ListSuperGroups(ids.idlist_val[i], &list);
650 if (code == RXGEN_OPCODE) {
651 continue; /* server does not support supergroups */
652 } else if (code != 0) {
653 afs_com_err(whoami, code,
654 "; unable to get supergroups of %s (id: %d)",
655 name, id);
656 continue;
657 }
658 printf("Groups %s (id: %d) is a member of:\n", name, id);
659 for (j = 0; j < list.namelist_len; j++)
660 printf(" %s\n", list.namelist_val[j]);
661 if (list.namelist_val)
662 free(list.namelist_val);
663 }
664 }
665 if (ids.idlist_val)
666 free(ids.idlist_val);
667 if (names.namelist_val)
668 free(names.namelist_val);
669 return 0;
670 }
671
672 static int
673 Delete(struct cmd_syndesc *as, void *arock)
674 {
675 afs_int32 code;
676 idlist ids;
677 namelist names;
678 int i;
679
680 if (GetNameOrId(as, &ids, &names))
681 return PRBADARG;
682
683 for (i = 0; i < ids.idlist_len; i++) {
684 afs_int32 id = ids.idlist_val[i];
685 char *name = names.namelist_val[i];
686
687 if (id == ANONYMOUSID)
688 continue;
689
690 code = pr_DeleteByID(id);
691 if (code) {
692 afs_com_err(whoami, code, "deleting %s (id: %d) %s", name, id,
693 (force ? "(ignored)" : ""));
694 if (!force)
695 return code;
696 }
697 }
698 if (ids.idlist_val)
699 free(ids.idlist_val);
700 if (names.namelist_val)
701 free(names.namelist_val);
702 return 0;
703 }
704
705 /* access bit translation info */
706
707 char *flags_upcase = "SOMA "; /* legal all access values */
708 char *flags_dncase = "s mar"; /* legal member acces values */
709 int flags_shift[5] = { 2, 1, 2, 2, 1 }; /* bits for each */
710
711 static int
712 CheckEntry(struct cmd_syndesc *as, void *arock)
713 {
714 afs_int32 code;
715 afs_int32 rcode = 1;
716 int i, flag = 0, admin = 0;
717 namelist lnames, names;
718 idlist ids;
719 idlist lids;
720 struct prcheckentry aentry;
721
722 if (GetNameOrId(as, &ids, &names))
723 return PRBADARG;
724
725 lids.idlist_len = 2;
726 lids.idlist_val = malloc(sizeof(afs_int32) * 2);
727 lnames.namelist_len = 0;
728 lnames.namelist_val = 0;
729
730 for (i = 0; i < ids.idlist_len; i++) {
731 afs_int32 id = ids.idlist_val[i];
732
733 if (id == ANONYMOUSID)
734 continue;
735
736 rcode = 0;
737 code = pr_ListEntry(id, &aentry);
738 if (code) {
739 rcode = code;
740 afs_com_err(whoami, code, "; unable to find entry for (id: %d)", id);
741 continue;
742 }
743
744 lids.idlist_val[0] = aentry.owner;
745 lids.idlist_val[1] = aentry.creator;
746 code = pr_IdToName(&lids, &lnames);
747 if (code) {
748 rcode = code;
749 afs_com_err(whoami, code,
750 "translating owner (%d) and creator (%d) ids",
751 aentry.owner, aentry.creator);
752 continue;
753 }
754 printf("Name: %s, id: %d, owner: %s, creator: %s,\n", aentry.name,
755 aentry.id, lnames.namelist_val[0], lnames.namelist_val[1]);
756 printf(" membership: %d", aentry.count);
757 {
758 char access[6];
759 afs_int32 flags = aentry.flags;
760 int j, s, new;
761 char c;
762 access[5] = 0; /* null-terminate the string */
763 for (j = 4; j >= 0; j--) {
764 s = flags_shift[j];
765 if (s == 1)
766 new = flags & 1;
767 else
768 new = flags & 3;
769 if (new == 0)
770 c = '-';
771 else if (new == 1) {
772 c = flags_dncase[j];
773 if (c == ' ')
774 c = flags_upcase[j];
775 } else if (new == 2)
776 c = flags_upcase[j];
777 else
778 c = 'X';
779 access[j] = c;
780 flags >>= s;
781 }
782 printf(", flags: %s", access);
783 }
784 if (aentry.id == SYSADMINID)
785 admin = 1;
786 else if (!pr_IsAMemberOf(aentry.name, "system:administrators", &flag)) {
787 if (flag)
788 admin = 1;
789 }
790 if (admin)
791 printf(", group quota: unlimited");
792 else
793 printf(", group quota: %d", aentry.ngroups);
794 printf(".\n");
795 }
796
797 if (lnames.namelist_val)
798 free(lnames.namelist_val);
799 if (lids.idlist_val)
800 free(lids.idlist_val);
801 if (ids.idlist_val)
802 free(ids.idlist_val);
803
804 return (rcode);
805 }
806
807 static int
808 ListEntries(struct cmd_syndesc *as, void *arock)
809 {
810 afs_int32 code = 0;
811 afs_int32 flag, startindex, nentries, nextstartindex;
812 struct prlistentries *entriesp = 0, *e;
813 afs_int32 i;
814
815 flag = PRUSERS;
816 if (as->parms[1].items)
817 flag = PRGROUPS;
818 if (as->parms[0].items)
819 flag |= PRUSERS;
820
821 printf("Name ID Owner Creator\n");
822 for (startindex = 0; startindex != -1; startindex = nextstartindex) {
823 code =
824 pr_ListEntries(flag, startindex, &nentries, &entriesp,
825 &nextstartindex);
826 if (code) {
827 afs_com_err(whoami, code, "; unable to list entries");
828 if (entriesp)
829 free(entriesp);
830 break;
831 }
832
833 /* Now display each of the entries we read */
834 for (i = 0, e = entriesp; i < nentries; i++, e++) {
835 printf("%-25s %6d %6d %7d \n", e->name, e->id, e->owner,
836 e->creator);
837 }
838 if (entriesp)
839 free(entriesp);
840 }
841 return code;
842 }
843
844 static int
845 ChownGroup(struct cmd_syndesc *as, void *arock)
846 {
847 afs_int32 code;
848 char *name;
849 char *owner;
850
851 name = as->parms[0].items->data;
852 owner = as->parms[1].items->data;
853 code = pr_ChangeEntry(name, "", 0, owner);
854 if (code)
855 afs_com_err(whoami, code, "; unable to change owner of %s to %s", name,
856 owner);
857 return code;
858 }
859
860 static int
861 ChangeName(struct cmd_syndesc *as, void *arock)
862 {
863 afs_int32 code;
864 char *oldname;
865 char *newname;
866
867 oldname = as->parms[0].items->data;
868 newname = as->parms[1].items->data;
869 code = pr_ChangeEntry(oldname, newname, 0, "");
870 if (code)
871 afs_com_err(whoami, code, "; unable to change name of %s to %s", oldname,
872 newname);
873 return code;
874 }
875
876 static int
877 ListMax(struct cmd_syndesc *as, void *arock)
878 {
879 afs_int32 code;
880 afs_int32 maxUser, maxGroup;
881
882 code = pr_ListMaxUserId(&maxUser);
883 if (code)
884 afs_com_err(whoami, code, "getting maximum user id");
885 else {
886 code = pr_ListMaxGroupId(&maxGroup);
887 if (code)
888 afs_com_err(whoami, code, "getting maximum group id");
889 else {
890 printf("Max user id is %d and max group id is %d.\n", maxUser,
891 maxGroup);
892 }
893 }
894 return code;
895 }
896
897 static int
898 SetMaxCommand(struct cmd_syndesc *as, void *arock)
899 {
900 afs_int32 code;
901 afs_int32 maxid;
902
903 code = 0;
904 if (as->parms[1].items) {
905 /* set user max */
906 code = util_GetInt32(as->parms[1].items->data, &maxid);
907 if (code) {
908 afs_com_err(whoami, code, "because id was: '%s'",
909 as->parms[1].items->data);
910 } else {
911 code = pr_SetMaxUserId(maxid);
912 if (code)
913 afs_com_err(whoami, code, "so couldn't set Max User Id to %d",
914 maxid);
915 }
916 }
917 if (as->parms[0].items) {
918 /* set group max */
919 code = util_GetInt32(as->parms[0].items->data, &maxid);
920 if (code) {
921 afs_com_err(whoami, code, "because id was: '%s'",
922 as->parms[0].items->data);
923 } else {
924 code = pr_SetMaxGroupId(maxid);
925 if (code)
926 afs_com_err(whoami, code, "so couldn't set Max Group Id to %d",
927 maxid);
928 }
929 }
930 if (!as->parms[0].items && !as->parms[1].items) {
931 code = PRBADARG;
932 fprintf(stderr, "Must specify at least one of group or user.\n");
933 }
934 return code;
935 }
936
937 static int
938 SetFields(struct cmd_syndesc *as, void *arock)
939 {
940 afs_int32 code;
941 idlist ids;
942 namelist names;
943 int i;
944 afs_int32 mask, flags=0, ngroups, nusers;
945
946 if (GetNameOrId(as, &ids, &names))
947 return PRBADARG;
948
949 mask = 0;
950 nusers = 0;
951 ngroups = 0;
952
953 if (as->parms[1].items) { /* privacy bits */
954 char *access = as->parms[1].items->data;
955 int new;
956
957 if (strpbrk(access, "76543210") != 0) { /* all octal digits */
958 sscanf(access, "%lo", (long unsigned int *) &flags);
959 } else { /* interpret flag bit names */
960 if (strlen(access) != 5) {
961 form_error:
962 fprintf(stderr, "Access bits must be of the form 'somar', not %s\n",
963 access);
964 return PRBADARG;
965 }
966 if (strpbrk(access, "somar-") == 0)
967 goto form_error;
968 flags = 0;
969 for (i = 0; i < 5; i++) {
970 if (access[i] == flags_upcase[i])
971 new = 2;
972 else if (access[i] == flags_dncase[i])
973 new = 1;
974 else if (access[i] == '-')
975 new = 0;
976 else {
977 fprintf(stderr,
978 "Access bits out of order or illegal:\n must be a combination of letters from '%s' or '%s' or hyphen, not %s\n",
979 flags_upcase, flags_dncase, access);
980 return PRBADARG;
981 }
982 flags <<= flags_shift[i];
983 if (flags_shift[i] == 1) {
984 if (new)
985 flags |= 1;
986 } else
987 flags |= new;
988 }
989 }
990 mask |= PR_SF_ALLBITS;
991 }
992 if (as->parms[2].items) { /* limitgroups */
993 code = util_GetInt32(as->parms[2].items->data, &ngroups);
994 if (code) {
995 afs_com_err(whoami, code, "because ngroups was: '%s'",
996 as->parms[2].items->data);
997 return code;
998 }
999 mask |= PR_SF_NGROUPS;
1000 }
1001
1002 for (i = 0; i < ids.idlist_len; i++) {
1003 afs_int32 id = ids.idlist_val[i];
1004 char *name = names.namelist_val[i];
1005 if (id == ANONYMOUSID)
1006 continue;
1007 code = pr_SetFieldsEntry(id, mask, flags, ngroups, nusers);
1008 if (code) {
1009 afs_com_err(whoami, code, "; unable to set fields for %s (id: %d)",
1010 name, id);
1011 return code;
1012 }
1013 }
1014 if (ids.idlist_val)
1015 free(ids.idlist_val);
1016 if (names.namelist_val)
1017 free(names.namelist_val);
1018 return 0;
1019 }
1020
1021 static int
1022 ListOwned(struct cmd_syndesc *as, void *arock)
1023 {
1024 afs_int32 code;
1025 idlist ids;
1026 namelist names;
1027 namelist list;
1028 int i, j;
1029 afs_int32 more;
1030
1031 if (GetNameOrId(as, &ids, &names))
1032 return PRBADARG;
1033
1034 for (i = 0; i < ids.idlist_len; i++) {
1035 afs_int32 oid = ids.idlist_val[i];
1036 char *name = names.namelist_val[i];
1037
1038 if (oid == ANONYMOUSID)
1039 continue;
1040
1041 if (oid)
1042 printf("Groups owned by %s (id: %d) are:\n", name, oid);
1043 else
1044 printf("Orphaned groups are:\n");
1045 more = 0;
1046 do {
1047 list.namelist_val = 0;
1048 list.namelist_len = 0;
1049 code = pr_ListOwned(oid, &list, &more);
1050 if (code) {
1051 afs_com_err(whoami, code,
1052 "; unable to get owner list for %s (id: %d)", name,
1053 oid);
1054 break;
1055 }
1056
1057 for (j = 0; j < list.namelist_len; j++)
1058 printf(" %s\n", list.namelist_val[j]);
1059 if (list.namelist_val)
1060 free(list.namelist_val);
1061 } while (more);
1062 }
1063
1064 if (ids.idlist_val)
1065 free(ids.idlist_val);
1066 if (names.namelist_val)
1067 free(names.namelist_val);
1068 return 0;
1069 }
1070
1071 static void
1072 add_std_args(struct cmd_syndesc *ts)
1073 {
1074 char *test_help;
1075
1076 if (asprintf(&test_help, "use config file in %s",
1077 AFSDIR_SERVER_ETC_DIRPATH) < 0) {
1078 test_help = strdup("use server config file");
1079 }
1080
1081 cmd_Seek(ts, 16);
1082 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
1083 cmd_AddParm(ts, "-noauth", CMD_FLAG, CMD_OPTIONAL, "run unauthenticated");
1084 cmd_AddParm(ts, "-test", CMD_FLAG, CMD_OPTIONAL | CMD_HIDE, test_help);
1085 cmd_AddParm(ts, "-force", CMD_FLAG, CMD_OPTIONAL,
1086 "Continue oper despite reasonable errors");
1087 cmd_AddParm(ts, "-localauth", CMD_FLAG, CMD_OPTIONAL,
1088 "use local authentication");
1089 cmd_AddParm(ts, "-auth", CMD_FLAG, CMD_OPTIONAL,
1090 "use user's authentication (default)");
1091 cmd_AddParm(ts, "-encrypt", CMD_FLAG, CMD_OPTIONAL,
1092 "encrypt commands");
1093 cmd_AddParm(ts, "-config", CMD_SINGLE, CMD_OPTIONAL, "config location");
1094 free(test_help);
1095 }
1096
1097 /*
1098 static void add_NameOrId_args (ts)
1099 struct cmd_syndesc *ts;
1100 {
1101 cmd_AddParm(ts,"-name",CMD_LIST,CMD_OPTIONAL,"user or group name");
1102 cmd_AddParm(ts,"-id",CMD_LIST,CMD_OPTIONAL,"user or group id");
1103 }
1104 */
1105
1106 #include "AFS_component_version_number.c"
1107
1108 int
1109 main(int argc, char **argv)
1110 {
1111 afs_int32 code;
1112 struct cmd_syndesc *ts;
1113
1114 char line[2048];
1115 char *cp, *lastp;
1116 int parsec;
1117 char *parsev[CMD_MAXPARMS];
1118 char *savec;
1119 struct authstate state;
1120
1121 #ifdef WIN32
1122 WSADATA WSAjunk;
1123 #endif
1124
1125 #ifdef WIN32
1126 WSAStartup(0x0101, &WSAjunk);
1127 #endif
1128
1129 #ifdef AFS_AIX32_ENV
1130 /*
1131 * The following signal action for AIX is necessary so that in case of a
1132 * crash (i.e. core is generated) we can include the user's data section
1133 * in the core dump. Unfortunately, by default, only a partial core is
1134 * generated which, in many cases, isn't too useful.
1135 */
1136 struct sigaction nsa;
1137
1138 sigemptyset(&nsa.sa_mask);
1139 nsa.sa_handler = SIG_DFL;
1140 nsa.sa_flags = SA_FULLDUMP;
1141 sigaction(SIGSEGV, &nsa, NULL);
1142 #endif
1143
1144 memset(&state, 0, sizeof(state));
1145 state.sec = 1; /* default is auth */
1146
1147 ts = cmd_CreateSyntax("creategroup", CreateGroup, NULL, 0,
1148 "create a new group");
1149 cmd_AddParm(ts, "-name", CMD_LIST, 0, "group name");
1150 cmd_AddParm(ts, "-owner", CMD_SINGLE, CMD_OPTIONAL, "owner of the group");
1151 cmd_AddParm(ts, "-id", CMD_LIST, CMD_OPTIONAL,
1152 "id (negated) for the group");
1153 add_std_args(ts);
1154 cmd_CreateAlias(ts, "cg");
1155
1156 ts = cmd_CreateSyntax("createuser", CreateUser, NULL, 0, "create a new user");
1157 cmd_AddParm(ts, "-name", CMD_LIST, 0, "user name");
1158 cmd_AddParm(ts, "-id", CMD_LIST, CMD_OPTIONAL, "user id");
1159 add_std_args(ts);
1160 cmd_CreateAlias(ts, "cu");
1161
1162 ts = cmd_CreateSyntax("adduser", AddToGroup, NULL, 0, "add a user to a group");
1163 cmd_AddParm(ts, "-user", CMD_LIST, 0, "user name");
1164 cmd_AddParm(ts, "-group", CMD_LIST, 0, "group name");
1165 add_std_args(ts);
1166
1167 ts = cmd_CreateSyntax("removeuser", RemoveFromGroup, NULL, 0,
1168 "remove a user from a group");
1169 cmd_AddParm(ts, "-user", CMD_LIST, 0, "user name");
1170 cmd_AddParm(ts, "-group", CMD_LIST, 0, "group name");
1171 add_std_args(ts);
1172
1173 ts = cmd_CreateSyntax("membership", ListMembership, NULL, 0,
1174 "list membership of a user or group");
1175 cmd_AddParm(ts, "-nameorid", CMD_LIST, 0, "user or group name or id");
1176 cmd_AddParm(ts, "-supergroups", CMD_FLAG, CMD_OPTIONAL, "show supergroups");
1177 cmd_AddParm(ts, "-expandgroups", CMD_FLAG, CMD_OPTIONAL, "expand super and sub group membership");
1178 add_std_args(ts);
1179 cmd_CreateAlias(ts, "groups");
1180
1181 ts = cmd_CreateSyntax("delete", Delete, NULL, 0,
1182 "delete a user or group from database");
1183 cmd_AddParm(ts, "-nameorid", CMD_LIST, 0, "user or group name or id");
1184 add_std_args(ts);
1185
1186 ts = cmd_CreateSyntax("examine", CheckEntry, NULL, 0, "examine an entry");
1187 cmd_AddParm(ts, "-nameorid", CMD_LIST, 0, "user or group name or id");
1188 add_std_args(ts);
1189 cmd_CreateAlias(ts, "check");
1190
1191 ts = cmd_CreateSyntax("chown", ChownGroup, NULL, 0,
1192 "change ownership of a group");
1193 cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "group name");
1194 cmd_AddParm(ts, "-owner", CMD_SINGLE, 0, "new owner");
1195 add_std_args(ts);
1196
1197 ts = cmd_CreateSyntax("rename", ChangeName, NULL, 0, "rename user or group");
1198 cmd_AddParm(ts, "-oldname", CMD_SINGLE, 0, "old name");
1199 cmd_AddParm(ts, "-newname", CMD_SINGLE, 0, "new name");
1200 add_std_args(ts);
1201 cmd_CreateAlias(ts, "chname");
1202
1203 ts = cmd_CreateSyntax("listmax", ListMax, NULL, 0, "list max id");
1204 add_std_args(ts);
1205
1206 ts = cmd_CreateSyntax("setmax", SetMaxCommand, NULL, 0, "set max id");
1207 cmd_AddParm(ts, "-group", CMD_SINGLE, CMD_OPTIONAL, "group max");
1208 cmd_AddParm(ts, "-user", CMD_SINGLE, CMD_OPTIONAL, "user max");
1209 add_std_args(ts);
1210
1211 ts = cmd_CreateSyntax("setfields", SetFields, NULL, 0,
1212 "set fields for an entry");
1213 cmd_AddParm(ts, "-nameorid", CMD_LIST, 0, "user or group name or id");
1214 cmd_AddParm(ts, "-access", CMD_SINGLE, CMD_OPTIONAL, "set privacy flags");
1215 cmd_AddParm(ts, "-groupquota", CMD_SINGLE, CMD_OPTIONAL,
1216 "set limit on group creation");
1217 add_std_args(ts);
1218
1219 ts = cmd_CreateSyntax("listowned", ListOwned, NULL, 0,
1220 "list groups owned by an entry or zero id gets orphaned groups");
1221 cmd_AddParm(ts, "-nameorid", CMD_LIST, 0, "user or group name or id");
1222 add_std_args(ts);
1223
1224 ts = cmd_CreateSyntax("listentries", ListEntries, NULL, 0,
1225 "list users/groups in the protection database");
1226 cmd_AddParm(ts, "-users", CMD_FLAG, CMD_OPTIONAL, "list user entries");
1227 cmd_AddParm(ts, "-groups", CMD_FLAG, CMD_OPTIONAL, "list group entries");
1228 add_std_args(ts);
1229
1230 ts = cmd_CreateSyntax("interactive", pts_Interactive, NULL, 0,
1231 "enter interactive mode");
1232 add_std_args(ts);
1233 cmd_CreateAlias(ts, "in");
1234
1235 ts = cmd_CreateSyntax("quit", pts_Quit, NULL, 0, "exit program");
1236 add_std_args(ts);
1237
1238 ts = cmd_CreateSyntax("source", pts_Source, NULL, 0, "read commands from file");
1239 cmd_AddParm(ts, "-file", CMD_SINGLE, 0, "filename");
1240 add_std_args(ts);
1241
1242 ts = cmd_CreateSyntax("sleep", pts_Sleep, NULL, 0, "pause for a bit");
1243 cmd_AddParm(ts, "-delay", CMD_SINGLE, 0, "seconds");
1244 add_std_args(ts);
1245
1246 cmd_SetBeforeProc(GetGlobals, &state);
1247
1248 finished = 1;
1249 source = NULL;
1250 if (cmd_Dispatch(argc, argv)) {
1251 CleanUp(NULL, NULL);
1252 exit(1);
1253 }
1254 while (source && !finished) {
1255 if (isatty(fileno(source)))
1256 fprintf(stderr, "pts> ");
1257 if (!fgets(line, sizeof line, source)) {
1258 if (!popsource())
1259 break;
1260 continue;
1261 }
1262 lastp = 0;
1263 for (cp = line; *cp; ++cp)
1264 if (!isspace(*cp))
1265 lastp = 0;
1266 else if (!lastp)
1267 lastp = cp;
1268 if (lastp)
1269 *lastp = 0;
1270 if (!*line)
1271 continue;
1272 code =
1273 cmd_ParseLine(line, parsev, &parsec,
1274 sizeof(parsev) / sizeof(*parsev));
1275 if (code) {
1276 afs_com_err(whoami, code, "parsing line: <%s>", line);
1277 exit(2);
1278 }
1279 savec = parsev[0];
1280 parsev[0] = argv[0];
1281 cmd_Dispatch(parsec, parsev);
1282 parsev[0] = savec;
1283 cmd_FreeArgv(parsev);
1284 }
1285 CleanUp(NULL, NULL);
1286 exit(0);
1287 }