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;
62 long WhoIsThis (acall, at, aid)
63 struct rx_call *acall;
64 struct ubik_trans *at;
67 /* aid is set to the identity of the caller, if known, ANONYMOUSID otherwise */
68 /* returns -1 and sets aid to ANONYMOUSID on any failure */
69 register struct rx_connection *tconn;
70 struct rxvab_conn *tc;
72 char tcell[MAXKTCREALMLEN];
74 char name[MAXKTCNAMELEN];
75 char inst[MAXKTCNAMELEN];
80 tconn = rx_ConnectionOf(acall);
81 code = rx_SecurityClassOf(tconn);
82 if (code == 0) return 0;
83 else if (code == 1) { /* vab class */
84 tc = (struct rxvab_conn *) tconn->securityData;
86 *aid = ntohl(tc->viceID);
89 else if (code == 2) { /* kad class */
90 if (code = rxkad_GetServerInfo
91 (acall->conn, (long *) 0, &exp, name, inst, tcell, (long *) 0))
93 if (exp < FT_ApproxTime()) goto done;
95 extern char *pr_realmName;
96 #ifdef AFS_ATHENA_STDENV
97 static char local_realm[REALM_SZ] = "";
98 if (!local_realm[0]) {
99 krb_get_lrealm (local_realm, 0);
103 #ifdef AFS_ATHENA_STDENV
104 strcasecmp (local_realm, tcell) &&
106 strcasecmp (pr_realmName, tcell))
110 strncpy (vname, name, sizeof(vname));
111 if (ilen = strlen (inst)) {
112 if (strlen(vname) + 1 + ilen >= sizeof(vname)) goto done;
114 strcat (vname, inst);
116 lcstring(vname, vname, sizeof(vname));
117 code = NameToID(at,vname,aid);
120 if (code && !pr_noAuth) return -1;
124 long PR_INewEntry(call,aname,aid,oid)
125 struct rx_call *call;
126 char aname[PR_MAXNAMELEN];
130 /* used primarily for conversion - not intended to be used as usual means
131 of entering people into the database. */
132 struct ubik_trans *tt;
138 #define abort_with(code) return (ubik_AbortTrans(tt),code)
142 if (code != PRSUCCESS) return code;
143 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS, &tt);
144 if (code) return code;
145 code = ubik_SetLock(tt, 1,1,LOCKWRITE);
146 if (code) abort_with (code);
148 code = WhoIsThis(call,tt,&cid);
149 if (code) abort_with (PRPERM);
150 admin = IsAMemberOf(tt,cid,SYSADMINID);
152 /* first verify the id is good */
153 if (aid == 0) abort_with (PRPERM);
156 /* only sysadmin can reuse a group id */
157 if (!admin && !pr_noAuth && (aid != ntohl(cheader.maxGroup)-1))
160 if (FindByID (tt, aid)) abort_with (PRIDEXIST);
162 /* check a few other things */
163 if (!CreateOK (tt, cid, oid, gflag, admin)) abort_with (PRPERM);
165 code = CreateEntry (tt,aname,&aid,1,gflag,oid,cid);
166 if (code != PRSUCCESS) {
170 /* finally, commit transaction */
171 code = ubik_EndTrans(tt);
172 if (code) return code;
177 long PR_NewEntry (call, aname, flag, oid, aid)
178 struct rx_call *call;
179 char aname[PR_MAXNAMELEN];
185 struct ubik_trans *tt;
191 if (code) return code;
192 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
193 if (code) return code;
194 code = ubik_SetLock(tt,1,1,LOCKWRITE);
200 code = WhoIsThis(call,tt,&cid);
206 admin = IsAMemberOf(tt,cid,SYSADMINID);
208 if (!CreateOK (tt, cid, oid, flag, admin)) goto perm;
210 code = CreateEntry (tt,aname,aid,0,flag,oid,cid);
211 if (code != PRSUCCESS) goto abort;
213 code = ubik_EndTrans(tt);
214 if (code) return code;
220 PR_WhereIsIt(call,aid,apos)
221 struct rx_call *call;
226 struct ubik_trans *tt;
230 if (code != PRSUCCESS) return code;
231 code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
232 if (code) return code;
233 code = ubik_SetLock(tt,1,1,LOCKREAD);
238 temp = FindByID(tt,aid);
244 code = ubik_EndTrans(tt);
245 if (code) return code;
250 PR_DumpEntry(call,apos, aentry)
251 struct rx_call *call;
253 struct prdebugentry *aentry;
256 struct ubik_trans *tt;
259 if (code != PRSUCCESS) return code;
260 code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
261 if (code) return code;
262 code = ubik_SetLock(tt,1,1,LOCKREAD);
268 code = pr_ReadEntry(tt, 0, apos, aentry);
269 if (code) goto abort;
271 if (aentry->flags & PRCONT) { /* wrong type, get coentry instead */
272 code = pr_ReadCoEntry(tt, 0, apos, aentry);
273 if (code) goto abort;
275 code = ubik_EndTrans(tt);
276 if (code) return code;
280 PR_AddToGroup(call,aid,gid)
281 struct rx_call *call;
286 struct ubik_trans *tt;
289 struct prentry tentry;
290 struct prentry uentry;
294 if (code != PRSUCCESS) return code;
295 if (gid == ANYUSERID || gid == AUTHUSERID) return PRPERM;
296 if (aid == ANONYMOUSID) return PRPERM;
297 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
298 if (code) return code;
299 code = ubik_SetLock(tt,1,1,LOCKWRITE);
304 code = WhoIsThis(call, tt, &cid);
309 tempu = FindByID(tt,aid);
314 bzero(&uentry,sizeof(uentry));
315 code = pr_ReadEntry(tt,0,tempu,&uentry);
320 /* we don't allow groups as members of groups at present */
321 if (uentry.flags & PRGRP) {
325 tempg = FindByID(tt,gid);
330 code = pr_ReadEntry(tt,0,tempg,&tentry);
335 /* make sure that this is a group */
336 if (!(tentry.flags & PRGRP)) {
340 if (!AccessOK (tt, cid, &tentry, PRP_ADD_MEM, PRP_ADD_ANY)) {
345 code = AddToEntry (tt, &tentry, tempg, aid);
346 if (code != PRSUCCESS) {
350 /* now, modify the user's entry as well */
351 code = AddToEntry (tt, &uentry, tempu, gid);
352 if (code != PRSUCCESS) {
356 code = ubik_EndTrans(tt);
357 if (code) return code;
361 long PR_NameToID (call, aname, aid)
362 struct rx_call *call;
367 struct ubik_trans *tt;
372 /* must do this first for RPC stub to work */
373 size = aname->namelist_len;
374 if ((size <= 0) || (size > PR_MAXLIST)) size = 0;
375 aid->idlist_val = (long *)malloc(size*sizeof(long));
377 if (aname->namelist_len == 0) return 0;
378 if (size == 0) return PRTOOMANY; /* rxgen will probably handle this */
381 if (code != PRSUCCESS) return code;
382 code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
383 if (code) return code;
384 code = ubik_SetLock(tt,1,1,LOCKREAD);
389 for (i=0;i<aname->namelist_len;i++) {
390 code = NameToID(tt,aname->namelist_val[i],&aid->idlist_val[i]);
391 if (code != PRSUCCESS) aid->idlist_val[i] = ANONYMOUSID;
392 if (count++ > 50) IOMGR_Poll(), count = 0;
394 aid->idlist_len = aname->namelist_len;
396 code = ubik_EndTrans(tt);
397 if (code) return code;
401 long PR_IDToName (call, aid, aname)
402 struct rx_call *call;
407 struct ubik_trans *tt;
412 /* leave this first for rpc stub */
413 size = aid->idlist_len;
414 if ((size <= 0) || (size > PR_MAXLIST)) size = 0;
415 aname->namelist_val = (prname *)malloc(size*PR_MAXNAMELEN);
416 aname->namelist_len = 0;
417 if (aid->idlist_len == 0) return 0;
418 if (size == 0) return PRTOOMANY; /* rxgen will probably handle this */
421 if (code != PRSUCCESS) return code;
422 code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
423 if (code) return code;
424 code = ubik_SetLock(tt,1,1,LOCKREAD);
429 for (i=0;i<aid->idlist_len;i++) {
430 /* interface won't allow more than PR_MAXLIST to be sent in */
431 code = IDToName(tt,aid->idlist_val[i],aname->namelist_val[i]);
432 if (code != PRSUCCESS)
433 sprintf(aname->namelist_val[i],"%d",aid->idlist_val[i]);
434 if (count++ > 50) IOMGR_Poll(), count = 0;
436 aname->namelist_len = aid->idlist_len;
438 code = ubik_EndTrans(tt);
439 if (code) return code;
443 long PR_Delete (call, aid)
444 struct rx_call *call;
448 struct ubik_trans *tt;
450 struct prentry tentry;
455 if (code) return code;
456 if (code != PRSUCCESS) return code;
457 if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID || aid == ANONYMOUSID) return PRPERM;
458 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
459 if (code) return code;
460 code = ubik_SetLock(tt,1,1,LOCKWRITE);
466 code = WhoIsThis(call,tt,&cid);
472 /* Read in entry to be deleted */
473 loc = FindByID (tt, aid);
474 if (loc == 0) {code = PRNOENT; goto abort;}
475 code = pr_ReadEntry (tt, 0, loc, &tentry);
476 if (code) {code = PRDBFAIL; goto abort;}
478 /* Do some access checking */
479 if (tentry.owner != cid &&
480 !IsAMemberOf (tt, cid, SYSADMINID) &&
481 !IsAMemberOf (tt, cid, tentry.owner) && !pr_noAuth)
482 {code = PRPERM; goto abort;}
484 /* Delete each continuation block as a separate transaction so that no one
485 * transaction become to large to complete. */
487 while (nptr != NULL) {
488 struct contentry centry;
491 code = pr_ReadCoEntry(tt, 0, nptr, ¢ry);
492 if (code != 0) {code = PRDBFAIL; goto abort;}
493 for (i=0;i<COSIZE;i++) {
494 if (centry.entries[i] == PRBADID) continue;
495 if (centry.entries[i] == 0) break;
496 code = RemoveFromEntry (tt, aid, centry.entries[i]);
497 if (code) goto abort;
498 tentry.count--; /* maintain count */
499 if ((i&3) == 0) IOMGR_Poll();
501 tentry.next = centry.next; /* thread out this block */
502 code = FreeBlock (tt, nptr); /* free continuation block */
503 if (code) goto abort;
504 code = pr_WriteEntry (tt, 0, loc, &tentry); /* update main entry */
505 if (code) goto abort;
507 /* end this trans and start a new one */
508 code = ubik_EndTrans(tt);
509 if (code) return code;
510 IOMGR_Poll(); /* just to keep the connection alive */
511 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
512 if (code) return code;
513 code = ubik_SetLock(tt,1,1,LOCKWRITE);
514 if (code) goto abort;
516 /* re-read entry to get consistent uptodate info */
517 loc = FindByID (tt, aid);
518 if (loc == 0) {code = PRNOENT; goto abort;}
519 code = pr_ReadEntry (tt, 0, loc, &tentry);
520 if (code) {code = PRDBFAIL; goto abort;}
525 /* Then move the owned chain, except possibly ourself to the orphan list.
526 * Because this list can be very long and so exceed the size of a ubik
527 * transaction, we start a new transaction every 50 entries. */
530 while (nptr != NULL) {
531 struct prentry nentry;
533 code = pr_ReadEntry (tt, 0, nptr, &nentry);
534 if (code) {code = PRDBFAIL; goto abort;}
535 nptr = tentry.owned = nentry.nextOwned; /* thread out */
537 if (nentry.id != tentry.id) { /* don't add us to orphan chain! */
538 code = AddToOrphan (tt, nentry.id);
539 if (code) goto abort;
541 if ((count & 3) == 0) IOMGR_Poll();
543 if (count < 50) continue;
544 code = pr_WriteEntry (tt, 0, loc, &tentry); /* update main entry */
545 if (code) goto abort;
547 /* end this trans and start a new one */
548 code = ubik_EndTrans(tt);
549 if (code) return code;
550 IOMGR_Poll(); /* just to keep the connection alive */
551 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
552 if (code) return code;
553 code = ubik_SetLock(tt,1,1,LOCKWRITE);
554 if (code) goto abort;
556 /* re-read entry to get consistent uptodate info */
557 loc = FindByID (tt, aid);
558 if (loc == 0) {code = PRNOENT; goto abort;}
559 code = pr_ReadEntry (tt, 0, loc, &tentry);
560 if (code) {code = PRDBFAIL; goto abort;}
565 /* now do what's left of the deletion stuff */
566 code = DeleteEntry (tt, &tentry, loc);
567 if (code != PRSUCCESS) {
571 code = ubik_EndTrans(tt);
572 if (code) return code;
576 PR_RemoveFromGroup(call,aid,gid)
577 struct rx_call *call;
582 struct ubik_trans *tt;
585 struct prentry uentry;
586 struct prentry gentry;
590 if (code != PRSUCCESS) return code;
591 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
592 if (code) return code;
593 code = ubik_SetLock(tt,1,1,LOCKWRITE);
598 code = WhoIsThis(call,tt,&cid);
603 tempu = FindByID(tt,aid);
608 tempg = FindByID(tt,gid);
613 bzero(&uentry,sizeof(uentry));
614 bzero(&gentry,sizeof(gentry));
615 code = pr_ReadEntry(tt,0,tempu,&uentry);
620 code = pr_ReadEntry(tt,0,tempg,&gentry);
625 if (!(gentry.flags & PRGRP)) {
629 if (uentry.flags & PRGRP) {
633 if (!AccessOK (tt, cid, &gentry, PRP_REMOVE_MEM, 0)) {
637 code = RemoveFromEntry(tt,aid,gid);
638 if (code != PRSUCCESS) {
642 code = RemoveFromEntry(tt,gid,aid);
643 if (code != PRSUCCESS) {
647 code = ubik_EndTrans(tt);
648 if (code) return code;
652 long PR_GetCPS (call, aid, alist, over)
653 struct rx_call *call;
659 struct ubik_trans *tt;
662 struct prentry tentry;
664 alist->prlist_len = 0;
665 alist->prlist_val = (long *) 0;
667 if (code != PRSUCCESS) goto done;
668 code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
670 code = ubik_SetLock(tt,1,1,LOCKREAD);
678 temp = FindByID(tt,aid);
679 if (!temp) {code = PRNOENT; goto abort;}
680 code = pr_ReadEntry (tt, 0, temp, &tentry);
681 if (code) goto abort;
683 if (0) { /* afs doesn't authenticate yet */
684 code = WhoIsThis (call, tt, &cid);
685 if (code || !AccessOK (tt, cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY)) {
691 code = GetList(tt, &tentry, alist, 1);
693 if (code == PRTOOMANY) *over = 1;
694 else if (code != PRSUCCESS) {
699 code = ubik_EndTrans(tt);
702 /* return code, making sure that prlist_val points to malloc'd memory */
703 if (!alist->prlist_val)
704 alist->prlist_val = (long *) malloc(0); /* make xdr stub happy */
708 PR_ListMax(call,uid,gid)
709 struct rx_call *call;
714 struct ubik_trans *tt;
717 if (code != PRSUCCESS) return code;
718 code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
719 if (code) return code;
720 code = ubik_SetLock(tt,1,1,LOCKREAD);
725 code = GetMax(tt,uid,gid);
726 if (code != PRSUCCESS) {
730 code = ubik_EndTrans(tt);
731 if (code) return code;
735 PR_SetMax(call,aid,gflag)
736 struct rx_call *call;
741 struct ubik_trans *tt;
745 if (code != PRSUCCESS) return code;
746 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
747 if (code) return code;
748 code = ubik_SetLock(tt,1,1,LOCKWRITE);
753 code = WhoIsThis(call,tt,&cid);
758 if (!AccessOK (tt, cid, 0, 0, 0)) {
762 if (((gflag & PRGRP) && (aid > 0)) ||
763 (!(gflag & PRGRP) && (aid < 0))) {
768 code = SetMax(tt,aid,gflag);
769 if (code != PRSUCCESS) {
774 code = ubik_EndTrans(tt);
775 if (code) return code;
779 PR_ListEntry(call,aid,aentry)
780 struct rx_call *call;
782 struct prcheckentry *aentry;
785 struct ubik_trans *tt;
788 struct prentry tentry;
791 if (code != PRSUCCESS) return code;
792 code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
793 if (code) return code;
794 code = ubik_SetLock(tt,1,1,LOCKREAD);
799 code = WhoIsThis(call,tt,&cid);
805 temp = FindByID(tt,aid);
810 code = pr_ReadEntry(tt, 0, temp, &tentry);
815 if (!AccessOK (tt, cid, &tentry, PRP_STATUS_MEM, PRP_STATUS_ANY)) goto perm;
817 aentry->flags = tentry.flags >> PRIVATE_SHIFT;
818 if (aentry->flags == 0)
819 if (tentry.flags & PRGRP)
820 aentry->flags = PRP_GROUP_DEFAULT >> PRIVATE_SHIFT;
821 else aentry->flags = PRP_USER_DEFAULT >> PRIVATE_SHIFT;
823 aentry->owner = tentry.owner;
824 aentry->id = tentry.id;
825 strncpy(aentry->name,tentry.name,PR_MAXNAMELEN);
826 aentry->creator = tentry.creator;
827 aentry->ngroups = tentry.ngroups;
828 aentry->nusers = tentry.nusers;
829 aentry->count = tentry.count;
830 bzero (aentry->reserved, sizeof(aentry->reserved));
831 code = ubik_EndTrans(tt);
832 if (code) return code;
836 PR_ChangeEntry(call,aid,name,oid,newid)
837 struct rx_call *call;
844 struct ubik_trans *tt;
850 if (code) return code;
851 if (aid == ANYUSERID || aid == AUTHUSERID || aid == ANONYMOUSID || aid == SYSADMINID) return PRPERM;
852 if (code != PRSUCCESS) return code;
853 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
854 if (code) return code;
855 code = ubik_SetLock(tt,1,1,LOCKWRITE);
860 code = WhoIsThis(call,tt,&cid);
865 pos = FindByID(tt,aid);
870 /* protection check in changeentry */
871 code = ChangeEntry(tt,aid,cid,name,oid,newid);
872 if (code != PRSUCCESS) {
876 code = ubik_EndTrans(tt);
880 PR_SetFieldsEntry(call, id, mask, flags, ngroups, nusers, spare1, spare2)
881 struct rx_call *call;
883 long mask; /* specify which fields to update */
884 long flags, ngroups, nusers;
888 struct ubik_trans *tt;
891 struct prentry tentry;
894 if (mask == 0) return 0; /* no-op */
896 if (code) return code;
897 if (id == ANYUSERID || id == AUTHUSERID || id == ANONYMOUSID)
899 if (code != PRSUCCESS) return code;
900 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
901 if (code) return code;
902 code = ubik_SetLock(tt,1,1,LOCKWRITE);
908 code = WhoIsThis(call,tt,&cid);
914 pos = FindByID(tt,id);
919 code = pr_ReadEntry (tt, 0, pos, &tentry);
920 if (code) goto abort;
921 tflags = tentry.flags;
923 if (mask & (PR_SF_NGROUPS | PR_SF_NUSERS)) {
924 if (!AccessOK (tt, cid, 0, 0, 0)) goto perm;
925 if ((tflags & PRQUOTA) == 0) { /* default if only setting one */
926 tentry.ngroups = tentry.nusers = 20;
929 if (!AccessOK (tt, cid, &tentry, 0, 0)) goto perm;
932 if (mask & 0xffff) { /* if setting flag bits */
933 long flagsMask = mask & 0xffff;
934 tflags &= ~(flagsMask << PRIVATE_SHIFT);
935 tflags |= (flags & flagsMask) << PRIVATE_SHIFT;
939 if (mask & PR_SF_NGROUPS) { /* setting group limit */
940 if (ngroups < 0) {code = PRBADARG; goto abort;}
941 tentry.ngroups = ngroups;
945 if (mask & PR_SF_NUSERS) { /* setting foreign user limit */
946 if (nusers < 0) {code = PRBADARG; goto abort;}
947 tentry.nusers = nusers;
950 tentry.flags = tflags;
952 code = pr_WriteEntry (tt, 0, pos, &tentry);
953 if (code) goto abort;
955 code = ubik_EndTrans(tt);
959 long PR_ListElements (call, aid, alist, over)
960 struct rx_call *call;
966 struct ubik_trans *tt;
969 struct prentry tentry;
971 alist->prlist_len = 0;
972 alist->prlist_val = (long *) 0;
975 if (code != PRSUCCESS) goto done;
976 code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
978 code = ubik_SetLock(tt,1,1,LOCKREAD);
984 code = WhoIsThis(call,tt,&cid);
992 temp = FindByID(tt,aid);
993 if (!temp) {code = PRNOENT; goto abort;}
994 code = pr_ReadEntry (tt, 0, temp, &tentry);
995 if (code) goto abort;
996 if (!AccessOK (tt, cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
999 code = GetList (tt, &tentry, alist, 0);
1001 if (code == PRTOOMANY) *over = 1;
1002 else if (code != PRSUCCESS) goto abort;
1004 code = ubik_EndTrans(tt);
1007 if (!alist->prlist_val)
1008 alist->prlist_val = (long *) malloc(0); /* make calling stub happy */
1012 /* List the entries owned by this id. If the id is zero return the orphans
1015 PR_ListOwned (call, aid, alist, over)
1016 struct rx_call *call;
1022 struct ubik_trans *tt;
1024 struct prentry tentry;
1027 alist->prlist_len = 0;
1028 alist->prlist_val = (long *) 0;
1031 if (code != PRSUCCESS) goto done;
1032 code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
1033 if (code) goto done;
1034 code = ubik_SetLock(tt,1,1,LOCKREAD);
1037 ubik_AbortTrans(tt);
1040 code = WhoIsThis(call,tt,&cid);
1044 ubik_AbortTrans(tt);
1049 long loc = FindByID (tt, aid);
1050 if (loc == 0) { code = PRNOENT; goto abort; }
1051 code = pr_ReadEntry (tt, 0, loc, &tentry);
1052 if (code) goto abort;
1054 if (!AccessOK (tt, cid, &tentry, -1, PRP_OWNED_ANY)) goto perm;
1055 head = tentry.owned;
1057 if (!AccessOK (tt, cid, 0, 0, 0)) goto perm;
1058 head = ntohl(cheader.orphan);
1061 code = GetOwnedChain (tt, head, alist);
1063 if (code == PRTOOMANY) *over = 1;
1064 else if (code) goto abort;
1066 code = ubik_EndTrans(tt);
1069 if (!alist->prlist_val)
1070 alist->prlist_val = (long *) malloc(0); /* make calling stub happy */
1074 PR_IsAMemberOf(call,uid,gid,flag)
1075 struct rx_call *call;
1081 struct ubik_trans *tt;
1084 if (code != PRSUCCESS) return code;
1085 code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
1086 if (code) return code;
1087 code = ubik_SetLock(tt,1,1,LOCKREAD);
1090 ubik_AbortTrans(tt);
1094 long uloc = FindByID (tt, uid);
1095 long gloc = FindByID (tt, gid);
1096 struct prentry uentry, gentry;
1098 if (!uloc || !gloc) {
1102 code = WhoIsThis(call, tt, &cid);
1108 code = pr_ReadEntry (tt, 0, uloc, &uentry);
1109 if (code) goto abort;
1110 code = pr_ReadEntry (tt, 0, gloc, &gentry);
1111 if (code) goto abort;
1112 if ((uentry.flags & PRGRP) || !(gentry.flags & PRGRP)) {
1116 if (!AccessOK (tt, cid, &uentry, 0, PRP_MEMBER_ANY) &&
1117 !AccessOK (tt, cid, &gentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY)) goto perm;
1120 *flag = IsAMemberOf(tt,uid,gid);
1121 code = ubik_EndTrans(tt);
1131 if (isupper(tc)) *s = tolower(tc);