Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / libadmin / pts / afs_ptsAdmin.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 #include <afs/stds.h>
13
14 #include <roken.h>
15
16 #include <ctype.h>
17
18 #include <rx/rx.h>
19 #include <rx/rxstat.h>
20
21 #include <afs/afs_AdminErrors.h>
22 #include <afs/afs_utilAdmin.h>
23 #include <afs/ptint.h>
24 #include <afs/ptserver.h>
25
26 #include "afs_ptsAdmin.h"
27 #include "../adminutil/afs_AdminInternal.h"
28
29 /*
30 * IsValidCellHandle - validate the cell handle for making pts
31 * requests.
32 *
33 * PARAMETERS
34 *
35 * IN cellHandle - a previously opened cellHandle that is to be validated.
36 *
37 * LOCKS
38 *
39 * No locks are obtained or released by this function
40 *
41 * RETURN CODES
42 *
43 * Returns != 0 upon successful completion.
44 *
45 */
46
47 static int
48 IsValidCellHandle(const afs_cell_handle_p c_handle, afs_status_p st)
49 {
50 int rc = 0;
51 afs_status_t tst = 0;
52
53 if (!CellHandleIsValid((void *)c_handle, &tst)) {
54 goto fail_IsValidCellHandle;
55 }
56
57 if (c_handle->pts_valid == 0) {
58 tst = ADMCLIENTCELLPTSINVALID;
59 goto fail_IsValidCellHandle;
60 }
61
62 if (c_handle->pts == NULL) {
63 tst = ADMCLIENTCELLPTSNULL;
64 goto fail_IsValidCellHandle;
65 }
66 rc = 1;
67
68
69 fail_IsValidCellHandle:
70
71 if (st != NULL) {
72 *st = tst;
73 }
74 return rc;
75 }
76
77
78 /*
79 * TranslatePTSNames - translate character representations of pts names
80 * into their numeric equivalent.
81 *
82 * PARAMETERS
83 *
84 * IN cellHandle - a previously opened cellHandle that corresponds
85 * to the cell where the id's exist.
86 *
87 * IN names - the list of names to be translated.
88 *
89 * OUT ids - the list of translated names
90 *
91 * LOCKS
92 *
93 * No locks are obtained or released by this function
94 *
95 * RETURN CODES
96 *
97 * Returns != 0 upon successful completion.
98 *
99 */
100
101 static int
102 TranslatePTSNames(const afs_cell_handle_p cellHandle, namelist * names,
103 idlist * ids, afs_status_p st)
104 {
105 int rc = 0;
106 afs_status_t tst = 0;
107 int i;
108 char *p;
109
110 /*
111 * Lowercase the names to translate
112 */
113
114 for (i = 0; i < names->namelist_len; i++) {
115 p = names->namelist_val[i];
116 while (*p) {
117 *p = tolower(*p);
118 p++;
119 }
120 }
121
122 tst = ubik_PR_NameToID(cellHandle->pts, 0, names, ids);
123
124 if (tst) {
125 goto fail_TranslatePTSNames;
126 }
127
128
129 /*
130 * Check to see if the lookup failed
131 */
132
133 for (i = 0; i < ids->idlist_len; i++) {
134 if (ids->idlist_val[i] == ANONYMOUSID) {
135 tst = ADMPTSFAILEDNAMETRANSLATE;
136 goto fail_TranslatePTSNames;
137 }
138 }
139 rc = 1;
140
141 fail_TranslatePTSNames:
142
143 if (st != NULL) {
144 *st = tst;
145 }
146 return rc;
147 }
148
149 /*
150 * TranslateTwoNames - translate two pts names to their pts ids.
151 *
152 * PARAMETERS
153 *
154 * IN cellHandle - a previously opened cellHandle that corresponds
155 * to the cell where the group exists.
156 *
157 * IN id1 - one id to be translated
158 *
159 * IN error1 - the error status to be returned in the event that id1 is
160 * too long.
161 *
162 * IN id2 - one id to be translated
163 *
164 * IN error2 - the error status to be returned in the event that id2 is
165 * too long.
166 *
167 *
168 * OUT idlist - the list of pts id's
169 *
170 * LOCKS
171 *
172 * No locks are obtained or released by this function
173 *
174 * RETURN CODES
175 *
176 * Returns != 0 upon successful completion.
177 *
178 */
179
180 static int
181 TranslateTwoNames(const afs_cell_handle_p c_handle, const char *id1,
182 afs_status_t error1, const char *id2, afs_status_t error2,
183 idlist * ids, afs_status_p st)
184 {
185 int rc = 0;
186 afs_status_t tst = 0;
187 namelist names;
188 char tmp_array[2 * PTS_MAX_NAME_LEN];
189
190 /*
191 * Copy the group and user names in order to translate them
192 */
193
194 names.namelist_len = 2;
195 names.namelist_val = (prname *) & tmp_array[0];
196
197 strncpy(names.namelist_val[0], id1, PTS_MAX_NAME_LEN);
198 names.namelist_val[0][PTS_MAX_NAME_LEN - 1] = '\0';
199 strncpy(names.namelist_val[1], id2, PTS_MAX_NAME_LEN);
200 names.namelist_val[1][PTS_MAX_NAME_LEN - 1] = '\0';
201 ids->idlist_val = 0;
202 ids->idlist_len = 0;
203
204 /*
205 * Check that user and group aren't too long
206 * This is a cheaper check than calling strlen
207 */
208
209 if (names.namelist_val[0][PTS_MAX_NAME_LEN - 1] != 0) {
210 tst = error1;
211 goto fail_TranslateTwoNames;
212 }
213
214 if (names.namelist_val[0][PTS_MAX_NAME_LEN - 1] != 0) {
215 tst = error2;
216 goto fail_TranslateTwoNames;
217 }
218
219 /*
220 * Translate user and group into pts ID's
221 */
222
223 if (TranslatePTSNames(c_handle, &names, ids, &tst) == 0) {
224 goto fail_TranslateTwoNames;
225 }
226 rc = 1;
227
228
229 fail_TranslateTwoNames:
230
231 if (st != NULL) {
232 *st = tst;
233 }
234 return rc;
235 }
236
237 /*
238 * TranslateOneName - translate a pts name to its pts id.
239 *
240 * PARAMETERS
241 *
242 * IN cellHandle - a previously opened cellHandle that corresponds
243 * to the cell where the group exists.
244 *
245 * IN userName - the user to be translated.
246 *
247 * OUT idlist - the user pts id.
248 *
249 * LOCKS
250 *
251 * No locks are obtained or released by this function
252 *
253 * RETURN CODES
254 *
255 * Returns != 0 upon successful completion.
256 *
257 */
258
259 static int
260 TranslateOneName(const afs_cell_handle_p c_handle, const char *ptsName,
261 afs_status_t tooLongError, afs_int32 * ptsId,
262 afs_status_p st)
263 {
264 int rc = 0;
265 afs_status_t tst = 0;
266 namelist names[1];
267 char tmp_array[PTS_MAX_NAME_LEN];
268 idlist ids;
269
270 /*
271 * Copy the name in order to translate it
272 */
273
274 names[0].namelist_len = 1;
275 names[0].namelist_val = (prname *) & tmp_array[0];
276
277 strncpy((char *)names[0].namelist_val, ptsName, PTS_MAX_NAME_LEN);
278 ((char *)names[0].namelist_val)[PTS_MAX_NAME_LEN - 1] = '\0';
279 ids.idlist_val = 0;
280 ids.idlist_len = 0;
281
282 /*
283 * Check that user isn't too long
284 * This is a cheaper check than calling strlen
285 */
286
287 if (names[0].namelist_val[0][PTS_MAX_NAME_LEN - 1] != 0) {
288 tst = tooLongError;
289 goto fail_TranslateOneName;
290 }
291
292 /*
293 * Translate user into pts ID
294 */
295
296 if (TranslatePTSNames(c_handle, names, &ids, &tst) == 0) {
297 goto fail_TranslateOneName;
298 } else {
299 if (ids.idlist_val != NULL) {
300 *ptsId = *ids.idlist_val;
301 free(ids.idlist_val);
302 }
303 }
304 rc = 1;
305
306
307 fail_TranslateOneName:
308
309 if (st != NULL) {
310 *st = tst;
311 }
312 return rc;
313 }
314
315 /*
316 * TranslatePTSIds - translate numeric representations of pts names
317 * into their character equivalent.
318 *
319 * PARAMETERS
320 *
321 * IN cellHandle - a previously opened cellHandle that corresponds
322 * to the cell where the id's exist.
323 *
324 * IN ids - the list of ids to be translated.
325 *
326 * OUT names - the list of translated names
327 *
328 * LOCKS
329 *
330 * No locks are obtained or released by this function
331 *
332 * RETURN CODES
333 *
334 * Returns != 0 upon successful completion.
335 *
336 */
337
338 static int
339 TranslatePTSIds(const afs_cell_handle_p cellHandle, namelist * names,
340 idlist * ids, afs_status_p st)
341 {
342 int rc = 0;
343 afs_status_t tst = 0;
344
345 tst = string_PR_IDToName(cellHandle->pts, 0, ids, names);
346
347 if (tst) {
348 goto fail_TranslatePTSIds;
349 }
350 rc = 1;
351
352 fail_TranslatePTSIds:
353
354 if (st != NULL) {
355 *st = tst;
356 }
357 return rc;
358 }
359
360 /*
361 * pts_GroupMemberAdd - add one member to a pts group
362 *
363 * PARAMETERS
364 *
365 * IN cellHandle - a previously opened cellHandle that corresponds
366 * to the cell where the group exists.
367 *
368 * IN userName - the name to be added to the group.
369 *
370 * IN groupName - the group to be modified.
371 *
372 * LOCKS
373 *
374 * No locks are obtained or released by this function
375 *
376 * RETURN CODES
377 *
378 * Returns != 0 upon successful completion.
379 *
380 */
381
382 int ADMINAPI
383 pts_GroupMemberAdd(const void *cellHandle, const char *userName,
384 const char *groupName, afs_status_p st)
385 {
386 int rc = 0;
387 afs_status_t tst = 0;
388 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
389 idlist ids = {0,0};
390
391 /*
392 * Validate arguments
393 */
394
395 if (!IsValidCellHandle(c_handle, &tst)) {
396 goto fail_pts_GroupMemberAdd;
397 }
398
399 if ((userName == NULL) || (*userName == 0)) {
400 tst = ADMPTSUSERNAMENULL;
401 goto fail_pts_GroupMemberAdd;
402 }
403
404 if ((groupName == NULL) || (*groupName == 0)) {
405 tst = ADMPTSGROUPNAMENULL;
406 goto fail_pts_GroupMemberAdd;
407 }
408
409 if (!TranslateTwoNames
410 (c_handle, userName, ADMPTSUSERNAMETOOLONG, groupName,
411 ADMPTSGROUPNAMETOOLONG, &ids, &tst)) {
412 goto fail_pts_GroupMemberAdd;
413 }
414
415 /*
416 * Make the rpc
417 */
418
419 tst =
420 ubik_PR_AddToGroup(c_handle->pts, 0, ids.idlist_val[0],
421 ids.idlist_val[1]);
422
423 if (tst != 0) {
424 goto fail_pts_GroupMemberAdd;
425 }
426 rc = 1;
427
428 fail_pts_GroupMemberAdd:
429
430 if (ids.idlist_val != 0) {
431 free(ids.idlist_val);
432 }
433
434 if (st != NULL) {
435 *st = tst;
436 }
437 return rc;
438 }
439
440 /*
441 * pts_GroupOwnerChange - change the owner of a group
442 *
443 * PARAMETERS
444 *
445 * IN cellHandle - a previously opened cellHandle that corresponds
446 * to the cell where the group exists.
447 *
448 * IN targetGroup - the group to be modified.
449 *
450 * IN userName - the new owner of the group.
451 *
452 * LOCKS
453 *
454 * No locks are obtained or released by this function
455 *
456 * RETURN CODES
457 *
458 * Returns != 0 upon successful completion.
459 *
460 */
461
462 int ADMINAPI
463 pts_GroupOwnerChange(const void *cellHandle, const char *targetGroup,
464 const char *newOwner, afs_status_p st)
465 {
466 int rc = 0;
467 afs_status_t tst = 0;
468 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
469 idlist ids;
470
471 memset(&ids, 0, sizeof(ids));
472
473 /*
474 * Validate arguments
475 */
476
477 if (!IsValidCellHandle(c_handle, &tst)) {
478 goto fail_pts_GroupOwnerChange;
479 }
480
481 if ((newOwner == NULL) || (*newOwner == 0)) {
482 tst = ADMPTSNEWOWNERNULL;
483 goto fail_pts_GroupOwnerChange;
484 }
485
486 if ((targetGroup == NULL) || (*targetGroup == 0)) {
487 tst = ADMPTSTARGETGROUPNULL;
488 goto fail_pts_GroupOwnerChange;
489 }
490
491 if (!TranslateTwoNames
492 (c_handle, newOwner, ADMPTSNEWOWNERTOOLONG, targetGroup,
493 ADMPTSTARGETGROUPTOOLONG, &ids, &tst)) {
494 goto fail_pts_GroupOwnerChange;
495 }
496
497 /*
498 * Make the rpc
499 */
500
501 tst =
502 ubik_PR_ChangeEntry(c_handle->pts, 0, ids.idlist_val[1], "",
503 ids.idlist_val[0], 0);
504
505 if (tst != 0) {
506 goto fail_pts_GroupOwnerChange;
507 }
508 rc = 1;
509
510 fail_pts_GroupOwnerChange:
511
512 if (ids.idlist_val != 0) {
513 free(ids.idlist_val);
514 }
515
516 if (st != NULL) {
517 *st = tst;
518 }
519 return rc;
520 }
521
522 /*
523 * pts_GroupCreate - create a new group
524 *
525 * PARAMETERS
526 *
527 * IN cellHandle - a previously opened cellHandle that corresponds
528 * to the cell where the group exists.
529 *
530 * IN newGroup - the group to be created.
531 *
532 * IN newOwner - the owner of the group. Pass NULL if the current user
533 * is to be the new owner, or the character string of the owner otherwise.
534 *
535 * IN/OUT newGroupId - the pts id of the group. Pass 0 to have ptserver
536 * generate a value, != 0 to assign a value on your own. The group id
537 * that is used to create the group is copied into this parameter in the
538 * event you pass in 0.
539 *
540 * LOCKS
541 *
542 * No locks are obtained or released by this function
543 *
544 * RETURN CODES
545 *
546 * Returns != 0 upon successful completion.
547 *
548 */
549
550 int ADMINAPI
551 pts_GroupCreate(const void *cellHandle, char *newGroup,
552 char *newOwner, int *newGroupId, afs_status_p st)
553 {
554 int rc = 0;
555 afs_status_t tst = 0;
556 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
557 afs_int32 newOwnerId = 0;
558
559 /*
560 * Validate arguments
561 */
562
563 if (!IsValidCellHandle(c_handle, &tst)) {
564 goto fail_pts_GroupCreate;
565 }
566
567 if ((newGroup == NULL) || (*newGroup == 0)) {
568 tst = ADMPTSNEWGROUPNULL;
569 goto fail_pts_GroupCreate;
570 }
571
572 if (newGroupId == NULL) {
573 tst = ADMPTSNEWGROUPIDNULL;
574 goto fail_pts_GroupCreate;
575 }
576
577 if (*newGroupId > 0) {
578 tst = ADMPTSNEWGROUPIDPOSITIVE;
579 goto fail_pts_GroupCreate;
580 }
581
582 /*
583 * If a newOwner was specified, validate that it exists
584 */
585
586 if (newOwner != NULL) {
587 if (!TranslateOneName
588 (c_handle, newOwner, ADMPTSNEWOWNERTOOLONG, &newOwnerId, &tst)) {
589 goto fail_pts_GroupCreate;
590 }
591 }
592
593 /*
594 * We make a different rpc based upon the input to this function
595 */
596
597 if (*newGroupId != 0) {
598 tst =
599 ubik_PR_INewEntry(c_handle->pts, 0, newGroup, *newGroupId,
600 newOwnerId);
601 } else {
602 tst =
603 ubik_PR_NewEntry(c_handle->pts, 0, newGroup, PRGRP,
604 newOwnerId, newGroupId);
605 }
606
607 if (tst != 0) {
608 goto fail_pts_GroupCreate;
609 }
610 rc = 1;
611
612 fail_pts_GroupCreate:
613
614 if (st != NULL) {
615 *st = tst;
616 }
617 return rc;
618 }
619
620 /*
621 * GetGroupAccess - a small convenience function for setting
622 * permissions.
623 *
624 * PARAMETERS
625 *
626 * IN access - a pointer to a pts_groupAccess_t to be set with the
627 * correct permission.
628 *
629 * IN flag - the current permission flag used to derive the permission.
630 *
631 * LOCKS
632 *
633 * No locks are obtained or released by this function
634 *
635 * RETURN CODES
636 *
637 * Since this function cannot fail, it returns void.
638 *
639 */
640
641 static void
642 GetGroupAccess(pts_groupAccess_p access, afs_int32 flag)
643 {
644
645 *access = PTS_GROUP_OWNER_ACCESS;
646 if (flag == 0) {
647 *access = PTS_GROUP_OWNER_ACCESS;
648 } else if (flag == 1) {
649 *access = PTS_GROUP_ACCESS;
650 } else if (flag == 2) {
651 *access = PTS_GROUP_ANYUSER_ACCESS;
652 }
653 }
654
655
656 /*
657 * pts_GroupGet - retrieve information about a particular group.
658 *
659 * PARAMETERS
660 *
661 * IN cellHandle - a previously opened cellHandle that corresponds
662 * to the cell where the group exists.
663 *
664 * IN groupName - the group to retrieve.
665 *
666 * OUT groupP - a pointer to a pts_GroupEntry_t structure that upon
667 * successful completion is filled with information about groupName.
668 *
669 * LOCKS
670 *
671 * No locks are obtained or released by this function
672 *
673 * RETURN CODES
674 *
675 * Returns != 0 upon successful completion.
676 *
677 */
678
679 int ADMINAPI
680 pts_GroupGet(const void *cellHandle, const char *groupName,
681 pts_GroupEntry_p groupP, afs_status_p st)
682 {
683 int rc = 0;
684 afs_status_t tst = 0;
685 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
686 afs_int32 groupId = 0;
687 afs_int32 flags;
688 afs_int32 twobit;
689 struct prcheckentry groupEntry;
690 idlist ids;
691 afs_int32 ptsids[2];
692 namelist names;
693
694 /*
695 * Validate arguments
696 */
697
698 if (!IsValidCellHandle(c_handle, &tst)) {
699 goto fail_pts_GroupGet;
700 }
701
702 if ((groupName == NULL) || (*groupName == 0)) {
703 tst = ADMPTSGROUPNAMENULL;
704 goto fail_pts_GroupGet;
705 }
706
707 if (groupP == NULL) {
708 tst = ADMPTSGROUPPNULL;
709 goto fail_pts_GroupGet;
710 }
711
712 /*
713 * Translate the group name into an id.
714 */
715
716 if (!TranslateOneName
717 (c_handle, groupName, ADMPTSGROUPNAMETOOLONG, &groupId, &tst)) {
718 goto fail_pts_GroupGet;
719 }
720
721 /*
722 * Retrieve information about the group
723 */
724
725 tst = ubik_PR_ListEntry(c_handle->pts, 0, groupId, &groupEntry);
726
727 if (tst != 0) {
728 goto fail_pts_GroupGet;
729 }
730
731 groupP->membershipCount = groupEntry.count;
732 groupP->nameUid = groupEntry.id;
733 groupP->ownerUid = groupEntry.owner;
734 groupP->creatorUid = groupEntry.creator;
735 strncpy(groupP->name, groupEntry.name, PTS_MAX_NAME_LEN);
736 groupP->name[PTS_MAX_NAME_LEN - 1] = '\0';
737 /*
738 * Set the access rights based upon the value of the flags member
739 * of the groupEntry struct.
740 *
741 * To the best of my ability to decypher the pts code, it looks like
742 * the rights are stored in flags as follows:
743 *
744 * I number my bits from least significant to most significant starting
745 * with 0.
746 *
747 * remove - bit 0
748 * if bit 0 == 0 -> r access is denied
749 * if bit 0 == 1 -> r access is granted
750 *
751 * add - bits 1 and 2
752 * if bit 2 == 0 and bit 1 == 0 -> a access is denied
753 * if bit 2 == 0 and bit 1 == 1 -> a access is granted
754 * if bit 2 == 1 and bit 1 == 0 -> A access is granted
755 * if bit 2 == 1 and bit 1 == 1 -> this is an error
756 *
757 * membership - bits 3 and 4
758 * if bit 4 == 0 and bit 3 == 0 -> m access is denied
759 * if bit 4 == 0 and bit 3 == 1 -> m access is granted
760 * if bit 4 == 1 and bit 3 == 0 -> M access is granted
761 * if bit 4 == 1 and bit 3 == 1 -> this is an error
762 *
763 * owned - bit 5
764 * if bit 5 == 0 -> O access is denied
765 * if bit 5 == 1 -> O access is granted
766 *
767 * status - bits 6 and 7
768 * if bit 7 == 0 and bit 6 == 0 -> s access is denied
769 * if bit 7 == 0 and bit 6 == 1 -> s access is granted
770 * if bit 7 == 1 and bit 6 == 0 -> S access is granted
771 * if bit 7 == 1 and bit 6 == 1 -> this is an error
772 *
773 * For cases where the permission doesn't make sense for the
774 * type of entry, or where an error occurs, we ignore it.
775 * This is the behavior of the pts code.
776 */
777
778 flags = groupEntry.flags;
779 if (flags & 1) {
780 groupP->listDelete = PTS_GROUP_ACCESS;
781 } else {
782 groupP->listDelete = PTS_GROUP_OWNER_ACCESS;
783 }
784
785 flags = flags >> 1;
786 twobit = flags & 3;
787
788 GetGroupAccess(&groupP->listAdd, twobit);
789
790 flags = flags >> 2;
791 twobit = flags & 3;
792
793 GetGroupAccess(&groupP->listMembership, twobit);
794
795 flags = flags >> 2;
796
797 if (flags & 1) {
798 groupP->listGroupsOwned = PTS_GROUP_ANYUSER_ACCESS;
799 } else {
800 groupP->listGroupsOwned = PTS_GROUP_OWNER_ACCESS;
801 }
802
803 flags = flags >> 1;
804 twobit = flags & 3;
805
806 GetGroupAccess(&groupP->listStatus, twobit);
807
808 /*
809 * Make another rpc and translate the owner and creator ids into
810 * character strings.
811 */
812
813 ids.idlist_len = 2;
814 ids.idlist_val = ptsids;
815 ptsids[0] = groupEntry.owner;
816 ptsids[1] = groupEntry.creator;
817 names.namelist_len = 0;
818 names.namelist_val = 0;
819
820
821 if (!TranslatePTSIds(c_handle, &names, &ids, &tst)) {
822 goto fail_pts_GroupGet;
823 }
824
825 strncpy(groupP->owner, names.namelist_val[0], PTS_MAX_NAME_LEN);
826 groupP->owner[PTS_MAX_NAME_LEN - 1] = '\0';
827 strncpy(groupP->creator, names.namelist_val[1], PTS_MAX_NAME_LEN);
828 groupP->creator[PTS_MAX_NAME_LEN - 1] = '\0';
829 free(names.namelist_val);
830 rc = 1;
831
832 fail_pts_GroupGet:
833
834 if (st != NULL) {
835 *st = tst;
836 }
837 return rc;
838 }
839
840 /*
841 * EntryDelete - delete a pts entry (group or user).
842 *
843 * PARAMETERS
844 *
845 * IN cellHandle - a previously opened cellHandle that corresponds
846 * to the cell where the group exists.
847 *
848 * IN entryName - the entry to be deleted.
849 *
850 * IN error1 - the error status to be returned in the event that entryName is
851 * null.
852 *
853 * IN error2 - the error status to be returned in the event that entryName is
854 * too long.
855 *
856 * LOCKS
857 *
858 * No locks are obtained or released by this function
859 *
860 * RETURN CODES
861 *
862 * Returns != 0 upon successful completion.
863 *
864 */
865
866 static int
867 EntryDelete(const void *cellHandle, const char *entryName,
868 afs_status_t error1, afs_status_t error2, afs_status_p st)
869 {
870 int rc = 0;
871 afs_status_t tst = 0;
872 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
873 afs_int32 entryId = 0;
874
875 /*
876 * Validate arguments
877 */
878
879 if (!IsValidCellHandle(c_handle, &tst)) {
880 goto fail_EntryDelete;
881 }
882
883 if ((entryName == NULL) || (*entryName == 0)) {
884 tst = error1;
885 goto fail_EntryDelete;
886 }
887
888 /*
889 * Translate the entry name into an id.
890 */
891
892 if (!TranslateOneName(c_handle, entryName, error2, &entryId, &tst)) {
893 goto fail_EntryDelete;
894 }
895
896 /*
897 * Make the rpc
898 */
899
900 tst = ubik_PR_Delete(c_handle->pts, 0, entryId);
901
902 if (tst != 0) {
903 goto fail_EntryDelete;
904 }
905 rc = 1;
906
907 fail_EntryDelete:
908
909 if (st != NULL) {
910 *st = tst;
911 }
912 return rc;
913 }
914
915
916 /*
917 * pts_GroupDelete - delete a group
918 *
919 * PARAMETERS
920 *
921 * IN cellHandle - a previously opened cellHandle that corresponds
922 * to the cell where the group exists.
923 *
924 * IN groupName - the group to be deleted.
925 *
926 * LOCKS
927 *
928 * No locks are obtained or released by this function
929 *
930 * RETURN CODES
931 *
932 * Returns != 0 upon successful completion.
933 *
934 */
935
936 int ADMINAPI
937 pts_GroupDelete(const void *cellHandle, const char *groupName,
938 afs_status_p st)
939 {
940
941 return EntryDelete(cellHandle, groupName, ADMPTSGROUPNAMENULL,
942 ADMPTSGROUPNAMETOOLONG, st);
943 }
944
945 /*
946 * pts_GroupMaxGet - get the maximum in use group id.
947 *
948 * PARAMETERS
949 *
950 * IN cellHandle - a previously opened cellHandle that corresponds
951 * to the cell where the group exists.
952 *
953 * OUT maxGroupId - upon successful completion contains the maximum
954 * group Id in use at the server.
955 *
956 * LOCKS
957 *
958 * No locks are obtained or released by this function
959 *
960 * RETURN CODES
961 *
962 * Returns != 0 upon successful completion.
963 *
964 */
965
966 int ADMINAPI
967 pts_GroupMaxGet(const void *cellHandle, int *maxGroupId, afs_status_p st)
968 {
969 int rc = 0;
970 afs_status_t tst = 0;
971 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
972 afs_int32 maxUserId = 0;
973
974 /*
975 * Validate arguments
976 */
977
978 if (!IsValidCellHandle(c_handle, &tst)) {
979 goto fail_pts_GroupMaxGet;
980 }
981
982 if (maxGroupId == NULL) {
983 tst = ADMPTSMAXGROUPIDNULL;
984 goto fail_pts_GroupMaxGet;
985 }
986
987 tst = ubik_PR_ListMax(c_handle->pts, 0, &maxUserId, maxGroupId);
988
989 if (tst != 0) {
990 goto fail_pts_GroupMaxGet;
991 }
992 rc = 1;
993
994 fail_pts_GroupMaxGet:
995
996 if (st != NULL) {
997 *st = tst;
998 }
999 return rc;
1000 }
1001
1002 /*
1003 * pts_GroupMaxSet - set the maximum in use group id.
1004 *
1005 * PARAMETERS
1006 *
1007 * IN cellHandle - a previously opened cellHandle that corresponds
1008 * to the cell where the group exists.
1009 *
1010 * IN maxGroupId - the new maximum group id.
1011 *
1012 * LOCKS
1013 *
1014 * No locks are obtained or released by this function
1015 *
1016 * RETURN CODES
1017 *
1018 * Returns != 0 upon successful completion.
1019 *
1020 */
1021
1022 int ADMINAPI
1023 pts_GroupMaxSet(const void *cellHandle, int maxGroupId, afs_status_p st)
1024 {
1025 int rc = 0;
1026 afs_status_t tst = 0;
1027 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1028
1029 /*
1030 * Validate arguments
1031 */
1032
1033 if (!IsValidCellHandle(c_handle, &tst)) {
1034 goto fail_pts_GroupMaxSet;
1035 }
1036
1037 tst = ubik_PR_SetMax(c_handle->pts, 0, maxGroupId, PRGRP);
1038
1039 if (tst != 0) {
1040 goto fail_pts_GroupMaxSet;
1041 }
1042 rc = 1;
1043
1044 fail_pts_GroupMaxSet:
1045
1046 if (st != NULL) {
1047 *st = tst;
1048 }
1049 return rc;
1050 }
1051
1052 /*
1053 * NOTE
1054 *
1055 * I'm not using the common iterator pattern here since the retrival
1056 * of the member list is actually accomplished in 1 rpc. There's no
1057 * sense in trying to fit this pts specific behavior into the more
1058 * generic model, so instead the Begin functions actually do all the
1059 * rpc work and the next/done functions just manipulate the retrieved
1060 * data.
1061 */
1062
1063 typedef struct pts_group_member_list_iterator {
1064 int begin_magic;
1065 int is_valid;
1066 pthread_mutex_t mutex; /* hold to manipulate this structure */
1067 prlist ids;
1068 namelist names;
1069 int index;
1070 int end_magic;
1071 } pts_group_member_list_iterator_t, *pts_group_member_list_iterator_p;
1072
1073 /*
1074 * pts_GroupMemberListBegin - begin iterating over the list of members
1075 * of a particular group.
1076 *
1077 * PARAMETERS
1078 *
1079 * IN iter - an iterator previously returned by pts_GroupMemberListBegin
1080 *
1081 * LOCKS
1082 *
1083 * No locks are obtained or released by this function
1084 *
1085 * RETURN CODES
1086 *
1087 * Returns != 0 upon successful completion.
1088 *
1089 */
1090
1091 static int
1092 IsValidPtsGroupMemberListIterator(pts_group_member_list_iterator_p iter,
1093 afs_status_p st)
1094 {
1095 int rc = 0;
1096 afs_status_t tst = 0;
1097
1098 if (iter == NULL) {
1099 tst = ADMITERATORNULL;
1100 goto fail_IsValidPtsGroupMemberListIterator;
1101 }
1102
1103 if ((iter->begin_magic != BEGIN_MAGIC) || (iter->end_magic != END_MAGIC)) {
1104 tst = ADMITERATORBADMAGICNULL;
1105 goto fail_IsValidPtsGroupMemberListIterator;
1106 }
1107
1108 if (iter->is_valid == 0) {
1109 tst = ADMITERATORINVALID;
1110 goto fail_IsValidPtsGroupMemberListIterator;
1111 }
1112 rc = 1;
1113
1114 fail_IsValidPtsGroupMemberListIterator:
1115
1116 if (st != NULL) {
1117 *st = tst;
1118 }
1119 return rc;
1120 }
1121
1122 /*
1123 * MemberListBegin - an internal function which is used to get both
1124 * the list of members in a group and the list of groups a user belongs
1125 * to.
1126 *
1127 * PARAMETERS
1128 *
1129 * IN cellHandle - a previously opened cellHandle that corresponds
1130 * to the cell where the group exists.
1131 *
1132 * IN name - the name whose membership will be retrieved.
1133 *
1134 * OUT iterationIdP - upon successful completion contains a iterator that
1135 * can be passed to pts_GroupMemberListNext or pts_UserMemberListNext
1136 *
1137 * LOCKS
1138 *
1139 * No locks are obtained or released by this function
1140 *
1141 * RETURN CODES
1142 *
1143 * Returns != 0 upon successful completion.
1144 *
1145 */
1146
1147 static int
1148 MemberListBegin(const void *cellHandle, const char *name, afs_status_t error1,
1149 afs_status_t error2, void **iterationIdP, afs_status_p st)
1150 {
1151 int rc = 0;
1152 afs_status_t tst = 0;
1153 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1154 afs_int32 groupId = 0;
1155 afs_int32 exceeded = 0;
1156 pts_group_member_list_iterator_p iter =
1157 malloc(sizeof(pts_group_member_list_iterator_t));
1158 int iter_allocated = 0;
1159 int ids_allocated = 0;
1160 int names_allocated = 0;
1161 int mutex_inited = 0;
1162
1163 /*
1164 * Validate arguments
1165 */
1166
1167 if (!IsValidCellHandle(c_handle, &tst)) {
1168 goto fail_MemberListBegin;
1169 }
1170
1171 if ((name == NULL) || (*name == 0)) {
1172 tst = ADMPTSGROUPNAMENULL;
1173 goto fail_MemberListBegin;
1174 }
1175
1176 if (iterationIdP == NULL) {
1177 tst = ADMITERATORNULL;
1178 goto fail_MemberListBegin;
1179 }
1180
1181 if (iter == NULL) {
1182 tst = ADMNOMEM;
1183 goto fail_MemberListBegin;
1184 }
1185
1186 iter_allocated = 1;
1187
1188 /*
1189 * Translate the name into an id.
1190 */
1191
1192 if (!TranslateOneName
1193 (c_handle, name, ADMPTSGROUPNAMETOOLONG, &groupId, &tst)) {
1194 goto fail_MemberListBegin;
1195 }
1196
1197 if (pthread_mutex_init(&iter->mutex, 0)) {
1198 tst = ADMMUTEXINIT;
1199 goto fail_MemberListBegin;
1200 }
1201
1202 mutex_inited = 1;
1203
1204 iter->ids.prlist_len = 0;
1205 iter->ids.prlist_val = 0;
1206
1207 tst =
1208 ubik_PR_ListElements(c_handle->pts, 0, groupId, &iter->ids,
1209 &exceeded);
1210
1211 if (tst != 0) {
1212 goto fail_MemberListBegin;
1213 }
1214
1215 if (exceeded != 0) {
1216 tst = ADMPTSGROUPMEMEXCEEDED;
1217 goto fail_MemberListBegin;
1218 }
1219
1220 ids_allocated = 1;
1221 iter->names.namelist_len = 0;
1222 iter->names.namelist_val = 0;
1223
1224 if (!TranslatePTSIds
1225 (c_handle, &iter->names, (idlist *) & iter->ids, &tst)) {
1226 goto fail_MemberListBegin;
1227 }
1228
1229 names_allocated = 1;
1230 iter->begin_magic = BEGIN_MAGIC;
1231 iter->end_magic = END_MAGIC;
1232 iter->index = 0;
1233 iter->is_valid = 1;
1234
1235 *iterationIdP = (void *)iter;
1236 rc = 1;
1237
1238 fail_MemberListBegin:
1239
1240 if (ids_allocated) {
1241 free(iter->ids.prlist_val);
1242 }
1243
1244 if (rc == 0) {
1245 if (names_allocated) {
1246 free(iter->names.namelist_val);
1247 }
1248 if (mutex_inited) {
1249 pthread_mutex_destroy(&iter->mutex);
1250 }
1251 if (iter_allocated) {
1252 free(iter);
1253 }
1254 }
1255 if (st != NULL) {
1256 *st = tst;
1257 }
1258 return rc;
1259 }
1260
1261
1262 /*
1263 * pts_GroupMemberListBegin - begin iterating over the list of members
1264 * of a particular group.
1265 *
1266 * PARAMETERS
1267 *
1268 * IN cellHandle - a previously opened cellHandle that corresponds
1269 * to the cell where the group exists.
1270 *
1271 * IN groupName - the group whose members will be returned.
1272 *
1273 * OUT iterationIdP - upon successful completion contains a iterator that
1274 * can be passed to pts_GroupMemberListNext.
1275 *
1276 * LOCKS
1277 *
1278 * No locks are obtained or released by this function
1279 *
1280 * RETURN CODES
1281 *
1282 * Returns != 0 upon successful completion.
1283 *
1284 */
1285
1286 int ADMINAPI
1287 pts_GroupMemberListBegin(const void *cellHandle, const char *groupName,
1288 void **iterationIdP, afs_status_p st)
1289 {
1290 return MemberListBegin(cellHandle, groupName, ADMPTSGROUPNAMENULL,
1291 ADMPTSGROUPNAMETOOLONG, iterationIdP, st);
1292 }
1293
1294 /*
1295 * pts_GroupMemberListNext - get the next member of a group
1296 *
1297 * PARAMETERS
1298 *
1299 * IN iterationId - an iterator previously returned by pts_GroupMemberListBegin
1300 *
1301 * OUT memberName - upon successful completion contains the next member of
1302 * a group.
1303 *
1304 * LOCKS
1305 *
1306 * The iterator mutex is held during the retrieval of the next member.
1307 *
1308 * RETURN CODES
1309 *
1310 * Returns != 0 upon successful completion.
1311 *
1312 */
1313
1314 int ADMINAPI
1315 pts_GroupMemberListNext(const void *iterationId, char *memberName,
1316 afs_status_p st)
1317 {
1318 int rc = 0;
1319 afs_status_t tst = 0;
1320 pts_group_member_list_iterator_p iter =
1321 (pts_group_member_list_iterator_p) iterationId;
1322 int mutex_locked = 0;
1323
1324 /*
1325 * Validate arguments
1326 */
1327
1328 if (iter == NULL) {
1329 tst = ADMITERATORNULL;
1330 goto fail_pts_GroupMemberListNext;
1331 }
1332
1333 if (memberName == NULL) {
1334 tst = ADMPTSMEMBERNAMENULL;
1335 goto fail_pts_GroupMemberListNext;
1336 }
1337
1338 /*
1339 * Lock the mutex and check the validity of the iterator
1340 */
1341
1342 if (pthread_mutex_lock(&iter->mutex)) {
1343 tst = ADMMUTEXLOCK;
1344 goto fail_pts_GroupMemberListNext;
1345 }
1346
1347 mutex_locked = 1;
1348
1349 if (!IsValidPtsGroupMemberListIterator(iter, &tst)) {
1350 goto fail_pts_GroupMemberListNext;
1351 }
1352
1353 /*
1354 * Check to see if we've copied out all the data. If we haven't,
1355 * copy another item. If we have, mark the iterator done.
1356 */
1357
1358 if (iter->index >= iter->names.namelist_len) {
1359 tst = ADMITERATORDONE;
1360 goto fail_pts_GroupMemberListNext;
1361 } else {
1362 strcpy(memberName, iter->names.namelist_val[iter->index]);
1363 iter->index++;
1364 }
1365 rc = 1;
1366
1367 fail_pts_GroupMemberListNext:
1368
1369 if (mutex_locked) {
1370 pthread_mutex_unlock(&iter->mutex);
1371 }
1372
1373 if (st != NULL) {
1374 *st = tst;
1375 }
1376 return rc;
1377 }
1378
1379 /*
1380 * pts_GroupMemberListDone - finish using a member list iterator
1381 *
1382 * PARAMETERS
1383 *
1384 * IN iterationId - an iterator previously returned by pts_GroupMemberListBegin
1385 *
1386 * LOCKS
1387 *
1388 * The iterator is locked and then destroyed
1389 *
1390 * RETURN CODES
1391 *
1392 * Returns != 0 upon successful completion.
1393 *
1394 * ASSUMPTIONS
1395 *
1396 * It is the user's responsibility to make sure pts_GroupMemberListDone
1397 * is called only once for each iterator.
1398 */
1399
1400 int ADMINAPI
1401 pts_GroupMemberListDone(const void *iterationId, afs_status_p st)
1402 {
1403 int rc = 0;
1404 afs_status_t tst = 0;
1405 pts_group_member_list_iterator_p iter =
1406 (pts_group_member_list_iterator_p) iterationId;
1407 int mutex_locked = 0;
1408
1409 /*
1410 * Validate arguments
1411 */
1412
1413 if (iter == NULL) {
1414 tst = ADMITERATORNULL;
1415 goto fail_pts_GroupMemberListDone;
1416 }
1417
1418 /*
1419 * Lock the mutex and check the validity of the iterator
1420 */
1421
1422 if (pthread_mutex_lock(&iter->mutex)) {
1423 tst = ADMMUTEXLOCK;
1424 goto fail_pts_GroupMemberListDone;
1425 }
1426
1427 mutex_locked = 1;
1428
1429 if (!IsValidPtsGroupMemberListIterator(iter, &tst)) {
1430 goto fail_pts_GroupMemberListDone;
1431 }
1432
1433 /*
1434 * Free the namelist and the iterator.
1435 */
1436
1437 pthread_mutex_destroy(&iter->mutex);
1438 mutex_locked = 0;
1439 iter->is_valid = 0;
1440 free(iter->names.namelist_val);
1441 free(iter);
1442 rc = 1;
1443
1444 fail_pts_GroupMemberListDone:
1445
1446 if (mutex_locked) {
1447 pthread_mutex_unlock(&iter->mutex);
1448 }
1449
1450 if (st != NULL) {
1451 *st = tst;
1452 }
1453 return rc;
1454 }
1455
1456 /*
1457 * pts_GroupMemberRemove - remove a member from a group.
1458 *
1459 * PARAMETERS
1460 *
1461 * IN cellHandle - a previously opened cellHandle that corresponds
1462 * to the cell where the group exists.
1463 *
1464 * IN userName - the user to remove.
1465 *
1466 * IN groupName - the group to modify
1467 *
1468 * LOCKS
1469 *
1470 * No locks are held by this function
1471 *
1472 * RETURN CODES
1473 *
1474 * Returns != 0 upon successful completion.
1475 *
1476 */
1477
1478 int ADMINAPI
1479 pts_GroupMemberRemove(const void *cellHandle, const char *userName,
1480 const char *groupName, afs_status_p st)
1481 {
1482 int rc = 0;
1483 afs_status_t tst = 0;
1484 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1485 idlist ids;
1486
1487 ids.idlist_val = NULL;
1488
1489 /*
1490 * Validate arguments
1491 */
1492
1493 if (!IsValidCellHandle(c_handle, &tst)) {
1494 goto fail_pts_GroupMemberRemove;
1495 }
1496
1497 if ((userName == NULL) || (*userName == 0)) {
1498 tst = ADMPTSUSERNAMENULL;
1499 goto fail_pts_GroupMemberRemove;
1500 }
1501
1502 if ((groupName == NULL) || (*groupName == 0)) {
1503 tst = ADMPTSGROUPNAMENULL;
1504 goto fail_pts_GroupMemberRemove;
1505 }
1506
1507 if (!TranslateTwoNames
1508 (c_handle, userName, ADMPTSUSERNAMETOOLONG, groupName,
1509 ADMPTSGROUPNAMETOOLONG, &ids, &tst)) {
1510 goto fail_pts_GroupMemberRemove;
1511 }
1512
1513 /*
1514 * Make the rpc
1515 */
1516
1517 tst =
1518 ubik_PR_RemoveFromGroup(c_handle->pts, 0, ids.idlist_val[0],
1519 ids.idlist_val[1]);
1520
1521 if (tst != 0) {
1522 goto fail_pts_GroupMemberRemove;
1523 }
1524 rc = 1;
1525
1526 fail_pts_GroupMemberRemove:
1527
1528 if (ids.idlist_val != 0) {
1529 free(ids.idlist_val);
1530 }
1531
1532 if (st != NULL) {
1533 *st = tst;
1534 }
1535 return rc;
1536 }
1537
1538 /*
1539 * pts_GroupRename - change the name of a group
1540 *
1541 * PARAMETERS
1542 *
1543 * IN cellHandle - a previously opened cellHandle that corresponds
1544 * to the cell where the group exists.
1545 *
1546 * IN oldName - the current group name
1547 *
1548 * IN newName - the new group name
1549 *
1550 * LOCKS
1551 *
1552 * No locks are held by this function
1553 *
1554 * RETURN CODES
1555 *
1556 * Returns != 0 upon successful completion.
1557 *
1558 */
1559
1560 int ADMINAPI
1561 pts_GroupRename(const void *cellHandle, const char *oldName,
1562 char *newName, afs_status_p st)
1563 {
1564 int rc = 0;
1565 afs_status_t tst = 0;
1566 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1567 afs_int32 groupId = 0;
1568
1569 /*
1570 * Validate arguments
1571 */
1572
1573 if (!IsValidCellHandle(c_handle, &tst)) {
1574 goto fail_pts_GroupRename;
1575 }
1576
1577 if ((newName == NULL) || (*newName == 0)) {
1578 tst = ADMPTSNEWNAMENULL;
1579 goto fail_pts_GroupRename;
1580 }
1581
1582 if ((oldName == NULL) || (*oldName == 0)) {
1583 tst = ADMPTSOLDNAMENULL;
1584 goto fail_pts_GroupRename;
1585 }
1586
1587 /*
1588 * Translate the group name into an id.
1589 */
1590
1591 if (!TranslateOneName
1592 (c_handle, oldName, ADMPTSOLDNAMETOOLONG, &groupId, &tst)) {
1593 goto fail_pts_GroupRename;
1594 }
1595
1596 /*
1597 * Make the rpc
1598 */
1599
1600 tst = ubik_PR_ChangeEntry(c_handle->pts, 0, groupId, newName, 0, 0);
1601
1602 if (tst != 0) {
1603 goto fail_pts_GroupRename;
1604 }
1605 rc = 1;
1606
1607 fail_pts_GroupRename:
1608
1609 if (st != NULL) {
1610 *st = tst;
1611 }
1612 return rc;
1613 }
1614
1615 /*
1616 * SetGroupAccess - translate our Access notation to pts flags.
1617 *
1618 * PARAMETERS
1619 *
1620 * IN rights - the permissions.
1621 *
1622 * OUT flags - a pointer to an afs_int32 structure that
1623 * contains the flags to pass to pts.
1624 *
1625 * LOCKS
1626 *
1627 * No locks are held by this function
1628 *
1629 * RETURN CODES
1630 *
1631 * Returns != 0 upon successful completion.
1632 *
1633 */
1634
1635 static int
1636 SetGroupAccess(const pts_GroupUpdateEntry_p rights, afs_int32 * flags,
1637 afs_status_p st)
1638 {
1639 int rc = 0;
1640 afs_status_t tst = 0;
1641
1642 *flags = 0;
1643
1644 if (rights->listDelete == PTS_GROUP_ACCESS) {
1645 *flags |= 1;
1646 } else if (rights->listDelete == PTS_GROUP_ANYUSER_ACCESS) {
1647 tst = ADMPTSINVALIDGROUPDELETEPERM;
1648 goto fail_SetGroupAccess;
1649 }
1650
1651 if (rights->listAdd == PTS_GROUP_ACCESS) {
1652 *flags |= 2;
1653 } else if (rights->listAdd == PTS_GROUP_ANYUSER_ACCESS) {
1654 *flags |= 4;
1655 }
1656
1657 if (rights->listMembership == PTS_GROUP_ACCESS) {
1658 *flags |= 8;
1659 } else if (rights->listMembership == PTS_GROUP_ANYUSER_ACCESS) {
1660 *flags |= 16;
1661 }
1662
1663 if (rights->listGroupsOwned == PTS_GROUP_ANYUSER_ACCESS) {
1664 *flags |= 32;
1665 } else if (rights->listGroupsOwned == PTS_GROUP_ACCESS) {
1666 tst = ADMPTSINVALIDGROUPSOWNEDPERM;
1667 goto fail_SetGroupAccess;
1668 }
1669
1670 if (rights->listStatus == PTS_GROUP_ACCESS) {
1671 *flags |= 64;
1672 } else if (rights->listStatus == PTS_GROUP_ANYUSER_ACCESS) {
1673 *flags |= 128;
1674 }
1675 rc = 1;
1676
1677 fail_SetGroupAccess:
1678
1679 if (st != NULL) {
1680 *st = tst;
1681 }
1682 return rc;
1683 }
1684
1685 /*
1686 * pts_GroupModify - change the contents of a group entry.
1687 *
1688 * PARAMETERS
1689 *
1690 * IN cellHandle - a previously opened cellHandle that corresponds
1691 * to the cell where the group exists.
1692 *
1693 * IN groupName - the group to change
1694 *
1695 * OUT newEntryP - a pointer to a pts_GroupUpdateEntry_t structure that
1696 * contains the new information for the group.
1697 *
1698 * LOCKS
1699 *
1700 * No locks are held by this function
1701 *
1702 * RETURN CODES
1703 *
1704 * Returns != 0 upon successful completion.
1705 *
1706 */
1707
1708 int ADMINAPI
1709 pts_GroupModify(const void *cellHandle, const char *groupName,
1710 const pts_GroupUpdateEntry_p newEntryP, afs_status_p st)
1711 {
1712 int rc = 0;
1713 afs_status_t tst = 0;
1714 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1715 afs_int32 groupId = 0;
1716 afs_int32 flags = 0;
1717
1718 /*
1719 * Validate arguments
1720 */
1721
1722 if (!IsValidCellHandle(c_handle, &tst)) {
1723 goto fail_pts_GroupModify;
1724 }
1725
1726 if ((groupName == NULL) || (*groupName == 0)) {
1727 tst = ADMPTSGROUPNAMENULL;
1728 goto fail_pts_GroupModify;
1729 }
1730
1731
1732 if (newEntryP == NULL) {
1733 tst = ADMPTSNEWENTRYPNULL;
1734 goto fail_pts_GroupModify;
1735 }
1736
1737 /*
1738 * Translate the group name into an id.
1739 */
1740
1741 if (!TranslateOneName
1742 (c_handle, groupName, ADMPTSGROUPNAMETOOLONG, &groupId, &tst)) {
1743 goto fail_pts_GroupModify;
1744 }
1745
1746 /*
1747 * Set the flags argument
1748 */
1749
1750 if (!SetGroupAccess(newEntryP, &flags, &tst)) {
1751 goto fail_pts_GroupModify;
1752 }
1753
1754 /*
1755 * Make the rpc
1756 */
1757
1758 tst =
1759 ubik_PR_SetFieldsEntry(c_handle->pts, 0, groupId, PR_SF_ALLBITS,
1760 flags, 0, 0, 0, 0);
1761
1762 if (tst != 0) {
1763 goto fail_pts_GroupModify;
1764 }
1765 rc = 1;
1766
1767 fail_pts_GroupModify:
1768
1769 if (st != NULL) {
1770 *st = tst;
1771 }
1772 return rc;
1773 }
1774
1775 /*
1776 * pts_UserCreate - create a new user.
1777 *
1778 * PARAMETERS
1779 *
1780 * IN cellHandle - a previously opened cellHandle that corresponds
1781 * to the cell where the group exists.
1782 *
1783 * IN newUser - the name of the new user.
1784 *
1785 * IN newUserId - the id to assign to the new user. Pass 0 to have the
1786 * id assigned by pts.
1787 *
1788 * LOCKS
1789 *
1790 * No locks are held by this function
1791 *
1792 * RETURN CODES
1793 *
1794 * Returns != 0 upon successful completion.
1795 *
1796 */
1797
1798 int ADMINAPI
1799 pts_UserCreate(const void *cellHandle, char *userName, int *newUserId,
1800 afs_status_p st)
1801 {
1802 int rc = 0;
1803 afs_status_t tst = 0;
1804 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1805
1806 /*
1807 * Validate arguments
1808 */
1809
1810 if (!IsValidCellHandle(c_handle, &tst)) {
1811 goto fail_pts_UserCreate;
1812 }
1813
1814 if ((userName == NULL) || (*userName == 0)) {
1815 tst = ADMPTSUSERNAMENULL;
1816 goto fail_pts_UserCreate;
1817 }
1818
1819 if (newUserId == NULL) {
1820 tst = ADMPTSNEWUSERIDNULL;
1821 goto fail_pts_UserCreate;
1822 }
1823
1824 /*
1825 * We make a different rpc based upon the input to this function
1826 */
1827
1828 if (*newUserId != 0) {
1829 tst =
1830 ubik_PR_INewEntry(c_handle->pts, 0, userName, *newUserId,
1831 0);
1832 } else {
1833 tst =
1834 ubik_PR_NewEntry(c_handle->pts, 0, userName, 0, 0,
1835 newUserId);
1836 }
1837
1838 if (tst != 0) {
1839 goto fail_pts_UserCreate;
1840 }
1841 rc = 1;
1842
1843 fail_pts_UserCreate:
1844
1845 if (st != NULL) {
1846 *st = tst;
1847 }
1848 return rc;
1849 }
1850
1851 /*
1852 * pts_UserDelete - delete a user.
1853 *
1854 * PARAMETERS
1855 *
1856 * IN cellHandle - a previously opened cellHandle that corresponds
1857 * to the cell where the group exists.
1858 *
1859 * IN user - the name of the user to delete.
1860 *
1861 * LOCKS
1862 *
1863 * No locks are held by this function
1864 *
1865 * RETURN CODES
1866 *
1867 * Returns != 0 upon successful completion.
1868 *
1869 */
1870
1871 int ADMINAPI
1872 pts_UserDelete(const void *cellHandle, const char *userName, afs_status_p st)
1873 {
1874 return EntryDelete(cellHandle, userName, ADMPTSUSERNAMENULL,
1875 ADMPTSUSERNAMETOOLONG, st);
1876 }
1877
1878
1879 /*
1880 * GetUserAccess - a small convenience function for setting
1881 * permissions.
1882 *
1883 * PARAMETERS
1884 *
1885 * IN access - a pointer to a pts_userAccess_t to be set with the
1886 * correct permission.
1887 *
1888 * IN flag - the current permission flag used to derive the permission.
1889 *
1890 * LOCKS
1891 *
1892 * No locks are obtained or released by this function
1893 *
1894 * RETURN CODES
1895 *
1896 * Since this function cannot fail, it returns void.
1897 *
1898 */
1899
1900 static void
1901 GetUserAccess(pts_userAccess_p access, afs_int32 flag)
1902 {
1903
1904 *access = PTS_USER_OWNER_ACCESS;
1905 if (flag == 2) {
1906 *access = PTS_USER_ANYUSER_ACCESS;
1907 }
1908 }
1909
1910 /*
1911 * IsAdministrator - determine if a user is an administrator.
1912 *
1913 * PARAMETERS
1914 *
1915 * IN cellHandle - a previously opened cellHandle that corresponds
1916 * to the cell where the group exists.
1917 *
1918 * IN userEntry - the user data for the user in question.
1919 *
1920 * OUT admin - set to 1 if the user is an administrator, 0 otherwise.
1921 *
1922 * LOCKS
1923 *
1924 * No locks are held by this function
1925 *
1926 * RETURN CODES
1927 *
1928 * Returns != 0 upon successful completion.
1929 *
1930 */
1931
1932 static int
1933 IsAdministrator(const afs_cell_handle_p c_handle, afs_int32 userId,
1934 int *admin, afs_status_p st)
1935 {
1936 int rc = 0;
1937 afs_status_t tst = 0;
1938 afs_int32 adminId = 0;
1939 afs_int32 isAdmin = 0;
1940
1941 *admin = 0;
1942
1943 if (userId == SYSADMINID) {
1944 *admin = 1;
1945 } else {
1946 if (!TranslateOneName
1947 (c_handle, "system:administrators", ADMPTSGROUPNAMETOOLONG,
1948 &adminId, &tst)) {
1949 goto fail_IsAdministrator;
1950 }
1951 tst =
1952 ubik_PR_IsAMemberOf(c_handle->pts, 0, userId, adminId,
1953 &isAdmin);
1954 if (tst != 0) {
1955 goto fail_IsAdministrator;
1956 }
1957 if (isAdmin) {
1958 *admin = 1;
1959 }
1960 }
1961 rc = 1;
1962
1963 fail_IsAdministrator:
1964
1965 if (st != NULL) {
1966 *st = tst;
1967 }
1968 return rc;
1969 }
1970
1971 /*
1972 * pts_UserGet - retrieve information about a particular user.
1973 *
1974 * PARAMETERS
1975 *
1976 * IN cellHandle - a previously opened cellHandle that corresponds
1977 * to the cell where the group exists.
1978 *
1979 * IN userName - the name of the user to retrieve.
1980 *
1981 * OUT userP - a pointer to a pts_UserEntry_t that is filled upon successful
1982 * completion.
1983 *
1984 * LOCKS
1985 *
1986 * No locks are held by this function
1987 *
1988 * RETURN CODES
1989 *
1990 * Returns != 0 upon successful completion.
1991 *
1992 */
1993
1994 int ADMINAPI
1995 pts_UserGet(const void *cellHandle, const char *userName,
1996 pts_UserEntry_p userP, afs_status_p st)
1997 {
1998 int rc = 0;
1999 afs_status_t tst = 0;
2000 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
2001 struct prcheckentry userEntry;
2002 afs_int32 userId = 0;
2003 afs_int32 flags;
2004 afs_int32 twobit;
2005 idlist ids;
2006 afs_int32 ptsids[2];
2007 namelist names;
2008 int admin = 0;
2009
2010
2011 /*
2012 * Validate arguments
2013 */
2014
2015 if (!IsValidCellHandle(c_handle, &tst)) {
2016 goto fail_pts_UserGet;
2017 }
2018
2019 if ((userName == NULL) || (*userName == 0)) {
2020 tst = ADMPTSUSERNAMENULL;
2021 goto fail_pts_UserGet;
2022 }
2023
2024 if (userP == NULL) {
2025 tst = ADMPTSUSERPNULL;
2026 goto fail_pts_UserGet;
2027 }
2028
2029 /*
2030 * Translate the group name into an id.
2031 */
2032
2033 if (!TranslateOneName
2034 (c_handle, userName, ADMPTSUSERNAMETOOLONG, &userId, &tst)) {
2035 goto fail_pts_UserGet;
2036 }
2037
2038 /*
2039 * Retrieve information about the group
2040 */
2041
2042 tst = ubik_PR_ListEntry(c_handle->pts, 0, userId, &userEntry);
2043
2044 if (tst != 0) {
2045 goto fail_pts_UserGet;
2046 }
2047
2048 userP->groupMembershipCount = userEntry.count;
2049 userP->groupCreationQuota = userEntry.ngroups;
2050 /*
2051 * The administrator id, or any member of "system:administrators"
2052 * has unlimited group creation quota. Denote this by setting
2053 * quota to -1.
2054 */
2055
2056 if (!IsAdministrator(c_handle, userEntry.id, &admin, &tst)) {
2057 goto fail_pts_UserGet;
2058 }
2059
2060 if (admin != 0) {
2061 userP->groupCreationQuota = -1;
2062 }
2063
2064 userP->nameUid = userEntry.id;
2065 userP->ownerUid = userEntry.owner;
2066 userP->creatorUid = userEntry.creator;
2067 strncpy(userP->name, userEntry.name, PTS_MAX_NAME_LEN);
2068 userP->name[PTS_MAX_NAME_LEN - 1] = '\0';
2069
2070 /*
2071 * The permission bits are described in the GroupGet function above.
2072 * The user entry only uses 3 of the 5 permissions, so we shift
2073 * past the unused entries.
2074 */
2075
2076 flags = userEntry.flags;
2077 flags = flags >> 3;
2078 twobit = flags & 3;
2079
2080 GetUserAccess(&userP->listMembership, twobit);
2081
2082 flags = flags >> 2;
2083
2084 if (flags & 1) {
2085 userP->listGroupsOwned = PTS_USER_ANYUSER_ACCESS;
2086 } else {
2087 userP->listGroupsOwned = PTS_USER_OWNER_ACCESS;
2088 }
2089
2090 flags = flags >> 1;
2091 twobit = flags & 3;
2092
2093 GetUserAccess(&userP->listStatus, twobit);
2094
2095 /*
2096 * Make another rpc and translate the owner and creator ids into
2097 * character strings.
2098 */
2099
2100 ids.idlist_len = 2;
2101 ids.idlist_val = ptsids;
2102 ptsids[0] = userEntry.owner;
2103 ptsids[1] = userEntry.creator;
2104 names.namelist_len = 0;
2105 names.namelist_val = 0;
2106
2107
2108 if (!TranslatePTSIds(c_handle, &names, &ids, &tst)) {
2109 goto fail_pts_UserGet;
2110 }
2111
2112 strncpy(userP->owner, names.namelist_val[0], PTS_MAX_NAME_LEN);
2113 userP->owner[PTS_MAX_NAME_LEN - 1] ='\0';
2114 strncpy(userP->creator, names.namelist_val[1], PTS_MAX_NAME_LEN);
2115 userP->creator[PTS_MAX_NAME_LEN - 1] = '\0';
2116 free(names.namelist_val);
2117 rc = 1;
2118
2119 fail_pts_UserGet:
2120
2121 if (st != NULL) {
2122 *st = tst;
2123 }
2124 return rc;
2125 }
2126
2127 /*
2128 * pts_UserRename - rename a user.
2129 *
2130 * PARAMETERS
2131 *
2132 * IN cellHandle - a previously opened cellHandle that corresponds
2133 * to the cell where the group exists.
2134 *
2135 * IN oldName - the name of the user to rename.
2136 *
2137 * IN newName - the new user name.
2138 *
2139 * LOCKS
2140 *
2141 * No locks are held by this function
2142 *
2143 * RETURN CODES
2144 *
2145 * Returns != 0 upon successful completion.
2146 *
2147 */
2148
2149 int ADMINAPI
2150 pts_UserRename(const void *cellHandle, const char *oldName,
2151 char *newName, afs_status_p st)
2152 {
2153 int rc = 0;
2154 afs_status_t tst = 0;
2155 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
2156 afs_int32 userId = 0;
2157
2158 /*
2159 * Validate arguments
2160 */
2161
2162 if (!IsValidCellHandle(c_handle, &tst)) {
2163 goto fail_pts_UserRename;
2164 }
2165
2166 if ((oldName == NULL) || (*oldName == 0)) {
2167 tst = ADMPTSOLDNAMENULL;
2168 goto fail_pts_UserRename;
2169 }
2170
2171 if ((newName == NULL) || (*newName == 0)) {
2172 tst = ADMPTSNEWNAMENULL;
2173 goto fail_pts_UserRename;
2174 }
2175
2176 /*
2177 * Translate the user name into an id.
2178 */
2179
2180 if (!TranslateOneName
2181 (c_handle, oldName, ADMPTSOLDNAMETOOLONG, &userId, &tst)) {
2182 goto fail_pts_UserRename;
2183 }
2184
2185 /*
2186 * Make the rpc
2187 */
2188
2189 tst = ubik_PR_ChangeEntry(c_handle->pts, 0, userId, newName, 0, 0);
2190
2191 if (tst != 0) {
2192 goto fail_pts_UserRename;
2193 }
2194 rc = 1;
2195
2196 fail_pts_UserRename:
2197
2198 if (st != NULL) {
2199 *st = tst;
2200 }
2201 return rc;
2202 }
2203
2204 /*
2205 * SetUserAccess - translate our Access notation to pts flags.
2206 *
2207 * PARAMETERS
2208 *
2209 * IN userP - the user structure that contains the new permissions.
2210 *
2211 * OUT flags - a pointer to an afs_int32 structure that
2212 * contains the flags to pass to pts.
2213 *
2214 * LOCKS
2215 *
2216 * No locks are held by this function
2217 *
2218 * RETURN CODES
2219 *
2220 * Returns != 0 upon successful completion.
2221 *
2222 */
2223
2224 static int
2225 SetUserAccess(const pts_UserUpdateEntry_p userP, afs_int32 * flags,
2226 afs_status_p st)
2227 {
2228 int rc = 0;
2229 afs_status_t tst = 0;
2230
2231 *flags = 0;
2232
2233 if (userP->listMembership == PTS_USER_ANYUSER_ACCESS) {
2234 *flags |= 16;
2235 }
2236
2237 if (userP->listGroupsOwned == PTS_USER_ANYUSER_ACCESS) {
2238 *flags |= 32;
2239 }
2240
2241 if (userP->listStatus == PTS_USER_ANYUSER_ACCESS) {
2242 *flags |= 128;
2243 }
2244 rc = 1;
2245
2246 if (st != NULL) {
2247 *st = tst;
2248 }
2249 return rc;
2250 }
2251
2252
2253 /*
2254 * pts_UserModify - update a user entry.
2255 *
2256 * PARAMETERS
2257 *
2258 * IN cellHandle - a previously opened cellHandle that corresponds
2259 * to the cell where the group exists.
2260 *
2261 * IN userName - the name of the user to update.
2262 *
2263 * IN newEntryP - a pointer to a pts_UserUpdateEntry_t that contains the
2264 * new information for user.
2265 *
2266 * LOCKS
2267 *
2268 * No locks are held by this function
2269 *
2270 * RETURN CODES
2271 *
2272 * Returns != 0 upon successful completion.
2273 *
2274 */
2275
2276 int ADMINAPI
2277 pts_UserModify(const void *cellHandle, const char *userName,
2278 const pts_UserUpdateEntry_p newEntryP, afs_status_p st)
2279 {
2280 int rc = 0;
2281 afs_status_t tst = 0;
2282 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
2283 afs_int32 userId = 0;
2284 afs_int32 newQuota = 0;
2285 afs_int32 mask = 0;
2286 afs_int32 flags = 0;
2287
2288 /*
2289 * Validate arguments
2290 */
2291
2292 if (!IsValidCellHandle(c_handle, &tst)) {
2293 goto fail_pts_UserModify;
2294 }
2295
2296 if ((userName == NULL) || (*userName == 0)) {
2297 tst = ADMPTSUSERNAMENULL;
2298 goto fail_pts_UserModify;
2299 }
2300
2301 if (newEntryP == NULL) {
2302 tst = ADMPTSNEWENTRYPNULL;
2303 goto fail_pts_UserModify;
2304 }
2305
2306 /*
2307 * Translate the user name into an id.
2308 */
2309
2310 if (!TranslateOneName
2311 (c_handle, userName, ADMPTSUSERNAMETOOLONG, &userId, &tst)) {
2312 goto fail_pts_UserModify;
2313 }
2314
2315
2316 if (newEntryP->flag & PTS_USER_UPDATE_GROUP_CREATE_QUOTA) {
2317 mask |= PR_SF_NGROUPS;
2318 newQuota = newEntryP->groupCreationQuota;
2319 }
2320
2321 if (newEntryP->flag & PTS_USER_UPDATE_PERMISSIONS) {
2322 mask |= PR_SF_ALLBITS;
2323 if (!SetUserAccess(newEntryP, &flags, &tst)) {
2324 goto fail_pts_UserModify;
2325 }
2326 }
2327
2328 /*
2329 * Make the rpc
2330 */
2331
2332 tst =
2333 ubik_PR_SetFieldsEntry(c_handle->pts, 0, userId, mask, flags,
2334 newQuota, 0, 0, 0);
2335
2336 if (tst != 0) {
2337 goto fail_pts_UserModify;
2338 }
2339 rc = 1;
2340
2341 fail_pts_UserModify:
2342
2343 if (st != NULL) {
2344 *st = tst;
2345 }
2346 return rc;
2347 }
2348
2349 /*
2350 * pts_UserMaxGet - get the maximum in use user id.
2351 *
2352 * PARAMETERS
2353 *
2354 * IN cellHandle - a previously opened cellHandle that corresponds
2355 * to the cell where the group exists.
2356 *
2357 * OUT maxUserId - upon successful completion contains the max in use id.
2358 *
2359 * LOCKS
2360 *
2361 * No locks are held by this function
2362 *
2363 * RETURN CODES
2364 *
2365 * Returns != 0 upon successful completion.
2366 *
2367 */
2368
2369 int ADMINAPI
2370 pts_UserMaxGet(const void *cellHandle, int *maxUserId, afs_status_p st)
2371 {
2372 int rc = 0;
2373 afs_status_t tst = 0;
2374 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
2375 afs_int32 maxGroupId = 0;
2376
2377 /*
2378 * Validate arguments
2379 */
2380
2381 if (!IsValidCellHandle(c_handle, &tst)) {
2382 goto fail_pts_UserMaxGet;
2383 }
2384
2385 if (maxUserId == NULL) {
2386 tst = ADMPTSMAXUSERIDNULL;
2387 goto fail_pts_UserMaxGet;
2388 }
2389
2390 tst = ubik_PR_ListMax(c_handle->pts, 0, maxUserId, &maxGroupId);
2391
2392 if (tst != 0) {
2393 goto fail_pts_UserMaxGet;
2394 }
2395 rc = 1;
2396
2397 fail_pts_UserMaxGet:
2398
2399 if (st != NULL) {
2400 *st = tst;
2401 }
2402 return rc;
2403 }
2404
2405 /*
2406 * pts_UserMaxSet - set the maximum user id.
2407 *
2408 * PARAMETERS
2409 *
2410 * IN cellHandle - a previously opened cellHandle that corresponds
2411 * to the cell where the group exists.
2412 *
2413 * IN maxUserId - the new max user id.
2414 *
2415 * LOCKS
2416 *
2417 * No locks are held by this function
2418 *
2419 * RETURN CODES
2420 *
2421 * Returns != 0 upon successful completion.
2422 *
2423 */
2424
2425 int ADMINAPI
2426 pts_UserMaxSet(const void *cellHandle, int maxUserId, afs_status_p st)
2427 {
2428 int rc = 0;
2429 afs_status_t tst = 0;
2430 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
2431
2432 /*
2433 * Validate arguments
2434 */
2435
2436 if (!IsValidCellHandle(c_handle, &tst)) {
2437 goto fail_pts_UserMaxSet;
2438 }
2439
2440 tst = ubik_PR_SetMax(c_handle->pts, 0, maxUserId, 0);
2441
2442 if (tst != 0) {
2443 goto fail_pts_UserMaxSet;
2444 }
2445 rc = 1;
2446
2447 fail_pts_UserMaxSet:
2448
2449 if (st != NULL) {
2450 *st = tst;
2451 }
2452 return rc;
2453 }
2454
2455 /*
2456 * pts_UserMemberListBegin - begin iterating over the list of groups
2457 * a particular user belongs to.
2458 *
2459 * PARAMETERS
2460 *
2461 * IN cellHandle - a previously opened cellHandle that corresponds
2462 * to the cell where the group exists.
2463 *
2464 * IN groupName - the group whose members will be returned.
2465 *
2466 * OUT iterationIdP - upon successful completion contains a iterator that
2467 * can be passed to pts_GroupMemberListNext.
2468 *
2469 * LOCKS
2470 *
2471 * No locks are obtained or released by this function
2472 *
2473 * RETURN CODES
2474 *
2475 * Returns != 0 upon successful completion.
2476 *
2477 */
2478
2479 int ADMINAPI
2480 pts_UserMemberListBegin(const void *cellHandle, const char *userName,
2481 void **iterationIdP, afs_status_p st)
2482 {
2483 return MemberListBegin(cellHandle, userName, ADMPTSUSERNAMENULL,
2484 ADMPTSUSERNAMETOOLONG, iterationIdP, st);
2485
2486 }
2487
2488 /*
2489 * pts_UserMemberListNext - get the next group a user belongs to
2490 *
2491 * PARAMETERS
2492 *
2493 * IN iterationId - an iterator previously returned by pts_UserMemberListBegin
2494 *
2495 * OUT userName - upon successful completion contains the next group a user
2496 * belongs to.
2497 *
2498 * LOCKS
2499 *
2500 * The iterator mutex is held during the retrieval of the next member.
2501 *
2502 * RETURN CODES
2503 *
2504 * Returns != 0 upon successful completion.
2505 *
2506 */
2507
2508 int ADMINAPI
2509 pts_UserMemberListNext(const void *iterationId, char *userName,
2510 afs_status_p st)
2511 {
2512 return pts_GroupMemberListNext(iterationId, userName, st);
2513 }
2514
2515 /*
2516 * pts_UserMemberListDone - finish using a user list iterator
2517 *
2518 * PARAMETERS
2519 *
2520 * IN iterationId - an iterator previously returned by pts_UserMemberListBegin
2521 *
2522 * LOCKS
2523 *
2524 * The iterator is locked and then destroyed
2525 *
2526 * RETURN CODES
2527 *
2528 * Returns != 0 upon successful completion.
2529 *
2530 * ASSUMPTIONS
2531 *
2532 * It is the user's responsibility to make sure pts_UserMemberListDone
2533 * is called only once for each iterator.
2534 */
2535
2536 int ADMINAPI
2537 pts_UserMemberListDone(const void *iterationId, afs_status_p st)
2538 {
2539 return pts_GroupMemberListDone(iterationId, st);
2540 }
2541
2542 typedef struct owned_group_list {
2543 namelist owned_names; /* the list of character names owned by this id */
2544 prlist owned_ids; /* the list of pts ids owned by this id */
2545 afs_int32 index; /* the index into owned_names for the next group */
2546 afs_int32 owner; /* the pts id of the owner */
2547 afs_int32 more; /* the last parameter to PR_ListOwned */
2548 int finished_retrieving; /* set when we've processed the last owned_names */
2549 afs_cell_handle_p c_handle; /* ubik client to pts server's from c_handle */
2550 char group[CACHED_ITEMS][PTS_MAX_NAME_LEN]; /* cache of names */
2551 } owned_group_list_t, *owned_group_list_p;
2552
2553 static int
2554 DeleteOwnedGroupSpecificData(void *rpc_specific, afs_status_p st)
2555 {
2556 int rc = 0;
2557 afs_status_t tst = 0;
2558 owned_group_list_p list = (owned_group_list_p) rpc_specific;
2559
2560 if (list->owned_names.namelist_val != NULL) {
2561 free(list->owned_names.namelist_val);
2562 }
2563
2564 if (list->owned_ids.prlist_val != NULL) {
2565 free(list->owned_ids.prlist_val);
2566 }
2567 rc = 1;
2568
2569 if (st != NULL) {
2570 *st = tst;
2571 }
2572 return rc;
2573 }
2574
2575 static int
2576 GetOwnedGroupRPC(void *rpc_specific, int slot, int *last_item,
2577 int *last_item_contains_data, afs_status_p st)
2578 {
2579 int rc = 0;
2580 afs_status_t tst = 0;
2581 owned_group_list_p list = (owned_group_list_p) rpc_specific;
2582
2583 /*
2584 * We really don't make an rpc for every entry we return here
2585 * since the pts interface allows several members to be returned
2586 * with one rpc, but we fake it to make the iterator happy.
2587 */
2588
2589 /*
2590 * Check to see if we are done retrieving data
2591 */
2592
2593 if ((list->finished_retrieving) && (list->owned_names.namelist_len == 0)) {
2594 *last_item = 1;
2595 *last_item_contains_data = 0;
2596 goto fail_GetOwnedGroupRPC;
2597 }
2598
2599 /*
2600 * Check to see if we really need to make an rpc
2601 */
2602
2603 if ((!list->finished_retrieving) && (list->owned_names.namelist_len == 0)) {
2604 tst =
2605 ubik_PR_ListOwned(list->c_handle->pts, 0, list->owner,
2606 &list->owned_ids, &list->more);
2607 if (tst != 0) {
2608 goto fail_GetOwnedGroupRPC;
2609 }
2610
2611 if (!TranslatePTSIds
2612 (list->c_handle, &list->owned_names, (idlist *) & list->owned_ids,
2613 &tst)) {
2614 goto fail_GetOwnedGroupRPC;
2615 }
2616 list->index = 0;
2617
2618 if (list->owned_names.namelist_val == NULL) {
2619 *last_item = 1;
2620 *last_item_contains_data = 0;
2621 goto fail_GetOwnedGroupRPC;
2622 }
2623 }
2624
2625 /*
2626 * We can retrieve the next group from data we already received
2627 */
2628
2629 strcpy(list->group[slot], list->owned_names.namelist_val[list->index]);
2630 list->index++;
2631
2632 /*
2633 * Check to see if there is more data to be retrieved
2634 * We need to free up the previously retrieved data here
2635 * and then check to see if the last rpc indicated that there
2636 * were more items to retrieve.
2637 */
2638
2639 if (list->index >= list->owned_names.namelist_len) {
2640 list->owned_names.namelist_len = 0;
2641 free(list->owned_names.namelist_val);
2642 list->owned_names.namelist_val = 0;
2643
2644 list->owned_ids.prlist_len = 0;
2645 free(list->owned_ids.prlist_val);
2646 list->owned_ids.prlist_val = 0;
2647
2648 if (!list->more) {
2649 list->finished_retrieving = 1;
2650 }
2651 }
2652 rc = 1;
2653
2654 fail_GetOwnedGroupRPC:
2655
2656 if (st != NULL) {
2657 *st = tst;
2658 }
2659 return rc;
2660 }
2661
2662 static int
2663 GetOwnedGroupFromCache(void *rpc_specific, int slot, void *dest,
2664 afs_status_p st)
2665 {
2666 int rc = 0;
2667 afs_status_t tst = 0;
2668 owned_group_list_p list = (owned_group_list_p) rpc_specific;
2669
2670 strcpy((char *)dest, list->group[slot]);
2671 rc = 1;
2672
2673 if (st != NULL) {
2674 *st = tst;
2675 }
2676
2677 return rc;
2678 }
2679
2680 /*
2681 * pts_OwnedGroupListBegin - begin iterating over the list of groups
2682 * a particular user owns.
2683 *
2684 * PARAMETERS
2685 *
2686 * IN cellHandle - a previously opened cellHandle that corresponds
2687 * to the cell where the group exists.
2688 *
2689 * IN ownerName - the owner of the groups of interest.
2690 *
2691 * OUT iterationIdP - upon successful completion contains a iterator that
2692 * can be passed to pts_OwnedGroupListNext.
2693 *
2694 * LOCKS
2695 *
2696 * No locks are held by this function
2697 *
2698 * RETURN CODES
2699 *
2700 * Returns != 0 upon successful completion.
2701 *
2702 */
2703
2704 int ADMINAPI
2705 pts_OwnedGroupListBegin(const void *cellHandle, const char *userName,
2706 void **iterationIdP, afs_status_p st)
2707 {
2708 int rc = 0;
2709 afs_status_t tst = 0;
2710 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
2711 afs_admin_iterator_p iter = malloc(sizeof(afs_admin_iterator_t));
2712 owned_group_list_p list = malloc(sizeof(owned_group_list_t));
2713
2714 /*
2715 * Validate arguments
2716 */
2717
2718 if (!IsValidCellHandle(c_handle, &tst)) {
2719 goto fail_pts_OwnedGroupListBegin;
2720 }
2721
2722 if ((userName == NULL) || (*userName == 0)) {
2723 tst = ADMPTSUSERNAMENULL;
2724 goto fail_pts_OwnedGroupListBegin;
2725 }
2726
2727 if (iterationIdP == NULL) {
2728 tst = ADMITERATORNULL;
2729 goto fail_pts_OwnedGroupListBegin;
2730 }
2731
2732 if ((iter == NULL) || (list == NULL)) {
2733 tst = ADMNOMEM;
2734 goto fail_pts_OwnedGroupListBegin;
2735 }
2736
2737 /*
2738 * Initialize the iterator specific data
2739 */
2740
2741 list->index = 0;
2742 list->finished_retrieving = 0;
2743 list->c_handle = c_handle;
2744 list->owned_names.namelist_len = 0;
2745 list->owned_names.namelist_val = 0;
2746 list->owned_ids.prlist_len = 0;
2747 list->owned_ids.prlist_val = 0;
2748
2749 /*
2750 * Translate the user name into an id.
2751 */
2752
2753 if (!TranslateOneName
2754 (c_handle, userName, ADMPTSUSERNAMETOOLONG, &list->owner, &tst)) {
2755 goto fail_pts_OwnedGroupListBegin;
2756 }
2757
2758 if (IteratorInit
2759 (iter, (void *)list, GetOwnedGroupRPC, GetOwnedGroupFromCache, NULL,
2760 DeleteOwnedGroupSpecificData, &tst)) {
2761 *iterationIdP = (void *)iter;
2762 rc = 1;
2763 }
2764
2765 fail_pts_OwnedGroupListBegin:
2766
2767 if (rc == 0) {
2768 if (iter != NULL) {
2769 free(iter);
2770 }
2771 if (list != NULL) {
2772 free(list);
2773 }
2774 }
2775
2776 if (st != NULL) {
2777 *st = tst;
2778 }
2779 return rc;
2780 }
2781
2782 /*
2783 * pts_OwnedGroupListNext - get the next group a user owns.
2784 *
2785 * PARAMETERS
2786 *
2787 * IN iterationId - an iterator previously returned by pts_OwnedGroupListBegin
2788 *
2789 * OUT groupName - upon successful completion contains the next group a user
2790 * owns.
2791 *
2792 * LOCKS
2793 *
2794 * The iterator mutex is held during the retrieval of the next member.
2795 *
2796 * RETURN CODES
2797 *
2798 * Returns != 0 upon successful completion.
2799 *
2800 */
2801
2802 int ADMINAPI
2803 pts_OwnedGroupListNext(const void *iterationId, char *groupName,
2804 afs_status_p st)
2805 {
2806 int rc = 0;
2807 afs_status_t tst = 0;
2808 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2809
2810 /*
2811 * Validate arguments
2812 */
2813
2814 if (iterationId == NULL) {
2815 tst = ADMITERATORNULL;
2816 goto fail_pts_OwnedGroupListNext;
2817 }
2818
2819 if (groupName == NULL) {
2820 tst = ADMPTSGROUPNAMENULL;
2821 goto fail_pts_OwnedGroupListNext;
2822 }
2823
2824 rc = IteratorNext(iter, (void *)groupName, &tst);
2825
2826 fail_pts_OwnedGroupListNext:
2827
2828 if (st != NULL) {
2829 *st = tst;
2830 }
2831 return rc;
2832 }
2833
2834 /*
2835 * pts_OwnedGroupListDone - finish using a group list iterator
2836 *
2837 * PARAMETERS
2838 *
2839 * IN iterationId - an iterator previously returned by pts_OwnedGroupListBegin
2840 *
2841 * LOCKS
2842 *
2843 * The iterator is locked and then destroyed
2844 *
2845 * RETURN CODES
2846 *
2847 * Returns != 0 upon successful completion.
2848 *
2849 * ASSUMPTIONS
2850 *
2851 * It is the user's responsibility to make sure pts_OwnedGroupListDone
2852 * is called only once for each iterator.
2853 */
2854
2855 int ADMINAPI
2856 pts_OwnedGroupListDone(const void *iterationId, afs_status_p st)
2857 {
2858 int rc = 0;
2859 afs_status_t tst = 0;
2860 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2861
2862 /*
2863 * Validate arguments
2864 */
2865
2866 if (iterationId == NULL) {
2867 tst = ADMITERATORNULL;
2868 goto fail_pts_OwnedGroupListDone;
2869 }
2870
2871 rc = IteratorDone(iter, &tst);
2872
2873 fail_pts_OwnedGroupListDone:
2874
2875 if (st != NULL) {
2876 *st = tst;
2877 }
2878 return rc;
2879 }
2880
2881 typedef struct pts_list {
2882 prlistentries *names; /* the current list of pts names in this cell */
2883 prlistentries *currName; /* the current pts entry */
2884 afs_int32 index; /* the index into names for the next pts entry */
2885 afs_int32 nextstartindex; /* the next start index for the RPC */
2886 afs_int32 nentries; /* the number of entries in names */
2887 afs_int32 flag; /* the type of the list */
2888 int finished_retrieving; /* set when we've processed the last owned_names */
2889 afs_cell_handle_p c_handle; /* ubik client to pts server's from c_handle */
2890 char entries[CACHED_ITEMS][PTS_MAX_NAME_LEN]; /* cache of pts names */
2891 } pts_list_t, *pts_list_p;
2892
2893 static int
2894 DeletePTSSpecificData(void *rpc_specific, afs_status_p st)
2895 {
2896 int rc = 0;
2897 afs_status_t tst = 0;
2898 pts_list_p list = (pts_list_p) rpc_specific;
2899
2900 if (list->names) {
2901 free(list->names);
2902 }
2903
2904 rc = 1;
2905
2906 if (st != NULL) {
2907 *st = tst;
2908 }
2909 return rc;
2910 }
2911
2912 static int
2913 GetPTSRPC(void *rpc_specific, int slot, int *last_item,
2914 int *last_item_contains_data, afs_status_p st)
2915 {
2916 int rc = 0;
2917 afs_status_t tst = 0;
2918 pts_list_p list = (pts_list_p) rpc_specific;
2919
2920 /*
2921 * We really don't make an rpc for every entry we return here
2922 * since the pts interface allows several members to be returned
2923 * with one rpc, but we fake it to make the iterator happy.
2924 */
2925
2926 /*
2927 * Check to see if we are done retrieving data
2928 */
2929
2930 if (list->finished_retrieving) {
2931 *last_item = 1;
2932 *last_item_contains_data = 0;
2933 goto fail_GetPTSRPC;
2934 }
2935
2936 /*
2937 * Check to see if we really need to make an rpc
2938 */
2939
2940 if ((!list->finished_retrieving) && (list->index >= list->nentries)) {
2941 afs_int32 start = list->nextstartindex;
2942 prentries bulkentries;
2943 list->nextstartindex = -1;
2944 bulkentries.prentries_val = 0;
2945 bulkentries.prentries_len = 0;
2946
2947 tst =
2948 ubik_PR_ListEntries(list->c_handle->pts, 0, list->flag,
2949 start, &bulkentries, &(list->nextstartindex));
2950
2951 if (tst != 0) {
2952 goto fail_GetPTSRPC;
2953 }
2954
2955 list->nentries = bulkentries.prentries_len;
2956 list->names = bulkentries.prentries_val;
2957
2958 list->index = 0;
2959 list->currName = list->names;
2960
2961 }
2962
2963 /*
2964 * We can retrieve the next entry from data we already received
2965 */
2966
2967 strcpy(list->entries[slot], list->currName->name);
2968 list->index++;
2969 list->currName++;
2970
2971
2972 /*
2973 * Check to see if there is more data to be retrieved
2974 * We need to free up the previously retrieved data here
2975 * and then check to see if the last rpc indicated that there
2976 * were more items to retrieve.
2977 */
2978
2979 if (list->index >= list->nentries) {
2980 if (list->names) {
2981 free(list->names);
2982 }
2983 list->names = NULL;
2984
2985 if (list->nextstartindex == -1) {
2986 list->finished_retrieving = 1;
2987 }
2988 }
2989 rc = 1;
2990
2991 fail_GetPTSRPC:
2992
2993 if (st != NULL) {
2994 *st = tst;
2995 }
2996
2997 return rc;
2998 }
2999
3000 static int
3001 GetPTSFromCache(void *rpc_specific, int slot, void *dest, afs_status_p st)
3002 {
3003 int rc = 0;
3004 afs_status_t tst = 0;
3005 pts_list_p list = (pts_list_p) rpc_specific;
3006
3007 strcpy((char *)dest, list->entries[slot]);
3008 rc = 1;
3009
3010 if (st != NULL) {
3011 *st = tst;
3012 }
3013
3014 return rc;
3015 }
3016
3017 /*
3018 * pts_UserListBegin - begin iterating over the list of users
3019 * in a particular cell
3020 *
3021 * PARAMETERS
3022 *
3023 * IN cellHandle - a previously opened cellHandle that corresponds
3024 * to the cell where the users exist.
3025 *
3026 * OUT iterationIdP - upon successful completion contains a iterator that
3027 * can be passed to pts_UserListNext.
3028 *
3029 * LOCKS
3030 *
3031 * No locks are held by this function
3032 *
3033 * RETURN CODES
3034 *
3035 * Returns != 0 upon successful completion.
3036 *
3037 */
3038
3039 int ADMINAPI
3040 pts_UserListBegin(const void *cellHandle, void **iterationIdP,
3041 afs_status_p st)
3042 {
3043 int rc = 0;
3044 afs_status_t tst = 0;
3045 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
3046 afs_admin_iterator_p iter = malloc(sizeof(afs_admin_iterator_t));
3047 pts_list_p list = malloc(sizeof(pts_list_t));
3048
3049 /*
3050 * Validate arguments
3051 */
3052
3053 if (!IsValidCellHandle(c_handle, &tst)) {
3054 goto fail_pts_UserListBegin;
3055 }
3056
3057 if (iterationIdP == NULL) {
3058 tst = ADMITERATORNULL;
3059 goto fail_pts_UserListBegin;
3060 }
3061
3062 if ((iter == NULL) || (list == NULL)) {
3063 tst = ADMNOMEM;
3064 goto fail_pts_UserListBegin;
3065 }
3066
3067 /*
3068 * Initialize the iterator specific data
3069 */
3070
3071 list->index = 0;
3072 list->finished_retrieving = 0;
3073 list->c_handle = c_handle;
3074 list->names = NULL;
3075 list->nextstartindex = 0;
3076 list->nentries = 0;
3077 list->flag = PRUSERS;
3078
3079 if (IteratorInit
3080 (iter, (void *)list, GetPTSRPC, GetPTSFromCache, NULL,
3081 DeletePTSSpecificData, &tst)) {
3082 *iterationIdP = (void *)iter;
3083 rc = 1;
3084 }
3085
3086 fail_pts_UserListBegin:
3087
3088 if (rc == 0) {
3089 if (iter != NULL) {
3090 free(iter);
3091 }
3092 if (list != NULL) {
3093 free(list);
3094 }
3095 }
3096
3097 if (st != NULL) {
3098 *st = tst;
3099 }
3100 return rc;
3101 }
3102
3103 /*
3104 * pts_UserListNext - get the next user in the cell.
3105 *
3106 * PARAMETERS
3107 *
3108 * IN iterationId - an iterator previously returned by pts_UserListBegin
3109 *
3110 * OUT groupName - upon successful completion contains the next user
3111 *
3112 * LOCKS
3113 *
3114 * The iterator mutex is held during the retrieval of the next member.
3115 *
3116 * RETURN CODES
3117 *
3118 * Returns != 0 upon successful completion.
3119 *
3120 */
3121
3122 int ADMINAPI
3123 pts_UserListNext(const void *iterationId, char *userName, afs_status_p st)
3124 {
3125 int rc = 0;
3126 afs_status_t tst = 0;
3127 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
3128
3129 /*
3130 * Validate arguments
3131 */
3132
3133 if (iterationId == NULL) {
3134 tst = ADMITERATORNULL;
3135 goto fail_pts_UserListNext;
3136 }
3137
3138 if (userName == NULL) {
3139 tst = ADMPTSUSERNAMENULL;
3140 goto fail_pts_UserListNext;
3141 }
3142
3143 rc = IteratorNext(iter, (void *)userName, &tst);
3144
3145 fail_pts_UserListNext:
3146
3147 if (st != NULL) {
3148 *st = tst;
3149 }
3150 return rc;
3151 }
3152
3153 /*
3154 * pts_UserListDone - finish using a user list iterator
3155 *
3156 * PARAMETERS
3157 *
3158 * IN iterationId - an iterator previously returned by pts_UserListBegin
3159 *
3160 * LOCKS
3161 *
3162 * The iterator is locked and then destroyed
3163 *
3164 * RETURN CODES
3165 *
3166 * Returns != 0 upon successful completion.
3167 *
3168 * ASSUMPTIONS
3169 *
3170 * It is the user's responsibility to make sure pts_UserListDone
3171 * is called only once for each iterator.
3172 */
3173
3174 int ADMINAPI
3175 pts_UserListDone(const void *iterationId, afs_status_p st)
3176 {
3177 int rc = 0;
3178 afs_status_t tst = 0;
3179 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
3180
3181 /*
3182 * Validate arguments
3183 */
3184
3185 if (iterationId == NULL) {
3186 tst = ADMITERATORNULL;
3187 goto fail_pts_UserListDone;
3188 }
3189
3190 rc = IteratorDone(iter, &tst);
3191
3192 fail_pts_UserListDone:
3193
3194 if (st != NULL) {
3195 *st = tst;
3196 }
3197 return rc;
3198 }
3199
3200 /*
3201 * pts_GroupListBegin - begin iterating over the list of groups
3202 * in a particular cell.
3203 *
3204 * PARAMETERS
3205 *
3206 * IN cellHandle - a previously opened cellHandle that corresponds
3207 * to the cell where the groups exist.
3208 *
3209 * OUT iterationIdP - upon successful completion contains a iterator that
3210 * can be passed to pts_GroupListNext.
3211 *
3212 * LOCKS
3213 *
3214 * No locks are held by this function
3215 *
3216 * RETURN CODES
3217 *
3218 * Returns != 0 upon successful completion.
3219 *
3220 */
3221
3222 int ADMINAPI
3223 pts_GroupListBegin(const void *cellHandle, void **iterationIdP,
3224 afs_status_p st)
3225 {
3226 int rc = 0;
3227 afs_status_t tst = 0;
3228 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
3229 afs_admin_iterator_p iter = malloc(sizeof(afs_admin_iterator_t));
3230 pts_list_p list = malloc(sizeof(pts_list_t));
3231
3232 /*
3233 * Validate arguments
3234 */
3235
3236 if (!IsValidCellHandle(c_handle, &tst)) {
3237 goto fail_pts_GroupListBegin;
3238 }
3239
3240 if (iterationIdP == NULL) {
3241 tst = ADMITERATORNULL;
3242 goto fail_pts_GroupListBegin;
3243 }
3244
3245 if ((iter == NULL) || (list == NULL)) {
3246 tst = ADMNOMEM;
3247 goto fail_pts_GroupListBegin;
3248 }
3249
3250 /*
3251 * Initialize the iterator specific data
3252 */
3253
3254 list->index = 0;
3255 list->finished_retrieving = 0;
3256 list->c_handle = c_handle;
3257 list->names = NULL;
3258 list->nextstartindex = 0;
3259 list->nentries = 0;
3260 list->flag = PRGROUPS;
3261
3262 if (IteratorInit
3263 (iter, (void *)list, GetPTSRPC, GetPTSFromCache, NULL,
3264 DeletePTSSpecificData, &tst)) {
3265 *iterationIdP = (void *)iter;
3266 rc = 1;
3267 }
3268
3269 fail_pts_GroupListBegin:
3270
3271 if (rc == 0) {
3272 if (iter != NULL) {
3273 free(iter);
3274 }
3275 if (list != NULL) {
3276 free(list);
3277 }
3278 }
3279
3280 if (st != NULL) {
3281 *st = tst;
3282 }
3283 return rc;
3284 }
3285
3286 /*
3287 * pts_UserListNext - get the next group in a cell.
3288 *
3289 * PARAMETERS
3290 *
3291 * IN iterationId - an iterator previously returned by pts_GroupListBegin
3292 *
3293 * OUT groupName - upon successful completion contains the next group
3294 *
3295 * LOCKS
3296 *
3297 * The iterator mutex is held during the retrieval of the next member.
3298 *
3299 * RETURN CODES
3300 *
3301 * Returns != 0 upon successful completion.
3302 *
3303 */
3304
3305 int ADMINAPI
3306 pts_GroupListNext(const void *iterationId, char *groupName, afs_status_p st)
3307 {
3308 int rc = 0;
3309 afs_status_t tst = 0;
3310 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
3311
3312 /*
3313 * Validate arguments
3314 */
3315
3316 if (iterationId == NULL) {
3317 tst = ADMITERATORNULL;
3318 goto fail_pts_GroupListNext;
3319 }
3320
3321 if (groupName == NULL) {
3322 tst = ADMPTSGROUPNAMENULL;
3323 goto fail_pts_GroupListNext;
3324 }
3325
3326 rc = IteratorNext(iter, (void *)groupName, &tst);
3327
3328 fail_pts_GroupListNext:
3329
3330 if (st != NULL) {
3331 *st = tst;
3332 }
3333 return rc;
3334 }
3335
3336 /*
3337 * pts_GroupListDone - finish using a group list iterator
3338 *
3339 * PARAMETERS
3340 *
3341 * IN iterationId - an iterator previously returned by pts_GroupListBegin
3342 *
3343 * LOCKS
3344 *
3345 * The iterator is locked and then destroyed
3346 *
3347 * RETURN CODES
3348 *
3349 * Returns != 0 upon successful completion.
3350 *
3351 * ASSUMPTIONS
3352 *
3353 * It is the user's responsibility to make sure pts_GroupListDone
3354 * is called only once for each iterator.
3355 */
3356
3357 int ADMINAPI
3358 pts_GroupListDone(const void *iterationId, afs_status_p st)
3359 {
3360 int rc = 0;
3361 afs_status_t tst = 0;
3362 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
3363
3364 /*
3365 * Validate arguments
3366 */
3367
3368 if (iterationId == NULL) {
3369 tst = ADMITERATORNULL;
3370 goto fail_pts_GroupListDone;
3371 }
3372
3373 rc = IteratorDone(iter, &tst);
3374
3375 fail_pts_GroupListDone:
3376
3377 if (st != NULL) {
3378 *st = tst;
3379 }
3380 return rc;
3381 }