2 * Copyright 2000, International Business Machines Corporation and others.
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
11 * (3) function addToGroup
13 * 1. Eliminate the code that tests for adding groups
14 * to groups. This is an error in normal AFS.
15 * 2. If adding a group to a group call AddToSGEntry
16 * to add the id of the group it's a member of.
20 * 1. Print a messsage if an error is returned from
21 * FindByID() and PTDEBUG is defined.
22 * 2. If removing a group from a group call
23 * RemoveFromSGEntry to remove the id of the
24 * group it's a member of.
25 * 3. Remove supergroup continuation records.
27 * (5) function RemoveFromGroup
29 * 1. Eliminate the code that tests for adding groups
30 * to groups. This is an error in normal AFS.
31 * 2. If removing a group from a group call
32 * RemoveFromSGEntry to remove the id of the
33 * group it's a member of.
35 * (6) Add new functions PR_ListSuperGroups and
38 * (7) function isAMemberOf
40 * 1. Allow groups to be members of groups.
42 * Transarc does not currently use opcodes past 520, but
43 * they *could* decide at any time to use more opcodes.
44 * If they did, then one part of our local mods,
45 * ListSupergroups, would break. I've therefore
46 * renumbered it to 530, and put logic in to enable the
47 * old opcode to work (for now).
50 #include <afsconfig.h>
51 #include <afs/param.h>
59 #include <afs/afsutil.h>
68 #include <netinet/in.h>
79 #include "afs/audit.h"
81 #ifdef AFS_ATHENA_STDENV
86 #define IP_WILDCARDS 1 /* XXX Should be defined outside of here XXX */
88 extern struct ubik_dbase *dbase;
89 extern afs_int32 Initdb();
91 extern afs_int32 initd;
92 afs_int32 iNewEntry(), newEntry(), whereIsIt(), dumpEntry(), addToGroup(), nameToID(), Delete(), removeFromGroup();
93 afs_int32 getCPS(), getCPS2(), getHostCPS(), listMax(), setMax(), listEntry();
94 afs_int32 listEntries(), changeEntry(), setFieldsEntry(), put_prentries();
95 afs_int32 listElements(), listOwned(), isAMemberOf(), idToName();
97 #if defined(SUPERGROUPS)
98 afs_int32 listSuperGroups();
104 /* When abort, reset initd so that the header is read in on next call.
105 * Abort the transarction and return the code.
107 #define ABORT_WITH(tt,code) return(initd=0,ubik_AbortTrans(tt),code)
109 static int CreateOK (ut, cid, oid, flag, admin)
110 struct ubik_trans *ut;
111 afs_int32 cid; /* id of caller */
112 afs_int32 oid; /* id of owner */
113 afs_int32 flag; /* indicates type of entry */
114 int admin; /* sysadmin membership */
116 if (flag & PRFOREIGN) {
117 /* Foreign users are recognized by the '@' sign and
118 * not by the PRFOREIGN flag.
122 else if (flag & PRGRP) {
123 /* Allow anonymous group creation only if owner specified
124 * and running noAuth.
126 if (cid == ANONYMOUSID) {
127 if ((oid == 0) || !pr_noAuth) return 0;
130 else { /* creating a user */
131 if (!admin && !pr_noAuth) return 0;
136 afs_int32 WhoIsThis (acall, at, aid)
137 struct rx_call *acall;
138 struct ubik_trans *at;
142 /* aid is set to the identity of the caller, if known, else ANONYMOUSID */
143 /* returns -1 and sets aid to ANONYMOUSID on any failure */
144 register struct rx_connection *tconn;
145 register afs_int32 code;
146 char tcell[MAXKTCREALMLEN];
147 char name[MAXKTCNAMELEN];
148 char inst[MAXKTCNAMELEN];
153 tconn = rx_ConnectionOf(acall);
154 code = rx_SecurityClassOf(tconn);
155 if (code == 0) return 0;
156 else if (code == 1) { /* vab class */
157 goto done; /* no longer supported */
159 else if (code == 2) { /* kad class */
160 if ((code = rxkad_GetServerInfo
161 (acall->conn, NULL, 0/*was &exp*/,
162 name, inst, tcell, NULL)))
165 /* This test is unnecessary, since rxkad_GetServerInfo already check.
166 * In addition, this is wrong since exp must be unsigned. */
167 if (exp < FT_ApproxTime()) goto done;
169 if (strlen (tcell)) {
170 extern char *pr_realmName;
171 #if defined(AFS_ATHENA_STDENV) || defined(AFS_KERBREALM_ENV)
172 static char local_realm[AFS_REALM_SZ] = "";
173 if (!local_realm[0]) {
174 if (afs_krb_get_lrealm(local_realm, 0) != 0/*KSUCCESS*/)
175 strncpy(local_realm, pr_realmName, AFS_REALM_SZ);
179 #if defined(AFS_ATHENA_STDENV) || defined(AFS_KERBREALM_ENV)
180 strcasecmp (local_realm, tcell) &&
182 strcasecmp (pr_realmName, tcell))
185 strncpy (vname, name, sizeof(vname));
186 if (ilen = strlen (inst)) {
187 if (strlen(vname) + 1 + ilen >= sizeof(vname)) goto done;
189 strcat (vname, inst);
192 if (strlen(vname) + strlen(tcell) + 1 >= sizeof(vname)) goto done;
194 strcat (vname, tcell);
196 if (strcmp (AUTH_SUPERUSER, vname) == 0)
197 *aid = SYSADMINID; /* special case for the fileserver */
199 lcstring(vname, vname, sizeof(vname));
200 code = NameToID(at,vname,aid);
204 if (code && !pr_noAuth) return -1;
208 afs_int32 SPR_INewEntry (call,aname,aid,oid)
209 struct rx_call *call;
210 char aname[PR_MAXNAMELEN];
216 code = iNewEntry (call,aname,aid,oid);
217 osi_auditU (call, PTS_INewEntEvent, code, AUD_LONG, aid, AUD_STR, aname, AUD_LONG, oid, AUD_END);
221 afs_int32 iNewEntry (call,aname,aid,oid)
222 struct rx_call *call;
223 char aname[PR_MAXNAMELEN];
227 /* used primarily for conversion - not intended to be used as usual means
228 of entering people into the database. */
229 struct ubik_trans *tt;
230 register afs_int32 code;
237 if (code != PRSUCCESS) return code;
238 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS, &tt);
239 if (code) return code;
240 code = ubik_SetLock(tt, 1,1,LOCKWRITE);
241 if (code) ABORT_WITH(tt,code);
242 code = read_DbHeader(tt);
243 if (code) ABORT_WITH(tt,code);
245 code = WhoIsThis(call,tt,&cid);
246 if (code) ABORT_WITH(tt,PRPERM);
247 admin = IsAMemberOf(tt,cid,SYSADMINID);
249 /* first verify the id is good */
250 if (aid == 0) ABORT_WITH(tt,PRPERM);
253 /* only sysadmin can reuse a group id */
254 if (!admin && !pr_noAuth && (aid != ntohl(cheader.maxGroup)-1))
255 ABORT_WITH(tt,PRPERM);
257 if (FindByID (tt, aid)) ABORT_WITH(tt,PRIDEXIST);
259 /* check a few other things */
260 if (!CreateOK (tt, cid, oid, gflag, admin)) ABORT_WITH(tt,PRPERM);
262 code = CreateEntry (tt,aname,&aid,1,gflag,oid,cid);
263 if (code != PRSUCCESS) ABORT_WITH(tt,code);
265 /* finally, commit transaction */
266 code = ubik_EndTrans(tt);
267 if (code) return code;
272 afs_int32 SPR_NewEntry (call, aname, flag, oid, aid)
273 struct rx_call *call;
274 char aname[PR_MAXNAMELEN];
281 code = newEntry (call, aname, flag, oid, aid);
282 osi_auditU (call, PTS_NewEntEvent, code, AUD_LONG, *aid, AUD_STR, aname, AUD_LONG, oid, AUD_END);
286 afs_int32 newEntry (call, aname, flag, oid, aid)
287 struct rx_call *call;
288 char aname[PR_MAXNAMELEN];
293 register afs_int32 code;
294 struct ubik_trans *tt;
297 extern afs_int32 WhoIsThisWithName();
298 char cname[PR_MAXNAMELEN];
301 if (code) return code;
302 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
303 if (code) return code;
304 code = ubik_SetLock(tt,1,1,LOCKWRITE);
305 if (code) ABORT_WITH(tt,code);
306 code = read_DbHeader(tt);
307 if (code) ABORT_WITH(tt,code);
309 /* this is for cross-cell self registration. It is not added in the
310 * SPR_INewEntry because we want self-registration to only do
311 * automatic id assignment.
313 code = WhoIsThisWithName(call,tt,&cid,cname);
314 if (code != 2) {/* 2 specifies that this is a foreign cell request */
315 if (code) ABORT_WITH(tt,PRPERM);
316 admin = IsAMemberOf(tt,cid,SYSADMINID);
318 admin = (!strcmp(aname,cname)) || IsAMemberOf(tt,cid,SYSADMINID);
319 oid = cid = SYSADMINID;
321 if (!CreateOK (tt, cid, oid, flag, admin)) ABORT_WITH(tt,PRPERM);
323 code = CreateEntry (tt,aname,aid,0,flag,oid,cid);
324 if (code != PRSUCCESS) ABORT_WITH(tt,code);
326 code = ubik_EndTrans(tt);
327 if (code) return code;
333 afs_int32 SPR_WhereIsIt (call,aid,apos)
334 struct rx_call *call;
340 code = whereIsIt(call,aid,apos);
341 osi_auditU (call, PTS_WheIsItEvent, code, AUD_LONG, aid, AUD_LONG, *apos, AUD_END);
345 afs_int32 whereIsIt (call,aid,apos)
346 struct rx_call *call;
350 register afs_int32 code;
351 struct ubik_trans *tt;
355 if (code != PRSUCCESS) return code;
356 code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt);
357 if (code) return code;
358 code = ubik_SetLock(tt,1,1,LOCKREAD);
359 if (code) ABORT_WITH(tt,code);
360 code = read_DbHeader(tt);
361 if (code) ABORT_WITH(tt,code);
363 temp = FindByID(tt,aid);
364 if (!temp) ABORT_WITH(tt,PRNOENT);
366 code = ubik_EndTrans(tt);
367 if (code) return code;
372 afs_int32 SPR_DumpEntry (call,apos, aentry)
373 struct rx_call *call;
375 struct prdebugentry *aentry;
379 code = dumpEntry(call,apos, aentry);
380 osi_auditU (call, PTS_DmpEntEvent, code, AUD_LONG, apos, AUD_END);
384 afs_int32 dumpEntry (call,apos, aentry)
385 struct rx_call *call;
387 struct prdebugentry *aentry;
389 register afs_int32 code;
391 struct ubik_trans *tt;
394 if (code != PRSUCCESS) return code;
395 code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt);
396 if (code) return code;
397 code = ubik_SetLock(tt,1,1,LOCKREAD);
398 if (code) ABORT_WITH(tt,code);
399 code = read_DbHeader(tt);
400 if (code) ABORT_WITH(tt,code);
402 code = WhoIsThis(call,tt,&cid);
403 if (code) ABORT_WITH(tt,PRPERM);
404 code = pr_ReadEntry(tt, 0, apos, aentry);
405 if (code) ABORT_WITH(tt,code);
407 if (!AccessOK (tt, cid, 0, PRP_STATUS_MEM, 0))
408 ABORT_WITH(tt,PRPERM);
410 /* Since prdebugentry is in the form of a prentry not a coentry, we will
411 * return the coentry slots in network order where the string is. */
413 if (aentry->flags & PRCONT) { /* wrong type, get coentry instead */
414 code = pr_ReadCoEntry(tt, 0, apos, aentry);
415 if (code) ABORT_WITH(tt,code);
418 code = ubik_EndTrans(tt);
419 if (code) return code;
423 afs_int32 SPR_AddToGroup (call,aid,gid)
424 struct rx_call *call;
430 code = addToGroup (call,aid,gid);
431 osi_auditU (call, PTS_AdToGrpEvent, code, AUD_LONG, gid, AUD_LONG, aid, AUD_END);
435 afs_int32 addToGroup (call,aid,gid)
436 struct rx_call *call;
440 register afs_int32 code;
441 struct ubik_trans *tt;
444 struct prentry tentry;
445 struct prentry uentry;
449 if (code != PRSUCCESS) return code;
450 if (gid == ANYUSERID || gid == AUTHUSERID) return PRPERM;
451 if (aid == ANONYMOUSID) return PRPERM;
452 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
453 if (code) return code;
454 code = ubik_SetLock(tt,1,1,LOCKWRITE);
455 if (code) ABORT_WITH(tt,code);
456 code = read_DbHeader(tt);
457 if (code) ABORT_WITH(tt,code);
459 code = WhoIsThis(call, tt, &cid);
460 if (code) ABORT_WITH(tt,PRPERM);
461 tempu = FindByID(tt,aid);
462 if (!tempu) ABORT_WITH(tt,PRNOENT);
463 memset(&uentry, 0, sizeof(uentry));
464 code = pr_ReadEntry(tt,0,tempu,&uentry);
465 if (code != 0) ABORT_WITH(tt,code);
467 #if !defined(SUPERGROUPS)
468 /* we don't allow groups as members of groups at present */
469 if (uentry.flags & PRGRP) ABORT_WITH(tt,PRNOTUSER);
472 tempg = FindByID(tt,gid);
473 if (!tempg) ABORT_WITH(tt,PRNOENT);
474 code = pr_ReadEntry(tt,0,tempg,&tentry);
475 if (code != 0) ABORT_WITH(tt,code);
476 /* make sure that this is a group */
477 if (!(tentry.flags & PRGRP)) ABORT_WITH(tt,PRNOTGROUP);
478 if (!AccessOK (tt, cid, &tentry, PRP_ADD_MEM, PRP_ADD_ANY)) ABORT_WITH(tt,PRPERM);
480 code = AddToEntry (tt, &tentry, tempg, aid);
481 if (code != PRSUCCESS) ABORT_WITH(tt,code);
483 #if defined(SUPERGROUPS)
484 if (uentry.flags & PRGRP)
485 code = AddToSGEntry (tt, &uentry, tempu, gid); /* mod group to be in sg */
488 /* now, modify the user's entry as well */
489 code = AddToEntry (tt, &uentry, tempu, gid);
490 if (code != PRSUCCESS) ABORT_WITH(tt,code);
491 code = ubik_EndTrans(tt);
492 if (code) return code;
496 afs_int32 SPR_NameToID (call, aname, aid)
497 struct rx_call *call;
503 code = nameToID (call, aname, aid);
504 osi_auditU (call, PTS_NmToIdEvent, code, AUD_END);
508 afs_int32 nameToID (call, aname, aid)
509 struct rx_call *call;
513 register afs_int32 code;
514 struct ubik_trans *tt;
519 /* Initialize return struct */
521 aid->idlist_val = NULL;
523 size = aname->namelist_len;
524 if (size == 0) return 0;
525 if (size < 0) return PRTOOMANY;
527 aid->idlist_val = (afs_int32 *)malloc(size*sizeof(afs_int32));
528 if (!aid->idlist_val) return PRNOMEM;
531 if (code != PRSUCCESS) return code;
532 code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt);
533 if (code) return code;
534 code = ubik_SetLock(tt,1,1,LOCKREAD);
535 if (code) ABORT_WITH(tt,code);
536 code = read_DbHeader(tt);
537 if (code) ABORT_WITH(tt,code);
539 for (i=0;i<aname->namelist_len;i++) {
540 code = NameToID(tt,aname->namelist_val[i],&aid->idlist_val[i]);
541 if (code != PRSUCCESS) aid->idlist_val[i] = ANONYMOUSID;
542 if (count++ > 50) IOMGR_Poll(), count = 0;
544 aid->idlist_len = aname->namelist_len;
546 code = ubik_EndTrans(tt);
547 if (code) return code;
553 * Given an array of ids, find the name for each of them.
554 * The array of ids and names is unlimited.
556 afs_int32 SPR_IDToName (call, aid, aname)
557 struct rx_call *call;
563 code = idToName (call, aid, aname);
564 osi_auditU (call, PTS_IdToNmEvent, code, AUD_LONG, aid, AUD_END);
568 afs_int32 idToName (call, aid, aname)
569 struct rx_call *call;
573 register afs_int32 code;
574 struct ubik_trans *tt;
579 /* leave this first for rpc stub */
580 size = aid->idlist_len;
581 if (size == 0) return 0;
582 if (size < 0) return PRTOOMANY;
583 aname->namelist_val = (prname *)malloc(size*PR_MAXNAMELEN);
584 aname->namelist_len = 0;
585 if (aname->namelist_val == 0) return PRNOMEM;
586 if (aid->idlist_len == 0) return 0;
587 if (size == 0) return PRTOOMANY; /* rxgen will probably handle this */
590 if (code != PRSUCCESS) return code;
591 code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt);
592 if (code) return code;
593 code = ubik_SetLock(tt,1,1,LOCKREAD);
594 if (code) ABORT_WITH(tt,code);
595 code = read_DbHeader(tt);
596 if (code) ABORT_WITH(tt,code);
598 for (i=0;i<aid->idlist_len;i++) {
599 code = IDToName(tt,aid->idlist_val[i],aname->namelist_val[i]);
600 if (code != PRSUCCESS)
601 sprintf(aname->namelist_val[i],"%d",aid->idlist_val[i]);
602 if (count++ > 50) IOMGR_Poll(), count = 0;
604 aname->namelist_len = aid->idlist_len;
606 code = ubik_EndTrans(tt);
607 if (code) return code;
611 afs_int32 SPR_Delete (call, aid)
612 struct rx_call *call;
617 code = Delete (call, aid);
618 osi_auditU (call, PTS_DelEvent, code, AUD_LONG, aid, AUD_END);
622 afs_int32 Delete (call, aid)
623 struct rx_call *call;
626 register afs_int32 code;
627 struct ubik_trans *tt;
629 struct prentry tentry;
634 if (code) return code;
635 if (code != PRSUCCESS) return code;
636 if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID ||
637 aid == ANONYMOUSID) return PRPERM;
638 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
639 if (code) return code;
640 code = ubik_SetLock(tt,1,1,LOCKWRITE);
641 if (code) ABORT_WITH(tt,code);
642 code = read_DbHeader(tt);
643 if (code) ABORT_WITH(tt,code);
645 code = WhoIsThis(call,tt,&cid);
646 if (code) ABORT_WITH(tt,PRPERM);
648 /* Read in entry to be deleted */
649 loc = FindByID (tt, aid);
650 if (loc == 0) ABORT_WITH(tt,PRNOENT);
651 code = pr_ReadEntry (tt, 0, loc, &tentry);
652 if (code) ABORT_WITH(tt,PRDBFAIL);
654 /* Do some access checking */
655 if (tentry.owner != cid &&
656 !IsAMemberOf (tt, cid, SYSADMINID) &&
657 !IsAMemberOf (tt, cid, tentry.owner) && !pr_noAuth)
658 ABORT_WITH(tt,PRPERM);
660 /* Delete each continuation block as a separate transaction so that no one
661 * transaction become to large to complete. */
663 while (nptr != (afs_int32)NULL) {
664 struct contentry centry;
667 code = pr_ReadCoEntry(tt, 0, nptr, ¢ry);
668 if (code != 0) ABORT_WITH(tt,PRDBFAIL);
669 for (i=0;i<COSIZE;i++) {
670 if (centry.entries[i] == PRBADID) continue;
671 if (centry.entries[i] == 0) break;
672 #if defined(SUPERGROUPS)
673 if (aid < 0 && centry.entries[i] < 0) /* Supergroup */
674 code = RemoveFromSGEntry (tt, aid, centry.entries[i]);
677 code = RemoveFromEntry (tt, aid, centry.entries[i]);
678 if (code) ABORT_WITH(tt,code);
679 tentry.count--; /* maintain count */
680 if ((i&3) == 0) IOMGR_Poll();
682 tentry.next = centry.next; /* thread out this block */
683 code = FreeBlock (tt, nptr); /* free continuation block */
684 if (code) ABORT_WITH(tt,code);
685 code = pr_WriteEntry (tt, 0, loc, &tentry); /* update main entry */
686 if (code) ABORT_WITH(tt,code);
688 /* end this trans and start a new one */
689 code = ubik_EndTrans(tt);
690 if (code) return code;
691 IOMGR_Poll(); /* just to keep the connection alive */
692 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
693 if (code) return code;
694 code = ubik_SetLock(tt,1,1,LOCKWRITE);
695 if (code) ABORT_WITH(tt,code);
697 /* re-read entry to get consistent uptodate info */
698 loc = FindByID (tt, aid);
699 if (loc == 0) ABORT_WITH(tt,PRNOENT);
700 code = pr_ReadEntry (tt, 0, loc, &tentry);
701 if (code) ABORT_WITH(tt,PRDBFAIL);
706 #if defined(SUPERGROUPS)
707 /* Delete each continuation block as a separate transaction
708 * so that no one transaction become too large to complete. */
710 struct prentryg *tentryg = (struct prentryg *)&tentry;
711 nptr = tentryg->nextsg;
712 while (nptr != NULL) {
713 struct contentry centry;
716 code = pr_ReadCoEntry(tt, 0, nptr, ¢ry);
717 if (code != 0) ABORT_WITH(tt,PRDBFAIL);
718 for (i=0;i<COSIZE;i++) {
719 if (centry.entries[i] == PRBADID) continue;
720 if (centry.entries[i] == 0) break;
721 code = RemoveFromEntry (tt, aid, centry.entries[i]);
722 if (code) ABORT_WITH(tt,code);
723 tentryg->countsg--; /* maintain count */
724 if ((i&3) == 0) IOMGR_Poll();
726 tentryg->nextsg = centry.next; /* thread out this block */
727 code = FreeBlock (tt, nptr); /* free continuation block */
728 if (code) ABORT_WITH(tt,code);
729 code = pr_WriteEntry (tt, 0, loc, &tentry); /* update main entry */
730 if (code) ABORT_WITH(tt,code);
732 /* end this trans and start a new one */
733 code = ubik_EndTrans(tt);
734 if (code) return code;
735 IOMGR_Poll(); /* just to keep the connection alive */
737 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
738 if (code) return code;
739 code = ubik_SetLock(tt,1,1,LOCKWRITE);
740 if (code) ABORT_WITH(tt,code);
742 /* re-read entry to get consistent uptodate info */
743 loc = FindByID (tt, aid);
744 if (loc == 0) ABORT_WITH(tt,PRNOENT);
745 code = pr_ReadEntry (tt, 0, loc, &tentry);
746 if (code) ABORT_WITH(tt,PRDBFAIL);
748 nptr = tentryg->nextsg;
752 #endif /* SUPERGROUPS */
754 /* Then move the owned chain, except possibly ourself to the orphan list.
755 * Because this list can be very long and so exceed the size of a ubik
756 * transaction, we start a new transaction every 50 entries. */
759 while (nptr != (afs_int32)NULL) {
760 struct prentry nentry;
762 code = pr_ReadEntry (tt, 0, nptr, &nentry);
763 if (code) ABORT_WITH(tt,PRDBFAIL);
764 nptr = tentry.owned = nentry.nextOwned; /* thread out */
766 if (nentry.id != tentry.id) { /* don't add us to orphan chain! */
767 code = AddToOrphan (tt, nentry.id);
768 if (code) ABORT_WITH(tt,code);
770 if ((count & 3) == 0) IOMGR_Poll();
772 if (count < 50) continue;
773 code = pr_WriteEntry (tt, 0, loc, &tentry); /* update main entry */
774 if (code) ABORT_WITH(tt,code);
776 /* end this trans and start a new one */
777 code = ubik_EndTrans(tt);
778 if (code) return code;
779 IOMGR_Poll(); /* just to keep the connection alive */
780 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
781 if (code) return code;
782 code = ubik_SetLock(tt,1,1,LOCKWRITE);
783 if (code) ABORT_WITH(tt,code);
785 /* re-read entry to get consistent uptodate info */
786 loc = FindByID (tt, aid);
787 if (loc == 0) ABORT_WITH(tt,PRNOENT);
788 code = pr_ReadEntry (tt, 0, loc, &tentry);
789 if (code) ABORT_WITH(tt,PRDBFAIL);
794 /* now do what's left of the deletion stuff */
795 code = DeleteEntry (tt, &tentry, loc);
796 if (code != PRSUCCESS) ABORT_WITH(tt,code);
798 code = ubik_EndTrans(tt);
799 if (code) return code;
803 afs_int32 SPR_UpdateEntry (call, aid, name, uentry)
804 struct rx_call *call;
807 struct PrUpdateEntry *uentry;
809 register afs_int32 code;
810 struct ubik_trans *tt;
812 struct prentry tentry;
817 if (code) return code;
818 if (code != PRSUCCESS) return code;
821 if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID ||
822 aid == ANONYMOUSID) return PRPERM;
824 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
825 if (code) return code;
826 code = ubik_SetLock(tt,1,1,LOCKWRITE);
827 if (code) ABORT_WITH(tt,code);
828 code = read_DbHeader(tt);
829 if (code) ABORT_WITH(tt,code);
831 code = WhoIsThis(call,tt,&cid);
832 if (code) ABORT_WITH(tt,PRPERM);
833 code = IsAMemberOf (tt, cid, SYSADMINID);
834 if (!code && !pr_noAuth) ABORT_WITH(tt,PRPERM);
836 /* Read in entry to be deleted */
838 loc = FindByID (tt, aid);
840 loc = FindByName(tt, name, &tentry);
842 if (loc == 0) ABORT_WITH(tt,PRNOENT);
843 code = pr_ReadEntry (tt, 0, loc, &tentry);
844 if (code) ABORT_WITH(tt,PRDBFAIL);
846 if (uentry->Mask & PRUPDATE_NAMEHASH) {
848 code = RemoveFromNameHash(tt, tentry.name, &tloc);
849 if (code != PRSUCCESS) ABORT_WITH(tt,PRDBFAIL);
850 code = AddToNameHash(tt, tentry.name, loc);
851 if (code) ABORT_WITH(tt,code);
854 if (uentry->Mask & PRUPDATE_IDHASH) {
856 if (!id) id = tentry.id;
857 code = RemoveFromIDHash(tt, id, &tloc);
858 if (code != PRSUCCESS) ABORT_WITH(tt,PRDBFAIL);
859 code = AddToIDHash(tt, id, loc);
860 if (code) ABORT_WITH(tt,code);
863 code = ubik_EndTrans(tt);
864 if (code) return code;
868 afs_int32 SPR_RemoveFromGroup (call,aid,gid)
869 struct rx_call *call;
875 code = removeFromGroup (call,aid,gid);
876 osi_auditU (call, PTS_RmFmGrpEvent, code, AUD_LONG, gid, AUD_LONG, aid, AUD_END);
880 afs_int32 removeFromGroup (call,aid,gid)
881 struct rx_call *call;
885 register afs_int32 code;
886 struct ubik_trans *tt;
889 struct prentry uentry;
890 struct prentry gentry;
894 if (code != PRSUCCESS) return code;
895 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
896 if (code) return code;
897 code = ubik_SetLock(tt,1,1,LOCKWRITE);
898 if (code) ABORT_WITH(tt,code);
899 code = read_DbHeader(tt);
900 if (code) ABORT_WITH(tt,code);
902 code = WhoIsThis(call,tt,&cid);
903 if (code) ABORT_WITH(tt,PRPERM);
904 tempu = FindByID(tt,aid);
905 if (!tempu) ABORT_WITH(tt,PRNOENT);
906 tempg = FindByID(tt,gid);
907 if (!tempg) ABORT_WITH(tt,PRNOENT);
908 memset(&uentry, 0, sizeof(uentry));
909 memset(&gentry, 0, sizeof(gentry));
910 code = pr_ReadEntry(tt,0,tempu,&uentry);
911 if (code != 0) ABORT_WITH(tt,code);
912 code = pr_ReadEntry(tt,0,tempg,&gentry);
913 if (code != 0) ABORT_WITH(tt,code);
914 if (!(gentry.flags & PRGRP)) ABORT_WITH(tt,PRNOTGROUP);
915 #if !defined(SUPERGROUPS)
916 if (uentry.flags & PRGRP) ABORT_WITH(tt,PRNOTUSER);
918 if (!AccessOK (tt, cid, &gentry, PRP_REMOVE_MEM, 0)) ABORT_WITH(tt,PRPERM);
919 code = RemoveFromEntry(tt,aid,gid);
920 if (code != PRSUCCESS) ABORT_WITH(tt,code);
921 #if defined(SUPERGROUPS)
922 if (!(uentry.flags & PRGRP))
924 code = RemoveFromEntry(tt,gid,aid);
925 #if defined(SUPERGROUPS)
927 code = RemoveFromSGEntry(tt,gid,aid);
929 if (code != PRSUCCESS) ABORT_WITH(tt,code);
931 code = ubik_EndTrans(tt);
932 if (code) return code;
937 afs_int32 SPR_GetCPS (call, aid, alist, over)
938 struct rx_call *call;
945 code = getCPS (call, aid, alist, over);
946 osi_auditU (call, PTS_GetCPSEvent, code, AUD_LONG, aid, AUD_END);
950 afs_int32 getCPS (call, aid, alist, over)
951 struct rx_call *call;
956 register afs_int32 code;
957 struct ubik_trans *tt;
960 struct prentry tentry;
963 alist->prlist_len = 0;
964 alist->prlist_val = NULL;
966 if (code != PRSUCCESS) return code;
967 code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt);
968 if (code) return code;
969 code = ubik_SetLock(tt,1,1,LOCKREAD);
970 if (code) ABORT_WITH(tt,code);
971 code = read_DbHeader(tt);
972 if (code) ABORT_WITH(tt,code);
974 temp = FindByID (tt, aid);
975 if (!temp) ABORT_WITH(tt,PRNOENT);
976 code = pr_ReadEntry (tt, 0, temp, &tentry);
977 if (code) ABORT_WITH(tt,code);
979 /* afs does authenticate now */
980 code = WhoIsThis (call, tt, &cid);
981 if (code || !AccessOK (tt, cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
982 ABORT_WITH(tt,PRPERM);
984 code = GetList(tt, &tentry, alist, 1);
985 if (code != PRSUCCESS) ABORT_WITH(tt,code);
987 code = ubik_EndTrans(tt);
999 for (i = (CPS.prlist_len-1) ; i >= 0; i--) {
1000 if (CPS.prlist_val[i] == id)
1005 #endif /* IP_WILDCARDS */
1008 afs_int32 SPR_GetCPS2 (call, aid, ahost, alist, over)
1009 struct rx_call *call;
1017 code = getCPS2 (call, aid, ahost, alist, over);
1018 osi_auditU (call, PTS_GetCPS2Event, code, AUD_LONG, aid, AUD_HOST, ahost, AUD_END);
1022 afs_int32 getCPS2 (call, aid, ahost, alist, over)
1023 struct rx_call *call;
1029 register afs_int32 code;
1030 struct ubik_trans *tt;
1033 struct prentry tentry;
1034 struct prentry host_tentry;
1037 struct in_addr iaddr;
1039 extern afs_int32 addWildCards();
1040 #endif /* IP_WILDCARDS */
1043 iaddr.s_addr = ntohl(ahost);
1044 alist->prlist_len = 0;
1045 alist->prlist_val = NULL;
1047 if (code != PRSUCCESS) return code;
1048 code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt);
1049 if (code) return code;
1050 code = ubik_SetLock(tt,1,1,LOCKREAD);
1051 if (code) ABORT_WITH(tt,code);
1052 code = read_DbHeader(tt);
1053 if (code) ABORT_WITH(tt,code);
1055 if (aid != PRBADID) {
1056 temp = FindByID(tt,aid);
1057 if (!temp) ABORT_WITH(tt,PRNOENT);
1058 code = pr_ReadEntry (tt, 0, temp, &tentry);
1059 if (code) ABORT_WITH(tt,code);
1061 /* afs does authenticate now */
1062 code = WhoIsThis (call, tt, &cid);
1063 if (code || !AccessOK (tt, cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1064 ABORT_WITH(tt,PRPERM);
1066 code = NameToID(tt, inet_ntoa(iaddr),&hostid);
1067 if (code == PRSUCCESS && hostid != 0) {
1068 temp = FindByID(tt,hostid);
1070 code = pr_ReadEntry (tt, 0, temp, &host_tentry);
1071 if (code == PRSUCCESS)
1074 fprintf(stderr,"pr_ReadEntry returned %d\n",code);
1076 fprintf(stderr,"FindByID Failed -- Not found\n");
1079 code = GetList2(tt, &tentry, &host_tentry, alist, 1);
1081 code = GetList(tt, &tentry, alist, 1);
1084 code = addWildCards(tt,alist,ntohl(ahost));
1085 #endif /* IP_WILDCARDS */
1086 if (code != PRSUCCESS) ABORT_WITH(tt,code);
1088 code = ubik_EndTrans(tt);
1093 afs_int32 SPR_GetHostCPS (call, ahost, alist, over)
1094 struct rx_call *call;
1101 code = getHostCPS (call, ahost, alist, over);
1102 osi_auditU (call, PTS_GetHCPSEvent, code, AUD_HOST, ahost, AUD_END);
1106 afs_int32 getHostCPS (call, ahost, alist, over)
1107 struct rx_call *call;
1112 register afs_int32 code, temp;
1113 struct ubik_trans *tt;
1114 struct prentry host_tentry;
1116 struct in_addr iaddr;
1118 extern afs_int32 addWildCards();
1119 #endif /* IP_WILDCARDS */
1122 iaddr.s_addr = ntohl(ahost);
1123 alist->prlist_len = 0;
1124 alist->prlist_val = NULL;
1126 if (code != PRSUCCESS) return code;
1127 code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt);
1128 if (code) return code;
1129 code = ubik_SetLock(tt,1,1,LOCKREAD);
1130 if (code) ABORT_WITH(tt,code);
1131 code = read_DbHeader(tt);
1132 if (code) ABORT_WITH(tt,code);
1134 code = NameToID(tt, inet_ntoa(iaddr), &hostid);
1135 if (code == PRSUCCESS && hostid != 0) {
1136 temp = FindByID(tt,hostid);
1138 code = pr_ReadEntry (tt, 0, temp, &host_tentry);
1139 if (code == PRSUCCESS) {
1140 code = GetList(tt, &host_tentry, alist, 0);
1143 fprintf(stderr,"pr_ReadEntry returned %d\n",code);
1145 fprintf(stderr,"FindByID Failed -- Not found\n");
1148 code = addWildCards(tt,alist,ntohl(ahost));
1149 #endif /* IP_WILDCARDS */
1151 if (code != PRSUCCESS) ABORT_WITH(tt,code);
1153 code = ubik_EndTrans(tt);
1158 afs_int32 SPR_ListMax (call,uid,gid)
1159 struct rx_call *call;
1165 code = listMax(call,uid,gid);
1166 osi_auditU (call, PTS_LstMaxEvent, code, AUD_END);
1170 afs_int32 listMax (call,uid,gid)
1171 struct rx_call *call;
1175 register afs_int32 code;
1176 struct ubik_trans *tt;
1179 if (code != PRSUCCESS) return code;
1180 code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt);
1181 if (code) return code;
1182 code = ubik_SetLock(tt,1,1,LOCKREAD);
1183 if (code) ABORT_WITH(tt,code);
1184 code = read_DbHeader(tt);
1185 if (code) ABORT_WITH(tt,code);
1187 code = GetMax(tt,uid,gid);
1188 if (code != PRSUCCESS) ABORT_WITH(tt,code);
1190 code = ubik_EndTrans(tt);
1191 if (code) return code;
1195 afs_int32 SPR_SetMax (call,aid,gflag)
1196 struct rx_call *call;
1202 code = setMax (call,aid,gflag);
1203 osi_auditU (call, PTS_SetMaxEvent, code, AUD_LONG, aid, AUD_LONG, gflag, AUD_END);
1207 afs_int32 setMax (call,aid,gflag)
1208 struct rx_call *call;
1212 register afs_int32 code;
1213 struct ubik_trans *tt;
1217 if (code != PRSUCCESS) return code;
1218 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
1219 if (code) return code;
1220 code = ubik_SetLock(tt,1,1,LOCKWRITE);
1221 if (code) ABORT_WITH(tt,code);
1222 code = read_DbHeader(tt);
1223 if (code) ABORT_WITH(tt,code);
1225 code = WhoIsThis(call,tt,&cid);
1226 if (code) ABORT_WITH(tt,PRPERM);
1227 if (!AccessOK (tt, cid, 0, 0, 0)) ABORT_WITH(tt,PRPERM);
1228 if (((gflag & PRGRP) && (aid > 0)) || (!(gflag & PRGRP) && (aid < 0))) ABORT_WITH(tt,PRBADARG);
1230 code = SetMax(tt,aid,gflag);
1231 if (code != PRSUCCESS) ABORT_WITH(tt,code);
1233 code = ubik_EndTrans(tt);
1234 if (code) return code;
1238 afs_int32 SPR_ListEntry (call,aid,aentry)
1239 struct rx_call *call;
1241 struct prcheckentry *aentry;
1245 code = listEntry (call,aid,aentry);
1246 osi_auditU (call, PTS_LstEntEvent, code, AUD_LONG, aid, AUD_END);
1250 afs_int32 listEntry (call,aid,aentry)
1251 struct rx_call *call;
1253 struct prcheckentry *aentry;
1255 register afs_int32 code;
1256 struct ubik_trans *tt;
1259 struct prentry tentry;
1262 if (code != PRSUCCESS) return code;
1263 code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt);
1264 if (code) return code;
1265 code = ubik_SetLock(tt,1,1,LOCKREAD);
1266 if (code) ABORT_WITH(tt,code);
1267 code = read_DbHeader(tt);
1268 if (code) ABORT_WITH(tt,code);
1270 code = WhoIsThis(call,tt,&cid);
1271 if (code) ABORT_WITH(tt,PRPERM);
1272 temp = FindByID(tt,aid);
1273 if (!temp) ABORT_WITH(tt,PRNOENT);
1274 code = pr_ReadEntry(tt, 0, temp, &tentry);
1275 if (code != 0) ABORT_WITH(tt,code);
1276 if (!AccessOK (tt, cid, &tentry, PRP_STATUS_MEM, PRP_STATUS_ANY))
1277 ABORT_WITH(tt,PRPERM);
1279 aentry->flags = tentry.flags >> PRIVATE_SHIFT;
1280 if (aentry->flags == 0) {
1281 if (tentry.flags & PRGRP)
1282 aentry->flags = PRP_GROUP_DEFAULT >> PRIVATE_SHIFT;
1283 else aentry->flags = PRP_USER_DEFAULT >> PRIVATE_SHIFT;
1285 aentry->owner = tentry.owner;
1286 aentry->id = tentry.id;
1287 strncpy(aentry->name,tentry.name,PR_MAXNAMELEN);
1288 aentry->creator = tentry.creator;
1289 aentry->ngroups = tentry.ngroups;
1290 aentry->nusers = tentry.nusers;
1291 aentry->count = tentry.count;
1292 memset(aentry->reserved, 0, sizeof(aentry->reserved));
1293 code = ubik_EndTrans(tt);
1294 if (code) return code;
1298 afs_int32 SPR_ListEntries(call, flag, startindex, bulkentries, nextstartindex)
1299 struct rx_call *call;
1301 afs_int32 startindex;
1302 prentries *bulkentries;
1303 afs_int32 *nextstartindex;
1307 code = listEntries(call, flag, startindex, bulkentries, nextstartindex);
1308 osi_auditU (call, PTS_LstEntsEvent, code, AUD_LONG, flag, AUD_END);
1312 afs_int32 listEntries(call, flag, startindex, bulkentries, nextstartindex)
1313 struct rx_call *call;
1315 afs_int32 startindex;
1316 prentries *bulkentries;
1317 afs_int32 *nextstartindex;
1320 struct ubik_trans *tt;
1322 afs_int32 i, eof, pos, maxentries, f;
1323 struct prentry tentry;
1324 afs_int32 pollcount=0;
1326 *nextstartindex = -1;
1327 bulkentries->prentries_val = 0;
1328 bulkentries->prentries_len = 0;
1331 if (code != PRSUCCESS) return code;
1332 code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt);
1333 if (code) return code;
1334 code = ubik_SetLock(tt,1,1,LOCKREAD);
1335 if (code) ABORT_WITH(tt,code);
1336 code = read_DbHeader(tt);
1337 if (code) ABORT_WITH(tt,code);
1339 /* Make sure we are an authenticated caller and that we are on the
1342 code = WhoIsThis(call,tt,&cid);
1343 if (code) ABORT_WITH(tt,PRPERM);
1344 code = IsAMemberOf (tt, cid, SYSADMINID);
1345 if (!code && !pr_noAuth) ABORT_WITH(tt,PRPERM);
1347 eof = ntohl(cheader.eofPtr) - sizeof(cheader);
1348 maxentries = eof / sizeof(struct prentry);
1349 for (i=startindex; i<maxentries; i++) {
1350 pos = i * sizeof(struct prentry) + sizeof(cheader);
1351 code = pr_ReadEntry (tt, 0, pos, &tentry);
1352 if (code) goto done;
1354 if (++pollcount > 50) {
1359 f = (tentry.flags & PRTYPE);
1360 if ( ((flag & PRUSERS ) && (f == 0) ) || /* User entry */
1361 ((flag & PRGROUPS) && (f & PRGRP)) ) { /* Group entry */
1362 code = put_prentries(&tentry, bulkentries);
1363 if (code == -1) break; /* Filled return array */
1364 if (code) goto done;
1369 *nextstartindex = i;
1373 if (bulkentries->prentries_val)
1374 free(bulkentries->prentries_val);
1375 bulkentries->prentries_val = 0;
1376 bulkentries->prentries_len = 0;
1377 ABORT_WITH(tt, code);
1380 code = ubik_EndTrans(tt);
1382 if (code) return code;
1386 #define PR_MAXENTRIES 500
1387 afs_int32 put_prentries(tentry, bulkentries)
1388 struct prentry *tentry;
1389 prentries *bulkentries;
1391 struct prlistentries *entry;
1393 if (bulkentries->prentries_val == 0) {
1394 bulkentries->prentries_len = 0;
1395 bulkentries->prentries_val = (struct prlistentries *)malloc(PR_MAXENTRIES * sizeof(struct prentry));
1396 if (!bulkentries->prentries_val) {
1401 if (bulkentries->prentries_len >= PR_MAXENTRIES) {
1405 entry = (struct prlistentries *)bulkentries->prentries_val;
1406 entry += bulkentries->prentries_len;
1408 entry->flags = tentry->flags >> PRIVATE_SHIFT;
1409 if (entry->flags == 0) {
1410 entry->flags = ( (tentry->flags & PRGRP)?PRP_GROUP_DEFAULT
1411 :PRP_USER_DEFAULT ) >> PRIVATE_SHIFT;
1413 entry->owner = tentry->owner;
1414 entry->id = tentry->id;
1415 entry->creator = tentry->creator;
1416 entry->ngroups = tentry->ngroups;
1417 entry->nusers = tentry->nusers;
1418 entry->count = tentry->count;
1419 strncpy(entry->name,tentry->name,PR_MAXNAMELEN);
1420 memset(entry->reserved, 0, sizeof(entry->reserved));
1421 bulkentries->prentries_len++;
1425 afs_int32 SPR_ChangeEntry (call,aid,name,oid,newid)
1426 struct rx_call *call;
1434 code = changeEntry (call,aid,name,oid,newid);
1435 osi_auditU (call, PTS_ChgEntEvent, code, AUD_LONG, aid, AUD_STR, name,
1437 AUD_LONG, newid, AUD_END);
1441 afs_int32 changeEntry (call,aid,name,oid,newid)
1442 struct rx_call *call;
1448 register afs_int32 code;
1449 struct ubik_trans *tt;
1453 if (!name) return PRPERM;
1457 if (code) return code;
1458 if (aid == ANYUSERID || aid == AUTHUSERID || aid == ANONYMOUSID ||
1459 aid == SYSADMINID) return PRPERM;
1460 if (code != PRSUCCESS) return code;
1461 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
1462 if (code) return code;
1463 code = ubik_SetLock(tt,1,1,LOCKWRITE);
1464 if (code) ABORT_WITH(tt,code);
1465 code = read_DbHeader(tt);
1466 if (code) ABORT_WITH(tt,code);
1468 code = WhoIsThis(call,tt,&cid);
1469 if (code) ABORT_WITH(tt,PRPERM);
1470 pos = FindByID(tt,aid);
1471 if (!pos) ABORT_WITH(tt,PRNOENT);
1472 /* protection check in changeentry */
1473 code = ChangeEntry(tt,aid,cid,name,oid,newid);
1474 if (code != PRSUCCESS) ABORT_WITH(tt,code);
1476 code = ubik_EndTrans(tt);
1480 afs_int32 SPR_SetFieldsEntry (call, id, mask, flags, ngroups, nusers, spare1, spare2)
1481 struct rx_call *call;
1483 afs_int32 mask; /* specify which fields to update */
1484 afs_int32 flags, ngroups, nusers;
1485 afs_int32 spare1, spare2;
1489 code = setFieldsEntry (call, id, mask, flags, ngroups, nusers, spare1, spare2);
1490 osi_auditU (call, PTS_SetFldEntEvent, code, AUD_LONG, id, AUD_END);
1494 afs_int32 setFieldsEntry (call, id, mask, flags, ngroups, nusers, spare1, spare2)
1495 struct rx_call *call;
1497 afs_int32 mask; /* specify which fields to update */
1498 afs_int32 flags, ngroups, nusers;
1499 afs_int32 spare1, spare2;
1501 register afs_int32 code;
1502 struct ubik_trans *tt;
1505 struct prentry tentry;
1508 if (mask == 0) return 0; /* no-op */
1510 if (code) return code;
1511 if (id == ANYUSERID || id == AUTHUSERID || id == ANONYMOUSID)
1513 if (code != PRSUCCESS) return code;
1514 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
1515 if (code) return code;
1516 code = ubik_SetLock(tt,1,1,LOCKWRITE);
1517 if (code) ABORT_WITH(tt,code);
1518 code = read_DbHeader(tt);
1519 if (code) ABORT_WITH(tt,code);
1521 code = WhoIsThis(call,tt,&cid);
1522 if (code) ABORT_WITH(tt,PRPERM);
1523 pos = FindByID(tt,id);
1524 if (!pos) ABORT_WITH(tt,PRNOENT);
1525 code = pr_ReadEntry (tt, 0, pos, &tentry);
1526 if (code) ABORT_WITH(tt,code);
1527 tflags = tentry.flags;
1529 if (mask & (PR_SF_NGROUPS | PR_SF_NUSERS)) {
1530 if (!AccessOK (tt, cid, 0, 0, 0)) ABORT_WITH(tt,PRPERM);
1531 if ((tflags & PRQUOTA) == 0) { /* default if only setting one */
1532 tentry.ngroups = tentry.nusers = 20;
1535 if (!AccessOK (tt, cid, &tentry, 0, 0)) ABORT_WITH(tt,PRPERM);
1538 if (mask & 0xffff) { /* if setting flag bits */
1539 afs_int32 flagsMask = mask & 0xffff;
1540 tflags &= ~(flagsMask << PRIVATE_SHIFT);
1541 tflags |= (flags & flagsMask) << PRIVATE_SHIFT;
1545 if (mask & PR_SF_NGROUPS) { /* setting group limit */
1546 if (ngroups < 0) ABORT_WITH(tt,PRBADARG);
1547 tentry.ngroups = ngroups;
1551 if (mask & PR_SF_NUSERS) { /* setting foreign user limit */
1552 if (nusers < 0) ABORT_WITH(tt,PRBADARG);
1553 tentry.nusers = nusers;
1556 tentry.flags = tflags;
1558 code = pr_WriteEntry (tt, 0, pos, &tentry);
1559 if (code) ABORT_WITH(tt,code);
1561 code = ubik_EndTrans(tt);
1565 afs_int32 SPR_ListElements (call, aid, alist, over)
1566 struct rx_call *call;
1573 code = listElements (call, aid, alist, over);
1574 osi_auditU (call, PTS_LstEleEvent, code, AUD_LONG, aid, AUD_END);
1578 afs_int32 listElements (call, aid, alist, over)
1579 struct rx_call *call;
1584 register afs_int32 code;
1585 struct ubik_trans *tt;
1588 struct prentry tentry;
1591 alist->prlist_len = 0;
1592 alist->prlist_val = NULL;
1595 if (code != PRSUCCESS) return code;
1596 code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt);
1597 if (code) return code;
1598 code = ubik_SetLock(tt,1,1,LOCKREAD);
1599 if (code) ABORT_WITH(tt,code);
1600 code = read_DbHeader(tt);
1601 if (code) ABORT_WITH(tt,code);
1603 code = WhoIsThis(call,tt,&cid);
1604 if (code) ABORT_WITH(tt,PRPERM);
1606 temp = FindByID(tt,aid);
1607 if (!temp) ABORT_WITH(tt,PRNOENT);
1608 code = pr_ReadEntry (tt, 0, temp, &tentry);
1609 if (code) ABORT_WITH(tt,code);
1610 if (!AccessOK (tt, cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1611 ABORT_WITH(tt,PRPERM);
1613 code = GetList (tt, &tentry, alist, 0);
1614 if (code != PRSUCCESS) ABORT_WITH(tt,code);
1616 code = ubik_EndTrans(tt);
1620 #if defined(SUPERGROUPS)
1622 afs_int32 SPR_ListSuperGroups (call, aid, alist, over)
1623 struct rx_call *call;
1630 code = listSuperGroups (call, aid, alist, over);
1631 osi_auditU (call, "PTS_LstSGrps", code, AUD_LONG, aid, AUD_END);
1635 afs_int32 listSuperGroups (call, aid, alist, over)
1636 struct rx_call *call;
1641 register afs_int32 code;
1642 struct ubik_trans *tt;
1645 struct prentry tentry;
1647 alist->prlist_len = 0;
1648 alist->prlist_val = (afs_int32 *) 0;
1651 if (code != PRSUCCESS) goto done;
1652 code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt);
1653 if (code) goto done;
1654 code = ubik_SetLock(tt,1,1,LOCKREAD);
1655 if (code) ABORT_WITH(tt,code);
1656 code = WhoIsThis(call,tt,&cid);
1657 if (code) ABORT_WITH(tt,PRPERM);
1659 temp = FindByID(tt,aid);
1660 if (!temp) ABORT_WITH(tt,PRNOENT);
1661 code = pr_ReadEntry (tt, 0, temp, &tentry);
1662 if (code) ABORT_WITH(tt,code);
1663 if (!AccessOK (tt, cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1664 ABORT_WITH(tt,PRPERM);
1666 code = GetSGList (tt, &tentry, alist);
1668 if (code == PRTOOMANY) *over = 1;
1669 else if (code != PRSUCCESS) ABORT_WITH(tt,code);
1671 code = ubik_EndTrans(tt);
1677 #endif /* SUPERGROUPS */
1681 * List the entries owned by this id. If the id is zero,
1682 * return the orphans list. This will return up to PR_MAXGROUPS
1683 * at a time with the lastP available to get the rest. The
1684 * maximum value is enforced in GetOwnedChain().
1686 afs_int32 SPR_ListOwned (call, aid, alist, lastP)
1687 struct rx_call *call;
1694 code = listOwned (call, aid, alist, lastP);
1695 osi_auditU (call, PTS_LstOwnEvent, code, AUD_LONG, aid, AUD_END);
1699 afs_int32 listOwned (call, aid, alist, lastP)
1700 struct rx_call *call;
1705 register afs_int32 code;
1706 struct ubik_trans *tt;
1708 struct prentry tentry;
1712 alist->prlist_len = 0;
1713 alist->prlist_val = NULL;
1715 if (!lastP) return PRBADARG;
1720 if (code != PRSUCCESS) return code;
1721 code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt);
1722 if (code) return code;
1723 code = ubik_SetLock(tt,1,1,LOCKREAD);
1724 if (code) ABORT_WITH(tt,code);
1725 code = read_DbHeader(tt);
1726 if (code) ABORT_WITH(tt,code);
1728 code = WhoIsThis(call,tt,&cid);
1729 if (code) ABORT_WITH(tt,PRPERM);
1732 code = pr_ReadEntry (tt, 0, start, &tentry);
1733 if (!code && (tentry.owner == aid))
1734 head = start; /* pick up where we left off */
1739 afs_int32 loc = FindByID (tt, aid);
1740 if (loc == 0) ABORT_WITH(tt,PRNOENT);
1741 code = pr_ReadEntry (tt, 0, loc, &tentry);
1742 if (code) ABORT_WITH(tt,code);
1744 if (!AccessOK (tt, cid, &tentry, -1, PRP_OWNED_ANY))
1745 ABORT_WITH(tt,PRPERM);
1746 head = tentry.owned;
1748 if (!AccessOK (tt, cid, 0, 0, 0)) ABORT_WITH(tt,PRPERM);
1749 head = ntohl(cheader.orphan);
1753 code = GetOwnedChain (tt, &head, alist);
1755 if (code == PRTOOMANY) *lastP = head;
1756 else ABORT_WITH(tt,code);
1759 code = ubik_EndTrans(tt);
1763 afs_int32 SPR_IsAMemberOf (call,uid,gid,flag)
1764 struct rx_call *call;
1771 code = isAMemberOf (call,uid,gid,flag);
1772 osi_auditU (call, PTS_IsMemOfEvent, code, AUD_LONG, uid, AUD_LONG, gid, AUD_END);
1776 afs_int32 isAMemberOf (call,uid,gid,flag)
1777 struct rx_call *call;
1782 register afs_int32 code;
1783 struct ubik_trans *tt;
1786 if (code != PRSUCCESS) return code;
1787 code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt);
1788 if (code) return code;
1789 code = ubik_SetLock(tt,1,1,LOCKREAD);
1790 if (code) ABORT_WITH(tt,code);
1791 code = read_DbHeader(tt);
1792 if (code) ABORT_WITH(tt,code);
1795 afs_int32 uloc = FindByID (tt, uid);
1796 afs_int32 gloc = FindByID (tt, gid);
1797 struct prentry uentry, gentry;
1799 if (!uloc || !gloc) ABORT_WITH(tt,PRNOENT);
1800 code = WhoIsThis(call, tt, &cid);
1801 if (code) ABORT_WITH(tt,PRPERM);
1802 code = pr_ReadEntry (tt, 0, uloc, &uentry);
1803 if (code) ABORT_WITH(tt,code);
1804 code = pr_ReadEntry (tt, 0, gloc, &gentry);
1805 if (code) ABORT_WITH(tt,code);
1806 #if !defined(SUPERGROUPS)
1807 if ((uentry.flags & PRGRP) || !(gentry.flags & PRGRP)) ABORT_WITH(tt,PRBADARG);
1809 if (!(gentry.flags & PRGRP)) ABORT_WITH(tt,PRBADARG);
1811 if (!AccessOK (tt, cid, &uentry, 0, PRP_MEMBER_ANY) &&
1812 !AccessOK (tt, cid, &gentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1813 ABORT_WITH(tt,PRPERM);
1816 *flag = IsAMemberOf(tt,uid,gid);
1817 code = ubik_EndTrans(tt);
1827 if (isupper(tc)) *s = tolower(tc);
1833 afs_int32 addWildCards(tt,alist,host)
1834 struct ubik_trans *tt;
1839 struct prentry tentry;
1841 unsigned wild = htonl(0xffffff00);
1842 struct in_addr iaddr;
1844 int size = 0, i, code;
1847 while ((host = (host & wild))) {
1848 wild = htonl ( ntohl(wild) << 8) ;
1849 iaddr.s_addr = host;
1850 code = NameToID(tt, inet_ntoa(iaddr),&hostid);
1851 if (code == PRSUCCESS && hostid != 0) {
1852 temp = FindByID(tt,hostid);
1854 code = pr_ReadEntry (tt, 0, temp, &tentry);
1855 if (code != PRSUCCESS)
1861 wlist.prlist_len = 0;
1862 wlist.prlist_val = NULL;
1864 code = GetList (tt, &tentry, &wlist, 0);
1865 if (code) return code;
1866 added += wlist.prlist_len;
1867 for (i=0; i< wlist.prlist_len; i++) {
1868 if (!inCPS(*alist,wlist.prlist_val[i]))
1869 if ((code = AddToPRList (alist, &size, wlist.prlist_val[i] ))) {
1870 free(wlist.prlist_val);
1874 if (wlist.prlist_val) free(wlist.prlist_val);
1877 qsort(alist->prlist_val,alist->prlist_len,sizeof(afs_int32),IDCmp);
1880 #endif /* IP_WILDCARDS */
1883 afs_int32 WhoIsThisWithName(acall, at, aid, aname)
1884 struct rx_call *acall;
1885 struct ubik_trans *at;
1889 /* aid is set to the identity of the caller, if known, else ANONYMOUSID */
1890 /* returns -1 and sets aid to ANONYMOUSID on any failure */
1891 register struct rx_connection *tconn;
1892 register afs_int32 code;
1893 char tcell[MAXKTCREALMLEN];
1894 char name[MAXKTCNAMELEN];
1895 char inst[MAXKTCNAMELEN];
1900 tconn = rx_ConnectionOf(acall);
1901 code = rx_SecurityClassOf(tconn);
1902 if (code == 0) return 0;
1903 else if (code == 1) { /* vab class */
1904 goto done; /* no longer supported */
1906 else if (code == 2) { /* kad class */
1909 extern char *pr_realmName;
1911 if ((code = rxkad_GetServerInfo
1912 (acall->conn, NULL, 0/*was &exp*/,
1913 name, inst, tcell, NULL)))
1915 strncpy (vname, name, sizeof(vname));
1916 if ((ilen = strlen(inst))) {
1917 if (strlen(vname) + 1 + ilen >= sizeof(vname)) goto done;
1918 strcat (vname, ".");
1919 strcat (vname, inst);
1921 if ( (clen = strlen(tcell))) {
1923 #if defined(AFS_ATHENA_STDENV) || defined(AFS_KERBREALM_ENV)
1924 static char local_realm[AFS_REALM_SZ] = "";
1925 if (!local_realm[0]) {
1926 if (afs_krb_get_lrealm(local_realm, 0) != 0/*KSUCCESS*/)
1927 strncpy(local_realm, pr_realmName, AFS_REALM_SZ);
1931 #if defined(AFS_ATHENA_STDENV) || defined(AFS_KERBREALM_ENV)
1932 strcasecmp (local_realm, tcell) &&
1934 strcasecmp (pr_realmName, tcell))
1936 if (strlen(vname) + 1 + clen >= sizeof(vname)) goto done;
1938 strcat(vname,tcell);
1939 lcstring(vname, vname, sizeof(vname));
1940 code = NameToID(at,vname,aid);
1941 strcpy(aname,vname);
1946 if (strcmp (AUTH_SUPERUSER, vname) == 0)
1947 *aid = SYSADMINID; /* special case for the fileserver */
1949 lcstring(vname, vname, sizeof(vname));
1950 code = NameToID(at,vname,aid);
1954 if (code && !pr_noAuth) return -1;