1 /* Copyright (C) 1989 Transarc Corporation - All rights reserved */
4 * P_R_P_Q_# (C) COPYRIGHT IBM CORPORATION 1988
5 * LICENSED MATERIALS - PROPERTY OF IBM
6 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
10 static char rcsid[] = "$Header$";
15 Information Technology Center
19 #include <afs/param.h>
26 #include <rx/rx_vab.h>
29 #include <netinet/in.h>
34 #ifdef AFS_ATHENA_STDENV
38 extern struct ubik_dbase *dbase;
42 static int CreateOK (ut, cid, oid, flag, admin)
43 struct ubik_trans *ut;
44 long cid; /* id of caller */
45 long oid; /* id of owner */
46 long flag; /* indicates type of entry */
47 int admin; /* sysadmin membership */
49 if (flag & (PRGRP | PRFOREIGN)) {
50 /* Allow anonymous group creation only if owner specified and running
52 if (cid == ANONYMOUSID) {
53 if ((oid == 0) || !pr_noAuth) return 0;
56 else { /* creating a user */
57 if (!admin && !pr_noAuth) return 0;
64 * WhoIsThis() has been replaced for the Moira-AFS synchronization.
66 long WhoIsThis (acall, at, aid)
67 struct rx_call *acall;
68 struct ubik_trans *at;
71 /* aid is set to the identity of the caller, if known, ANONYMOUSID otherwise */
72 /* returns -1 and sets aid to ANONYMOUSID on any failure */
73 register struct rx_connection *tconn;
74 struct rxvab_conn *tc;
76 char tcell[MAXKTCREALMLEN];
78 char name[MAXKTCNAMELEN];
79 char inst[MAXKTCNAMELEN];
84 tconn = rx_ConnectionOf(acall);
85 code = rx_SecurityClassOf(tconn);
86 if (code == 0) return 0;
87 else if (code == 1) { /* vab class */
88 tc = (struct rxvab_conn *) tconn->securityData;
90 *aid = ntohl(tc->viceID);
93 else if (code == 2) { /* kad class */
94 if (code = rxkad_GetServerInfo
95 (acall->conn, (long *) 0, &exp, name, inst, tcell, (long *) 0))
97 if (exp < FT_ApproxTime()) goto done;
99 extern char *pr_realmName;
100 #ifdef AFS_ATHENA_STDENV
101 static char local_realm[REALM_SZ] = "";
102 if (!local_realm[0]) {
103 krb_get_lrealm (local_realm, 0);
107 #ifdef AFS_ATHENA_STDENV
108 strcasecmp (local_realm, tcell) &&
110 strcasecmp (pr_realmName, tcell))
114 strncpy (vname, name, sizeof(vname));
115 if (ilen = strlen (inst)) {
116 if (strlen(vname) + 1 + ilen >= sizeof(vname)) goto done;
118 strcat (vname, inst);
120 lcstring(vname, vname, sizeof(vname));
121 code = NameToID(at,vname,aid);
124 if (code && !pr_noAuth) return -1;
127 #else /* AFS-Moira synchronization */
128 #define USERSMS 14487
130 long WhoIsThis(acall, at, aid)
131 struct rx_call *acall;
132 struct ubik_trans *at;
140 long PR_INewEntry(call,aname,aid,oid)
141 struct rx_call *call;
142 char aname[PR_MAXNAMELEN];
146 /* used primarily for conversion - not intended to be used as usual means
147 of entering people into the database. */
148 struct ubik_trans *tt;
154 #define abort_with(code) return (ubik_AbortTrans(tt),code)
158 if (code != PRSUCCESS) return code;
159 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS, &tt);
160 if (code) return code;
161 code = ubik_SetLock(tt, 1,1,LOCKWRITE);
162 if (code) abort_with (code);
164 code = WhoIsThis(call,tt,&cid);
165 if (code) abort_with (PRPERM);
166 admin = IsAMemberOf(tt,cid,SYSADMINID);
168 /* first verify the id is good */
169 if (aid == 0) abort_with (PRPERM);
172 /* only sysadmin can reuse a group id */
173 if (!admin && !pr_noAuth && (aid != ntohl(cheader.maxGroup)-1))
176 if (FindByID (tt, aid)) abort_with (PRIDEXIST);
178 /* check a few other things */
179 if (!CreateOK (tt, cid, oid, gflag, admin)) abort_with (PRPERM);
181 code = CreateEntry (tt,aname,&aid,1,gflag,oid,cid);
182 if (code != PRSUCCESS) {
186 /* finally, commit transaction */
187 code = ubik_EndTrans(tt);
188 if (code) return code;
193 long PR_NewEntry (call, aname, flag, oid, aid)
194 struct rx_call *call;
195 char aname[PR_MAXNAMELEN];
201 struct ubik_trans *tt;
207 if (code) return code;
208 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
209 if (code) return code;
210 code = ubik_SetLock(tt,1,1,LOCKWRITE);
216 code = WhoIsThis(call,tt,&cid);
222 admin = IsAMemberOf(tt,cid,SYSADMINID);
224 if (!CreateOK (tt, cid, oid, flag, admin)) goto perm;
226 code = CreateEntry (tt,aname,aid,0,flag,oid,cid);
227 if (code != PRSUCCESS) goto abort;
229 code = ubik_EndTrans(tt);
230 if (code) return code;
236 PR_WhereIsIt(call,aid,apos)
237 struct rx_call *call;
242 struct ubik_trans *tt;
246 if (code != PRSUCCESS) return code;
247 code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
248 if (code) return code;
249 code = ubik_SetLock(tt,1,1,LOCKREAD);
254 temp = FindByID(tt,aid);
260 code = ubik_EndTrans(tt);
261 if (code) return code;
266 PR_DumpEntry(call,apos, aentry)
267 struct rx_call *call;
269 struct prdebugentry *aentry;
272 struct ubik_trans *tt;
275 if (code != PRSUCCESS) return code;
276 code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
277 if (code) return code;
278 code = ubik_SetLock(tt,1,1,LOCKREAD);
284 code = pr_ReadEntry(tt, 0, apos, aentry);
285 if (code) goto abort;
287 if (aentry->flags & PRCONT) { /* wrong type, get coentry instead */
288 code = pr_ReadCoEntry(tt, 0, apos, aentry);
289 if (code) goto abort;
291 code = ubik_EndTrans(tt);
292 if (code) return code;
296 PR_AddToGroup(call,aid,gid)
297 struct rx_call *call;
302 struct ubik_trans *tt;
305 struct prentry tentry;
306 struct prentry uentry;
310 if (code != PRSUCCESS) return code;
311 if (gid == ANYUSERID || gid == AUTHUSERID) return PRPERM;
312 if (aid == ANONYMOUSID) return PRPERM;
313 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
314 if (code) return code;
315 code = ubik_SetLock(tt,1,1,LOCKWRITE);
320 code = WhoIsThis(call, tt, &cid);
325 tempu = FindByID(tt,aid);
330 bzero(&uentry,sizeof(uentry));
331 code = pr_ReadEntry(tt,0,tempu,&uentry);
336 /* we don't allow groups as members of groups at present */
337 if (uentry.flags & PRGRP) {
341 tempg = FindByID(tt,gid);
346 code = pr_ReadEntry(tt,0,tempg,&tentry);
351 /* make sure that this is a group */
352 if (!(tentry.flags & PRGRP)) {
356 if (!AccessOK (tt, cid, &tentry, PRP_ADD_MEM, PRP_ADD_ANY)) {
361 code = AddToEntry (tt, &tentry, tempg, aid);
362 if (code != PRSUCCESS) {
366 /* now, modify the user's entry as well */
367 code = AddToEntry (tt, &uentry, tempu, gid);
368 if (code != PRSUCCESS) {
372 code = ubik_EndTrans(tt);
373 if (code) return code;
377 long PR_NameToID (call, aname, aid)
378 struct rx_call *call;
383 struct ubik_trans *tt;
388 /* must do this first for RPC stub to work */
389 size = aname->namelist_len;
390 if ((size <= 0) || (size > PR_MAXLIST)) size = 0;
391 aid->idlist_val = (long *)malloc(size*sizeof(long));
393 if (aname->namelist_len == 0) return 0;
394 if (size == 0) return PRTOOMANY; /* rxgen will probably handle this */
397 if (code != PRSUCCESS) return code;
398 code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
399 if (code) return code;
400 code = ubik_SetLock(tt,1,1,LOCKREAD);
405 for (i=0;i<aname->namelist_len;i++) {
406 code = NameToID(tt,aname->namelist_val[i],&aid->idlist_val[i]);
407 if (code != PRSUCCESS) aid->idlist_val[i] = ANONYMOUSID;
408 if (count++ > 50) IOMGR_Poll(), count = 0;
410 aid->idlist_len = aname->namelist_len;
412 code = ubik_EndTrans(tt);
413 if (code) return code;
417 long PR_IDToName (call, aid, aname)
418 struct rx_call *call;
423 struct ubik_trans *tt;
428 /* leave this first for rpc stub */
429 size = aid->idlist_len;
430 if ((size <= 0) || (size > PR_MAXLIST)) size = 0;
431 aname->namelist_val = (prname *)malloc(size*PR_MAXNAMELEN);
432 aname->namelist_len = 0;
433 if (aid->idlist_len == 0) return 0;
434 if (size == 0) return PRTOOMANY; /* rxgen will probably handle this */
437 if (code != PRSUCCESS) return code;
438 code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
439 if (code) return code;
440 code = ubik_SetLock(tt,1,1,LOCKREAD);
445 for (i=0;i<aid->idlist_len;i++) {
446 /* interface won't allow more than PR_MAXLIST to be sent in */
447 code = IDToName(tt,aid->idlist_val[i],aname->namelist_val[i]);
448 if (code != PRSUCCESS)
449 sprintf(aname->namelist_val[i],"%d",aid->idlist_val[i]);
450 if (count++ > 50) IOMGR_Poll(), count = 0;
452 aname->namelist_len = aid->idlist_len;
454 code = ubik_EndTrans(tt);
455 if (code) return code;
459 long PR_Delete (call, aid)
460 struct rx_call *call;
464 struct ubik_trans *tt;
466 struct prentry tentry;
471 if (code) return code;
472 if (code != PRSUCCESS) return code;
473 if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID || aid == ANONYMOUSID) return PRPERM;
474 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
475 if (code) return code;
476 code = ubik_SetLock(tt,1,1,LOCKWRITE);
482 code = WhoIsThis(call,tt,&cid);
488 /* Read in entry to be deleted */
489 loc = FindByID (tt, aid);
490 if (loc == 0) {code = PRNOENT; goto abort;}
491 code = pr_ReadEntry (tt, 0, loc, &tentry);
492 if (code) {code = PRDBFAIL; goto abort;}
494 /* Do some access checking */
495 if (tentry.owner != cid &&
496 !IsAMemberOf (tt, cid, SYSADMINID) &&
497 !IsAMemberOf (tt, cid, tentry.owner) && !pr_noAuth)
498 {code = PRPERM; goto abort;}
500 /* Delete each continuation block as a separate transaction so that no one
501 * transaction become to large to complete. */
503 while (nptr != NULL) {
504 struct contentry centry;
507 code = pr_ReadCoEntry(tt, 0, nptr, ¢ry);
508 if (code != 0) {code = PRDBFAIL; goto abort;}
509 for (i=0;i<COSIZE;i++) {
510 if (centry.entries[i] == PRBADID) continue;
511 if (centry.entries[i] == 0) break;
512 code = RemoveFromEntry (tt, aid, centry.entries[i]);
513 if (code) goto abort;
514 tentry.count--; /* maintain count */
515 if ((i&3) == 0) IOMGR_Poll();
517 tentry.next = centry.next; /* thread out this block */
518 code = FreeBlock (tt, nptr); /* free continuation block */
519 if (code) goto abort;
520 code = pr_WriteEntry (tt, 0, loc, &tentry); /* update main entry */
521 if (code) goto abort;
523 /* end this trans and start a new one */
524 code = ubik_EndTrans(tt);
525 if (code) return code;
526 IOMGR_Poll(); /* just to keep the connection alive */
527 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
528 if (code) return code;
529 code = ubik_SetLock(tt,1,1,LOCKWRITE);
530 if (code) goto abort;
532 /* re-read entry to get consistent uptodate info */
533 loc = FindByID (tt, aid);
534 if (loc == 0) {code = PRNOENT; goto abort;}
535 code = pr_ReadEntry (tt, 0, loc, &tentry);
536 if (code) {code = PRDBFAIL; goto abort;}
541 /* Then move the owned chain, except possibly ourself to the orphan list.
542 * Because this list can be very long and so exceed the size of a ubik
543 * transaction, we start a new transaction every 50 entries. */
546 while (nptr != NULL) {
547 struct prentry nentry;
549 code = pr_ReadEntry (tt, 0, nptr, &nentry);
550 if (code) {code = PRDBFAIL; goto abort;}
551 nptr = tentry.owned = nentry.nextOwned; /* thread out */
553 if (nentry.id != tentry.id) { /* don't add us to orphan chain! */
554 code = AddToOrphan (tt, nentry.id);
555 if (code) goto abort;
557 if ((count & 3) == 0) IOMGR_Poll();
559 if (count < 50) continue;
560 code = pr_WriteEntry (tt, 0, loc, &tentry); /* update main entry */
561 if (code) goto abort;
563 /* end this trans and start a new one */
564 code = ubik_EndTrans(tt);
565 if (code) return code;
566 IOMGR_Poll(); /* just to keep the connection alive */
567 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
568 if (code) return code;
569 code = ubik_SetLock(tt,1,1,LOCKWRITE);
570 if (code) goto abort;
572 /* re-read entry to get consistent uptodate info */
573 loc = FindByID (tt, aid);
574 if (loc == 0) {code = PRNOENT; goto abort;}
575 code = pr_ReadEntry (tt, 0, loc, &tentry);
576 if (code) {code = PRDBFAIL; goto abort;}
581 /* now do what's left of the deletion stuff */
582 code = DeleteEntry (tt, &tentry, loc);
583 if (code != PRSUCCESS) {
587 code = ubik_EndTrans(tt);
588 if (code) return code;
592 PR_RemoveFromGroup(call,aid,gid)
593 struct rx_call *call;
598 struct ubik_trans *tt;
601 struct prentry uentry;
602 struct prentry gentry;
606 if (code != PRSUCCESS) return code;
607 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
608 if (code) return code;
609 code = ubik_SetLock(tt,1,1,LOCKWRITE);
614 code = WhoIsThis(call,tt,&cid);
619 tempu = FindByID(tt,aid);
624 tempg = FindByID(tt,gid);
629 bzero(&uentry,sizeof(uentry));
630 bzero(&gentry,sizeof(gentry));
631 code = pr_ReadEntry(tt,0,tempu,&uentry);
636 code = pr_ReadEntry(tt,0,tempg,&gentry);
641 if (!(gentry.flags & PRGRP)) {
645 if (uentry.flags & PRGRP) {
649 if (!AccessOK (tt, cid, &gentry, PRP_REMOVE_MEM, 0)) {
653 code = RemoveFromEntry(tt,aid,gid);
654 if (code != PRSUCCESS) {
658 code = RemoveFromEntry(tt,gid,aid);
659 if (code != PRSUCCESS) {
663 code = ubik_EndTrans(tt);
664 if (code) return code;
668 long PR_GetCPS (call, aid, alist, over)
669 struct rx_call *call;
675 struct ubik_trans *tt;
678 struct prentry tentry;
680 alist->prlist_len = 0;
681 alist->prlist_val = (long *) 0;
683 if (code != PRSUCCESS) goto done;
684 code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
686 code = ubik_SetLock(tt,1,1,LOCKREAD);
694 temp = FindByID(tt,aid);
695 if (!temp) {code = PRNOENT; goto abort;}
696 code = pr_ReadEntry (tt, 0, temp, &tentry);
697 if (code) goto abort;
699 if (0) { /* afs doesn't authenticate yet */
700 code = WhoIsThis (call, tt, &cid);
701 if (code || !AccessOK (tt, cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY)) {
707 code = GetList(tt, &tentry, alist, 1);
709 if (code == PRTOOMANY) *over = 1;
710 else if (code != PRSUCCESS) {
715 code = ubik_EndTrans(tt);
718 /* return code, making sure that prlist_val points to malloc'd memory */
719 if (!alist->prlist_val)
720 alist->prlist_val = (long *) malloc(0); /* make xdr stub happy */
724 PR_ListMax(call,uid,gid)
725 struct rx_call *call;
730 struct ubik_trans *tt;
733 if (code != PRSUCCESS) return code;
734 code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
735 if (code) return code;
736 code = ubik_SetLock(tt,1,1,LOCKREAD);
741 code = GetMax(tt,uid,gid);
742 if (code != PRSUCCESS) {
746 code = ubik_EndTrans(tt);
747 if (code) return code;
751 PR_SetMax(call,aid,gflag)
752 struct rx_call *call;
757 struct ubik_trans *tt;
761 if (code != PRSUCCESS) return code;
762 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
763 if (code) return code;
764 code = ubik_SetLock(tt,1,1,LOCKWRITE);
769 code = WhoIsThis(call,tt,&cid);
774 if (!AccessOK (tt, cid, 0, 0, 0)) {
778 if (((gflag & PRGRP) && (aid > 0)) ||
779 (!(gflag & PRGRP) && (aid < 0))) {
784 code = SetMax(tt,aid,gflag);
785 if (code != PRSUCCESS) {
790 code = ubik_EndTrans(tt);
791 if (code) return code;
795 PR_ListEntry(call,aid,aentry)
796 struct rx_call *call;
798 struct prcheckentry *aentry;
801 struct ubik_trans *tt;
804 struct prentry tentry;
807 if (code != PRSUCCESS) return code;
808 code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
809 if (code) return code;
810 code = ubik_SetLock(tt,1,1,LOCKREAD);
815 code = WhoIsThis(call,tt,&cid);
821 temp = FindByID(tt,aid);
826 code = pr_ReadEntry(tt, 0, temp, &tentry);
831 if (!AccessOK (tt, cid, &tentry, PRP_STATUS_MEM, PRP_STATUS_ANY)) goto perm;
833 aentry->flags = tentry.flags >> PRIVATE_SHIFT;
834 if (aentry->flags == 0)
835 if (tentry.flags & PRGRP)
836 aentry->flags = PRP_GROUP_DEFAULT >> PRIVATE_SHIFT;
837 else aentry->flags = PRP_USER_DEFAULT >> PRIVATE_SHIFT;
839 aentry->owner = tentry.owner;
840 aentry->id = tentry.id;
841 strncpy(aentry->name,tentry.name,PR_MAXNAMELEN);
842 aentry->creator = tentry.creator;
843 aentry->ngroups = tentry.ngroups;
844 aentry->nusers = tentry.nusers;
845 aentry->count = tentry.count;
846 bzero (aentry->reserved, sizeof(aentry->reserved));
847 code = ubik_EndTrans(tt);
848 if (code) return code;
852 PR_ChangeEntry(call,aid,name,oid,newid)
853 struct rx_call *call;
860 struct ubik_trans *tt;
866 if (code) return code;
867 if (aid == ANYUSERID || aid == AUTHUSERID || aid == ANONYMOUSID || aid == SYSADMINID) return PRPERM;
868 if (code != PRSUCCESS) return code;
869 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
870 if (code) return code;
871 code = ubik_SetLock(tt,1,1,LOCKWRITE);
876 code = WhoIsThis(call,tt,&cid);
881 pos = FindByID(tt,aid);
886 /* protection check in changeentry */
887 code = ChangeEntry(tt,aid,cid,name,oid,newid);
888 if (code != PRSUCCESS) {
892 code = ubik_EndTrans(tt);
896 PR_SetFieldsEntry(call, id, mask, flags, ngroups, nusers, spare1, spare2)
897 struct rx_call *call;
899 long mask; /* specify which fields to update */
900 long flags, ngroups, nusers;
904 struct ubik_trans *tt;
907 struct prentry tentry;
910 if (mask == 0) return 0; /* no-op */
912 if (code) return code;
913 if (id == ANYUSERID || id == AUTHUSERID || id == ANONYMOUSID)
915 if (code != PRSUCCESS) return code;
916 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
917 if (code) return code;
918 code = ubik_SetLock(tt,1,1,LOCKWRITE);
924 code = WhoIsThis(call,tt,&cid);
930 pos = FindByID(tt,id);
935 code = pr_ReadEntry (tt, 0, pos, &tentry);
936 if (code) goto abort;
937 tflags = tentry.flags;
939 if (mask & (PR_SF_NGROUPS | PR_SF_NUSERS)) {
940 if (!AccessOK (tt, cid, 0, 0, 0)) goto perm;
941 if ((tflags & PRQUOTA) == 0) { /* default if only setting one */
942 tentry.ngroups = tentry.nusers = 20;
945 if (!AccessOK (tt, cid, &tentry, 0, 0)) goto perm;
948 if (mask & 0xffff) { /* if setting flag bits */
949 long flagsMask = mask & 0xffff;
950 tflags &= ~(flagsMask << PRIVATE_SHIFT);
951 tflags |= (flags & flagsMask) << PRIVATE_SHIFT;
955 if (mask & PR_SF_NGROUPS) { /* setting group limit */
956 if (ngroups < 0) {code = PRBADARG; goto abort;}
957 tentry.ngroups = ngroups;
961 if (mask & PR_SF_NUSERS) { /* setting foreign user limit */
962 if (nusers < 0) {code = PRBADARG; goto abort;}
963 tentry.nusers = nusers;
966 tentry.flags = tflags;
968 code = pr_WriteEntry (tt, 0, pos, &tentry);
969 if (code) goto abort;
971 code = ubik_EndTrans(tt);
975 long PR_ListElements (call, aid, alist, over)
976 struct rx_call *call;
982 struct ubik_trans *tt;
985 struct prentry tentry;
987 alist->prlist_len = 0;
988 alist->prlist_val = (long *) 0;
991 if (code != PRSUCCESS) goto done;
992 code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
994 code = ubik_SetLock(tt,1,1,LOCKREAD);
1000 code = WhoIsThis(call,tt,&cid);
1004 ubik_AbortTrans(tt);
1008 temp = FindByID(tt,aid);
1009 if (!temp) {code = PRNOENT; goto abort;}
1010 code = pr_ReadEntry (tt, 0, temp, &tentry);
1011 if (code) goto abort;
1012 if (!AccessOK (tt, cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1015 code = GetList (tt, &tentry, alist, 0);
1017 if (code == PRTOOMANY) *over = 1;
1018 else if (code != PRSUCCESS) goto abort;
1020 code = ubik_EndTrans(tt);
1023 if (!alist->prlist_val)
1024 alist->prlist_val = (long *) malloc(0); /* make calling stub happy */
1028 /* List the entries owned by this id. If the id is zero return the orphans
1031 PR_ListOwned (call, aid, alist, over)
1032 struct rx_call *call;
1038 struct ubik_trans *tt;
1040 struct prentry tentry;
1043 alist->prlist_len = 0;
1044 alist->prlist_val = (long *) 0;
1047 if (code != PRSUCCESS) goto done;
1048 code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
1049 if (code) goto done;
1050 code = ubik_SetLock(tt,1,1,LOCKREAD);
1053 ubik_AbortTrans(tt);
1056 code = WhoIsThis(call,tt,&cid);
1060 ubik_AbortTrans(tt);
1065 long loc = FindByID (tt, aid);
1066 if (loc == 0) { code = PRNOENT; goto abort; }
1067 code = pr_ReadEntry (tt, 0, loc, &tentry);
1068 if (code) goto abort;
1070 if (!AccessOK (tt, cid, &tentry, -1, PRP_OWNED_ANY)) goto perm;
1071 head = tentry.owned;
1073 if (!AccessOK (tt, cid, 0, 0, 0)) goto perm;
1074 head = ntohl(cheader.orphan);
1077 code = GetOwnedChain (tt, head, alist);
1079 if (code == PRTOOMANY) *over = 1;
1080 else if (code) goto abort;
1082 code = ubik_EndTrans(tt);
1085 if (!alist->prlist_val)
1086 alist->prlist_val = (long *) malloc(0); /* make calling stub happy */
1090 PR_IsAMemberOf(call,uid,gid,flag)
1091 struct rx_call *call;
1097 struct ubik_trans *tt;
1100 if (code != PRSUCCESS) return code;
1101 code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
1102 if (code) return code;
1103 code = ubik_SetLock(tt,1,1,LOCKREAD);
1106 ubik_AbortTrans(tt);
1110 long uloc = FindByID (tt, uid);
1111 long gloc = FindByID (tt, gid);
1112 struct prentry uentry, gentry;
1114 if (!uloc || !gloc) {
1118 code = WhoIsThis(call, tt, &cid);
1124 code = pr_ReadEntry (tt, 0, uloc, &uentry);
1125 if (code) goto abort;
1126 code = pr_ReadEntry (tt, 0, gloc, &gentry);
1127 if (code) goto abort;
1128 if ((uentry.flags & PRGRP) || !(gentry.flags & PRGRP)) {
1132 if (!AccessOK (tt, cid, &uentry, 0, PRP_MEMBER_ANY) &&
1133 !AccessOK (tt, cid, &gentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY)) goto perm;
1136 *flag = IsAMemberOf(tt,uid,gid);
1137 code = ubik_EndTrans(tt);
1147 if (isupper(tc)) *s = tolower(tc);