add-ptprocs-prototype-use-20050426
[openafs.git] / src / ptserver / ptprocs.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 /*
11  *                      (3) function addToGroup
12  *
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.
17  *                      
18  *                      (4) function Delete
19  *
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.
26  *
27  *                      (5) function RemoveFromGroup 
28  *               
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.
34  *
35  *                      (6) Add new functions PR_ListSuperGroups and 
36  *                          listSuperGroups.
37  *                      
38  *                      (7) function isAMemberOf
39  *                      
40  *                          1. Allow groups to be members of groups.
41  *
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).
48  */
49
50 #include <afsconfig.h>
51 #include <afs/param.h>
52
53 RCSID
54     ("$Header$");
55
56 #include <afs/stds.h>
57 #include <ctype.h>
58 #include <stdio.h>
59 #include <lock.h>
60 #include <afs/afsutil.h>
61 #include <ubik.h>
62 #include <rx/xdr.h>
63 #include <rx/rx.h>
64 #include <rx/rxkad.h>
65 #include <afs/auth.h>
66 #ifdef AFS_NT40_ENV
67 #include <winsock2.h>
68 #else
69 #include <netinet/in.h>
70 #include <arpa/inet.h>
71 #endif
72 #ifdef HAVE_STRING_H
73 #include <string.h>
74 #else
75 #ifdef HAVE_STRINGS_H
76 #include <strings.h>
77 #endif
78 #endif
79 #include "ptserver.h"
80 #include "pterror.h"
81 #include "ptprototypes.h"
82 #include "afs/audit.h"
83
84 #ifdef AFS_ATHENA_STDENV
85 #include <krb.h>
86 #endif
87
88
89 #define IP_WILDCARDS    1       /* XXX Should be defined outside of here XXX */
90
91 extern int restricted;
92 extern struct ubik_dbase *dbase;
93 extern afs_int32 Initdb();
94 extern int pr_noAuth;
95 extern afs_int32 initd;
96 afs_int32 iNewEntry(), newEntry(), whereIsIt(), dumpEntry(), addToGroup(),
97 nameToID(), Delete(), removeFromGroup();
98 afs_int32 getCPS(), getCPS2(), getHostCPS(), listMax(), setMax(), listEntry();
99 afs_int32 listEntries(), changeEntry(), setFieldsEntry(), put_prentries();
100 afs_int32 listElements(), listOwned(), isAMemberOf(), idToName();
101
102 #if defined(SUPERGROUPS)
103 afs_int32 listSuperGroups();
104 #endif
105
106 static stolower();
107 extern int IDCmp();
108
109 extern int prp_group_default;
110 extern int prp_user_default;
111
112 /* When abort, reset initd so that the header is read in on next call.
113  * Abort the transaction and return the code.
114  */
115 #define ABORT_WITH(tt,code) return(initd=0,ubik_AbortTrans(tt),code)
116
117 static int
118 CreateOK(ut, cid, oid, flag, admin)
119      struct ubik_trans *ut;
120      afs_int32 cid;             /* id of caller */
121      afs_int32 oid;             /* id of owner */
122      afs_int32 flag;            /* indicates type of entry */
123      int admin;                 /* sysadmin membership */
124 {
125     if (restricted && !admin) 
126         return 0;
127
128     if (flag & PRFOREIGN) {
129         /* Foreign users are recognized by the '@' sign and 
130          * not by the PRFOREIGN flag.
131          */
132         return 0;
133     } else if (flag & PRGRP) {
134         /* Allow anonymous group creation only if owner specified
135          * and running noAuth.
136          */
137         if (cid == ANONYMOUSID) {
138             if ((oid == 0) || !pr_noAuth)
139                 return 0;
140         }
141     } else {                    /* creating a user */
142         if (!admin && !pr_noAuth)
143             return 0;
144     }
145     return 1;                   /* OK! */
146 }
147
148 afs_int32
149 WhoIsThis(acall, at, aid)
150      struct rx_call *acall;
151      struct ubik_trans *at;
152      afs_int32 *aid;
153 {
154     int foreign = 0;
155     /* aid is set to the identity of the caller, if known, else ANONYMOUSID */
156     /* returns -1 and sets aid to ANONYMOUSID on any failure */
157     register struct rx_connection *tconn;
158     register afs_int32 code;
159     char tcell[MAXKTCREALMLEN];
160     char name[MAXKTCNAMELEN];
161     char inst[MAXKTCNAMELEN];
162     int ilen;
163     char vname[256];
164
165     *aid = ANONYMOUSID;
166     tconn = rx_ConnectionOf(acall);
167     code = rx_SecurityClassOf(tconn);
168     if (code == 0)
169         return 0;
170     else if (code == 1) {       /* vab class */
171         goto done;              /* no longer supported */
172     } else if (code == 2) {     /* kad class */
173         if ((code = rxkad_GetServerInfo(acall->conn, NULL, 0 /*was &exp */ ,
174                                         name, inst, tcell, NULL)))
175             goto done;
176 #if 0
177         /* This test is unnecessary, since rxkad_GetServerInfo already check.
178          * In addition, this is wrong since exp must be unsigned. */
179         if (exp < FT_ApproxTime())
180             goto done;
181 #endif
182         if (strlen(tcell)) {
183             extern char *pr_realmName;
184 #if     defined(AFS_ATHENA_STDENV) || defined(AFS_KERBREALM_ENV)
185             static char local_realm[AFS_REALM_SZ] = "";
186             if (!local_realm[0]) {
187                 if (afs_krb_get_lrealm(local_realm, 0) != 0 /*KSUCCESS*/)
188                     strncpy(local_realm, pr_realmName, AFS_REALM_SZ);
189             }
190 #endif
191             if (
192 #if     defined(AFS_ATHENA_STDENV) || defined(AFS_KERBREALM_ENV)
193                    strcasecmp(local_realm, tcell) &&
194 #endif
195                    strcasecmp(pr_realmName, tcell))
196                 foreign = 1;
197         }
198         strncpy(vname, name, sizeof(vname));
199         if (ilen = strlen(inst)) {
200             if (strlen(vname) + 1 + ilen >= sizeof(vname))
201                 goto done;
202             strcat(vname, ".");
203             strcat(vname, inst);
204         }
205         if (foreign) {
206             if (strlen(vname) + strlen(tcell) + 1 >= sizeof(vname))
207                 goto done;
208             strcat(vname, "@");
209             strcat(vname, tcell);
210         }
211         if (strcmp(AUTH_SUPERUSER, vname) == 0)
212             *aid = SYSADMINID;  /* special case for the fileserver */
213         else {
214             lcstring(vname, vname, sizeof(vname));
215             code = NameToID(at, vname, aid);
216         }
217     }
218   done:
219     if (code && !pr_noAuth)
220         return -1;
221     return 0;
222 }
223
224 afs_int32
225 SPR_INewEntry(call, aname, aid, oid)
226      struct rx_call *call;
227      char aname[PR_MAXNAMELEN];
228      afs_int32 aid;
229      afs_int32 oid;
230 {
231     afs_int32 code;
232
233     code = iNewEntry(call, aname, aid, oid);
234     osi_auditU(call, PTS_INewEntEvent, code, AUD_LONG, aid, AUD_STR, aname,
235                AUD_LONG, oid, AUD_END);
236     return code;
237 }
238
239 afs_int32
240 iNewEntry(call, aname, aid, oid)
241      struct rx_call *call;
242      char aname[PR_MAXNAMELEN];
243      afs_int32 aid;
244      afs_int32 oid;
245 {
246     /* used primarily for conversion - not intended to be used as usual means
247      * of entering people into the database. */
248     struct ubik_trans *tt;
249     register afs_int32 code;
250     afs_int32 gflag = 0;
251     afs_int32 cid;
252     int admin;
253
254     stolower(aname);
255     code = Initdb();
256     if (code != PRSUCCESS)
257         return code;
258     code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
259     if (code)
260         return code;
261     code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
262     if (code)
263         ABORT_WITH(tt, code);
264     code = read_DbHeader(tt);
265     if (code)
266         ABORT_WITH(tt, code);
267
268     code = WhoIsThis(call, tt, &cid);
269     if (code)
270         ABORT_WITH(tt, PRPERM);
271     admin = IsAMemberOf(tt, cid, SYSADMINID);
272
273     /* first verify the id is good */
274     if (aid == 0)
275         ABORT_WITH(tt, PRPERM);
276     if (aid < 0) {
277         gflag |= PRGRP;
278         /* only sysadmin can reuse a group id */
279         if (!admin && !pr_noAuth && (aid != ntohl(cheader.maxGroup) - 1))
280             ABORT_WITH(tt, PRPERM);
281     }
282     if (FindByID(tt, aid))
283         ABORT_WITH(tt, PRIDEXIST);
284
285     /* check a few other things */
286     if (!CreateOK(tt, cid, oid, gflag, admin))
287         ABORT_WITH(tt, PRPERM);
288
289     code = CreateEntry(tt, aname, &aid, 1, gflag, oid, cid);
290     if (code != PRSUCCESS)
291         ABORT_WITH(tt, code);
292
293     /* finally, commit transaction */
294     code = ubik_EndTrans(tt);
295     if (code)
296         return code;
297     return PRSUCCESS;
298 }
299
300
301 afs_int32
302 SPR_NewEntry(call, aname, flag, oid, aid)
303      struct rx_call *call;
304      char aname[PR_MAXNAMELEN];
305      afs_int32 flag;
306      afs_int32 oid;
307      afs_int32 *aid;
308 {
309     afs_int32 code;
310
311     code = newEntry(call, aname, flag, oid, aid);
312     osi_auditU(call, PTS_NewEntEvent, code, AUD_LONG, *aid, AUD_STR, aname,
313                AUD_LONG, oid, AUD_END);
314     return code;
315 }
316
317 afs_int32
318 newEntry(call, aname, flag, oid, aid)
319      struct rx_call *call;
320      char aname[PR_MAXNAMELEN];
321      afs_int32 flag;
322      afs_int32 oid;
323      afs_int32 *aid;
324 {
325     register afs_int32 code;
326     struct ubik_trans *tt;
327     afs_int32 cid;
328     int admin;
329     extern afs_int32 WhoIsThisWithName();
330     char cname[PR_MAXNAMELEN];
331     stolower(aname);
332     code = Initdb();
333     if (code)
334         return code;
335     code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
336     if (code)
337         return code;
338     code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
339     if (code)
340         ABORT_WITH(tt, code);
341     code = read_DbHeader(tt);
342     if (code)
343         ABORT_WITH(tt, code);
344
345     /* this is for cross-cell self registration. It is not added in the
346      * SPR_INewEntry because we want self-registration to only do 
347      * automatic id assignment.
348      */
349     code = WhoIsThisWithName(call, tt, &cid, cname);
350     if (code != 2) {            /* 2 specifies that this is a foreign cell request */
351         if (code)
352             ABORT_WITH(tt, PRPERM);
353         admin = IsAMemberOf(tt, cid, SYSADMINID);
354     } else {
355         admin = ((!restricted && !strcmp(aname, cname))) || IsAMemberOf(tt, cid, SYSADMINID);
356         oid = cid = SYSADMINID;
357     }
358     if (!CreateOK(tt, cid, oid, flag, admin))
359         ABORT_WITH(tt, PRPERM);
360
361     code = CreateEntry(tt, aname, aid, 0, flag, oid, cid);
362     if (code != PRSUCCESS)
363         ABORT_WITH(tt, code);
364
365     code = ubik_EndTrans(tt);
366     if (code)
367         return code;
368     return PRSUCCESS;
369 }
370
371
372
373 afs_int32
374 SPR_WhereIsIt(call, aid, apos)
375      struct rx_call *call;
376      afs_int32 aid;
377      afs_int32 *apos;
378 {
379     afs_int32 code;
380
381     code = whereIsIt(call, aid, apos);
382     osi_auditU(call, PTS_WheIsItEvent, code, AUD_LONG, aid, AUD_LONG, *apos,
383                AUD_END);
384     return code;
385 }
386
387 afs_int32
388 whereIsIt(call, aid, apos)
389      struct rx_call *call;
390      afs_int32 aid;
391      afs_int32 *apos;
392 {
393     register afs_int32 code;
394     struct ubik_trans *tt;
395     afs_int32 temp;
396
397     code = Initdb();
398     if (code != PRSUCCESS)
399         return code;
400     code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
401     if (code)
402         return code;
403     code = ubik_SetLock(tt, 1, 1, LOCKREAD);
404     if (code)
405         ABORT_WITH(tt, code);
406     code = read_DbHeader(tt);
407     if (code)
408         ABORT_WITH(tt, code);
409
410     temp = FindByID(tt, aid);
411     if (!temp)
412         ABORT_WITH(tt, PRNOENT);
413     *apos = temp;
414     code = ubik_EndTrans(tt);
415     if (code)
416         return code;
417     return PRSUCCESS;
418 }
419
420
421 afs_int32
422 SPR_DumpEntry(call, apos, aentry)
423      struct rx_call *call;
424      afs_int32 apos;
425      struct prdebugentry *aentry;
426 {
427     afs_int32 code;
428
429     code = dumpEntry(call, apos, aentry);
430     osi_auditU(call, PTS_DmpEntEvent, code, AUD_LONG, apos, AUD_END);
431     return code;
432 }
433
434 afs_int32
435 dumpEntry(call, apos, aentry)
436      struct rx_call *call;
437      afs_int32 apos;
438      struct prdebugentry *aentry;
439 {
440     register afs_int32 code;
441     afs_int32 cid;
442     struct ubik_trans *tt;
443
444     code = Initdb();
445     if (code != PRSUCCESS)
446         return code;
447     code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
448     if (code)
449         return code;
450     code = ubik_SetLock(tt, 1, 1, LOCKREAD);
451     if (code)
452         ABORT_WITH(tt, code);
453     code = read_DbHeader(tt);
454     if (code)
455         ABORT_WITH(tt, code);
456
457     code = WhoIsThis(call, tt, &cid);
458     if (code)
459         ABORT_WITH(tt, PRPERM);
460     code = pr_ReadEntry(tt, 0, apos, aentry);
461     if (code)
462         ABORT_WITH(tt, code);
463
464     if (!AccessOK(tt, cid, 0, PRP_STATUS_MEM, 0))
465         ABORT_WITH(tt, PRPERM);
466
467     /* Since prdebugentry is in the form of a prentry not a coentry, we will
468      * return the coentry slots in network order where the string is. */
469 #if 0
470     if (aentry->flags & PRCONT) {       /* wrong type, get coentry instead */
471         code = pr_ReadCoEntry(tt, 0, apos, aentry);
472         if (code)
473             ABORT_WITH(tt, code);
474     }
475 #endif
476     code = ubik_EndTrans(tt);
477     if (code)
478         return code;
479     return PRSUCCESS;
480 }
481
482 afs_int32
483 SPR_AddToGroup(call, aid, gid)
484      struct rx_call *call;
485      afs_int32 aid;
486      afs_int32 gid;
487 {
488     afs_int32 code;
489
490     code = addToGroup(call, aid, gid);
491     osi_auditU(call, PTS_AdToGrpEvent, code, AUD_LONG, gid, AUD_LONG, aid,
492                AUD_END);
493     return code;
494 }
495
496 afs_int32
497 addToGroup(call, aid, gid)
498      struct rx_call *call;
499      afs_int32 aid;
500      afs_int32 gid;
501 {
502     register afs_int32 code;
503     struct ubik_trans *tt;
504     afs_int32 tempu;
505     afs_int32 tempg;
506     struct prentry tentry;
507     struct prentry uentry;
508     afs_int32 cid;
509
510     code = Initdb();
511     if (code != PRSUCCESS)
512         return code;
513     if (gid == ANYUSERID || gid == AUTHUSERID)
514         return PRPERM;
515     if (aid == ANONYMOUSID)
516         return PRPERM;
517     code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
518     if (code)
519         return code;
520     code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
521     if (code)
522         ABORT_WITH(tt, code);
523     code = read_DbHeader(tt);
524     if (code)
525         ABORT_WITH(tt, code);
526
527     code = WhoIsThis(call, tt, &cid);
528     if (code)
529         ABORT_WITH(tt, PRPERM);
530     tempu = FindByID(tt, aid);
531     if (!tempu)
532         ABORT_WITH(tt, PRNOENT);
533     memset(&uentry, 0, sizeof(uentry));
534     code = pr_ReadEntry(tt, 0, tempu, &uentry);
535     if (code != 0)
536         ABORT_WITH(tt, code);
537
538 #if !defined(SUPERGROUPS)
539     /* we don't allow groups as members of groups at present */
540     if (uentry.flags & PRGRP)
541         ABORT_WITH(tt, PRNOTUSER);
542 #endif
543
544     tempg = FindByID(tt, gid);
545     if (!tempg)
546         ABORT_WITH(tt, PRNOENT);
547     code = pr_ReadEntry(tt, 0, tempg, &tentry);
548     if (code != 0)
549         ABORT_WITH(tt, code);
550     /* make sure that this is a group */
551     if (!(tentry.flags & PRGRP))
552         ABORT_WITH(tt, PRNOTGROUP);
553     if (!AccessOK(tt, cid, &tentry, PRP_ADD_MEM, PRP_ADD_ANY))
554         ABORT_WITH(tt, PRPERM);
555
556     code = AddToEntry(tt, &tentry, tempg, aid);
557     if (code != PRSUCCESS)
558         ABORT_WITH(tt, code);
559
560 #if defined(SUPERGROUPS)
561     if (uentry.flags & PRGRP)
562         code = AddToSGEntry(tt, &uentry, tempu, gid);   /* mod group to be in sg */
563     else
564 #endif
565         /* now, modify the user's entry as well */
566         code = AddToEntry(tt, &uentry, tempu, gid);
567     if (code != PRSUCCESS)
568         ABORT_WITH(tt, code);
569     code = ubik_EndTrans(tt);
570     if (code)
571         return code;
572     return PRSUCCESS;
573 }
574
575 afs_int32
576 SPR_NameToID(call, aname, aid)
577      struct rx_call *call;
578      namelist *aname;
579      idlist *aid;
580 {
581     afs_int32 code;
582
583     code = nameToID(call, aname, aid);
584     osi_auditU(call, PTS_NmToIdEvent, code, AUD_END);
585     return code;
586 }
587
588 afs_int32
589 nameToID(call, aname, aid)
590      struct rx_call *call;
591      namelist *aname;
592      idlist *aid;
593 {
594     register afs_int32 code;
595     struct ubik_trans *tt;
596     afs_int32 i;
597     int size;
598     int count = 0;
599
600     /* Initialize return struct */
601     aid->idlist_len = 0;
602     aid->idlist_val = NULL;
603
604     size = aname->namelist_len;
605     if (size == 0)
606         return 0;
607     if (size < 0)
608         return PRTOOMANY;
609
610     aid->idlist_val = (afs_int32 *) malloc(size * sizeof(afs_int32));
611     if (!aid->idlist_val)
612         return PRNOMEM;
613
614     code = Initdb();
615     if (code != PRSUCCESS)
616         return code;
617     code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
618     if (code)
619         return code;
620     code = ubik_SetLock(tt, 1, 1, LOCKREAD);
621     if (code)
622         ABORT_WITH(tt, code);
623     code = read_DbHeader(tt);
624     if (code)
625         ABORT_WITH(tt, code);
626
627     for (i = 0; i < aname->namelist_len; i++) {
628         code = NameToID(tt, aname->namelist_val[i], &aid->idlist_val[i]);
629         if (code != PRSUCCESS)
630             aid->idlist_val[i] = ANONYMOUSID;
631         if (count++ > 50)
632             IOMGR_Poll(), count = 0;
633     }
634     aid->idlist_len = aname->namelist_len;
635
636     code = ubik_EndTrans(tt);
637     if (code)
638         return code;
639     return PRSUCCESS;
640 }
641
642 /*
643  * SPR_IDToName
644  * Given an array of ids, find the name for each of them.
645  * The array of ids and names is unlimited.
646  */
647 afs_int32
648 SPR_IDToName(call, aid, aname)
649      struct rx_call *call;
650      idlist *aid;
651      namelist *aname;
652 {
653     afs_int32 code;
654
655     code = idToName(call, aid, aname);
656     osi_auditU(call, PTS_IdToNmEvent, code, AUD_LONG, aid, AUD_END);
657     return code;
658 }
659
660 afs_int32
661 idToName(call, aid, aname)
662      struct rx_call *call;
663      idlist *aid;
664      namelist *aname;
665 {
666     register afs_int32 code;
667     struct ubik_trans *tt;
668     afs_int32 i;
669     int size;
670     int count = 0;
671
672     /* leave this first for rpc stub */
673     size = aid->idlist_len;
674     if (size == 0)
675         return 0;
676     if (size < 0)
677         return PRTOOMANY;
678     aname->namelist_val = (prname *) malloc(size * PR_MAXNAMELEN);
679     aname->namelist_len = 0;
680     if (aname->namelist_val == 0)
681         return PRNOMEM;
682     if (aid->idlist_len == 0)
683         return 0;
684     if (size == 0)
685         return PRTOOMANY;       /* rxgen will probably handle this */
686
687     code = Initdb();
688     if (code != PRSUCCESS)
689         return code;
690     code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
691     if (code)
692         return code;
693     code = ubik_SetLock(tt, 1, 1, LOCKREAD);
694     if (code)
695         ABORT_WITH(tt, code);
696     code = read_DbHeader(tt);
697     if (code)
698         ABORT_WITH(tt, code);
699
700     for (i = 0; i < aid->idlist_len; i++) {
701         code = IDToName(tt, aid->idlist_val[i], aname->namelist_val[i]);
702         if (code != PRSUCCESS)
703             sprintf(aname->namelist_val[i], "%d", aid->idlist_val[i]);
704         if (count++ > 50)
705             IOMGR_Poll(), count = 0;
706     }
707     aname->namelist_len = aid->idlist_len;
708
709     code = ubik_EndTrans(tt);
710     if (code)
711         return code;
712     return PRSUCCESS;
713 }
714
715 afs_int32
716 SPR_Delete(call, aid)
717      struct rx_call *call;
718      afs_int32 aid;
719 {
720     afs_int32 code;
721
722     code = Delete(call, aid);
723     osi_auditU(call, PTS_DelEvent, code, AUD_LONG, aid, AUD_END);
724     return code;
725 }
726
727 afs_int32
728 Delete(call, aid)
729      struct rx_call *call;
730      afs_int32 aid;
731 {
732     register afs_int32 code;
733     struct ubik_trans *tt;
734     afs_int32 cid;
735     struct prentry tentry;
736     afs_int32 loc, nptr;
737     int count;
738
739     code = Initdb();
740     if (code)
741         return code;
742     if (code != PRSUCCESS)
743         return code;
744     if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID
745         || aid == ANONYMOUSID)
746         return PRPERM;
747     code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
748     if (code)
749         return code;
750     code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
751     if (code)
752         ABORT_WITH(tt, code);
753     code = read_DbHeader(tt);
754     if (code)
755         ABORT_WITH(tt, code);
756
757     code = WhoIsThis(call, tt, &cid);
758     if (code)
759         ABORT_WITH(tt, PRPERM);
760
761     /* Read in entry to be deleted */
762     loc = FindByID(tt, aid);
763     if (loc == 0)
764         ABORT_WITH(tt, PRNOENT);
765     code = pr_ReadEntry(tt, 0, loc, &tentry);
766     if (code)
767         ABORT_WITH(tt, PRDBFAIL);
768
769     /* Do some access checking */
770     if (tentry.owner != cid && !IsAMemberOf(tt, cid, SYSADMINID)
771         && !IsAMemberOf(tt, cid, tentry.owner) && !pr_noAuth)
772         ABORT_WITH(tt, PRPERM);
773
774     /* Delete each continuation block as a separate transaction so that no one
775      * transaction become to large to complete. */
776     nptr = tentry.next;
777     while (nptr != (afs_int32) NULL) {
778         struct contentry centry;
779         int i;
780
781         code = pr_ReadCoEntry(tt, 0, nptr, &centry);
782         if (code != 0)
783             ABORT_WITH(tt, PRDBFAIL);
784         for (i = 0; i < COSIZE; i++) {
785             if (centry.entries[i] == PRBADID)
786                 continue;
787             if (centry.entries[i] == 0)
788                 break;
789 #if defined(SUPERGROUPS)
790             if (aid < 0 && centry.entries[i] < 0)       /* Supergroup */
791                 code = RemoveFromSGEntry(tt, aid, centry.entries[i]);
792             else
793 #endif
794                 code = RemoveFromEntry(tt, aid, centry.entries[i]);
795             if (code)
796                 ABORT_WITH(tt, code);
797             tentry.count--;     /* maintain count */
798             if ((i & 3) == 0)
799                 IOMGR_Poll();
800         }
801         tentry.next = centry.next;      /* thread out this block */
802         code = FreeBlock(tt, nptr);     /* free continuation block */
803         if (code)
804             ABORT_WITH(tt, code);
805         code = pr_WriteEntry(tt, 0, loc, &tentry);      /* update main entry */
806         if (code)
807             ABORT_WITH(tt, code);
808
809         /* end this trans and start a new one */
810         code = ubik_EndTrans(tt);
811         if (code)
812             return code;
813         IOMGR_Poll();           /* just to keep the connection alive */
814         code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
815         if (code)
816             return code;
817         code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
818         if (code)
819             ABORT_WITH(tt, code);
820
821         /* re-read entry to get consistent uptodate info */
822         loc = FindByID(tt, aid);
823         if (loc == 0)
824             ABORT_WITH(tt, PRNOENT);
825         code = pr_ReadEntry(tt, 0, loc, &tentry);
826         if (code)
827             ABORT_WITH(tt, PRDBFAIL);
828
829         nptr = tentry.next;
830     }
831
832 #if defined(SUPERGROUPS)
833     /* Delete each continuation block as a separate transaction
834      * so that no one transaction become too large to complete. */
835     {
836         struct prentryg *tentryg = (struct prentryg *)&tentry;
837         nptr = tentryg->nextsg;
838         while (nptr != NULL) {
839             struct contentry centry;
840             int i;
841
842             code = pr_ReadCoEntry(tt, 0, nptr, &centry);
843             if (code != 0)
844                 ABORT_WITH(tt, PRDBFAIL);
845             for (i = 0; i < COSIZE; i++) {
846                 if (centry.entries[i] == PRBADID)
847                     continue;
848                 if (centry.entries[i] == 0)
849                     break;
850                 code = RemoveFromEntry(tt, aid, centry.entries[i]);
851                 if (code)
852                     ABORT_WITH(tt, code);
853                 tentryg->countsg--;     /* maintain count */
854                 if ((i & 3) == 0)
855                     IOMGR_Poll();
856             }
857             tentryg->nextsg = centry.next;      /* thread out this block */
858             code = FreeBlock(tt, nptr); /* free continuation block */
859             if (code)
860                 ABORT_WITH(tt, code);
861             code = pr_WriteEntry(tt, 0, loc, &tentry);  /* update main entry */
862             if (code)
863                 ABORT_WITH(tt, code);
864
865             /* end this trans and start a new one */
866             code = ubik_EndTrans(tt);
867             if (code)
868                 return code;
869             IOMGR_Poll();       /* just to keep the connection alive */
870
871             code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
872             if (code)
873                 return code;
874             code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
875             if (code)
876                 ABORT_WITH(tt, code);
877
878             /* re-read entry to get consistent uptodate info */
879             loc = FindByID(tt, aid);
880             if (loc == 0)
881                 ABORT_WITH(tt, PRNOENT);
882             code = pr_ReadEntry(tt, 0, loc, &tentry);
883             if (code)
884                 ABORT_WITH(tt, PRDBFAIL);
885
886             nptr = tentryg->nextsg;
887         }
888     }
889
890 #endif /* SUPERGROUPS */
891
892     /* Then move the owned chain, except possibly ourself to the orphan list.
893      * Because this list can be very long and so exceed the size of a ubik
894      * transaction, we start a new transaction every 50 entries. */
895     count = 0;
896     nptr = tentry.owned;
897     while (nptr != (afs_int32) NULL) {
898         struct prentry nentry;
899
900         code = pr_ReadEntry(tt, 0, nptr, &nentry);
901         if (code)
902             ABORT_WITH(tt, PRDBFAIL);
903         nptr = tentry.owned = nentry.nextOwned; /* thread out */
904
905         if (nentry.id != tentry.id) {   /* don't add us to orphan chain! */
906             code = AddToOrphan(tt, nentry.id);
907             if (code)
908                 ABORT_WITH(tt, code);
909             count++;
910             if ((count & 3) == 0)
911                 IOMGR_Poll();
912         }
913         if (count < 50)
914             continue;
915         code = pr_WriteEntry(tt, 0, loc, &tentry);      /* update main entry */
916         if (code)
917             ABORT_WITH(tt, code);
918
919         /* end this trans and start a new one */
920         code = ubik_EndTrans(tt);
921         if (code)
922             return code;
923         IOMGR_Poll();           /* just to keep the connection alive */
924         code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
925         if (code)
926             return code;
927         code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
928         if (code)
929             ABORT_WITH(tt, code);
930
931         /* re-read entry to get consistent uptodate info */
932         loc = FindByID(tt, aid);
933         if (loc == 0)
934             ABORT_WITH(tt, PRNOENT);
935         code = pr_ReadEntry(tt, 0, loc, &tentry);
936         if (code)
937             ABORT_WITH(tt, PRDBFAIL);
938
939         nptr = tentry.owned;
940     }
941
942     /* now do what's left of the deletion stuff */
943     code = DeleteEntry(tt, &tentry, loc);
944     if (code != PRSUCCESS)
945         ABORT_WITH(tt, code);
946
947     code = ubik_EndTrans(tt);
948     if (code)
949         return code;
950     return PRSUCCESS;
951 }
952
953 afs_int32
954 SPR_UpdateEntry(call, aid, name, uentry)
955      struct rx_call *call;
956      afs_int32 aid;
957      char *name;
958      struct PrUpdateEntry *uentry;
959 {
960     register afs_int32 code;
961     struct ubik_trans *tt;
962     afs_int32 cid;
963     struct prentry tentry;
964     afs_int32 loc;
965     int id = 0;
966
967     code = Initdb();
968     if (code)
969         return code;
970     if (code != PRSUCCESS)
971         return code;
972     if (aid) {
973         id = aid;
974         if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID
975             || aid == ANONYMOUSID)
976             return PRPERM;
977     }
978     code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
979     if (code)
980         return code;
981     code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
982     if (code)
983         ABORT_WITH(tt, code);
984     code = read_DbHeader(tt);
985     if (code)
986         ABORT_WITH(tt, code);
987
988     code = WhoIsThis(call, tt, &cid);
989     if (code)
990         ABORT_WITH(tt, PRPERM);
991     code = IsAMemberOf(tt, cid, SYSADMINID);
992     if (!code && !pr_noAuth)
993         ABORT_WITH(tt, PRPERM);
994
995     /* Read in entry to be deleted */
996     if (id) {
997         loc = FindByID(tt, aid);
998     } else {
999         loc = FindByName(tt, name, &tentry);
1000     }
1001     if (loc == 0)
1002         ABORT_WITH(tt, PRNOENT);
1003     code = pr_ReadEntry(tt, 0, loc, &tentry);
1004     if (code)
1005         ABORT_WITH(tt, PRDBFAIL);
1006
1007     if (uentry->Mask & PRUPDATE_NAMEHASH) {
1008         int tloc;
1009         code = RemoveFromNameHash(tt, tentry.name, &tloc);
1010         if (code != PRSUCCESS)
1011             ABORT_WITH(tt, PRDBFAIL);
1012         code = AddToNameHash(tt, tentry.name, loc);
1013         if (code)
1014             ABORT_WITH(tt, code);
1015     }
1016
1017     if (uentry->Mask & PRUPDATE_IDHASH) {
1018         int tloc;
1019         if (!id)
1020             id = tentry.id;
1021         code = RemoveFromIDHash(tt, id, &tloc);
1022         if (code != PRSUCCESS)
1023             ABORT_WITH(tt, PRDBFAIL);
1024         code = AddToIDHash(tt, id, loc);
1025         if (code)
1026             ABORT_WITH(tt, code);
1027     }
1028
1029     code = ubik_EndTrans(tt);
1030     if (code)
1031         return code;
1032     return PRSUCCESS;
1033 }
1034
1035 afs_int32
1036 SPR_RemoveFromGroup(call, aid, gid)
1037      struct rx_call *call;
1038      afs_int32 aid;
1039      afs_int32 gid;
1040 {
1041     afs_int32 code;
1042
1043     code = removeFromGroup(call, aid, gid);
1044     osi_auditU(call, PTS_RmFmGrpEvent, code, AUD_LONG, gid, AUD_LONG, aid,
1045                AUD_END);
1046     return code;
1047 }
1048
1049 afs_int32
1050 removeFromGroup(call, aid, gid)
1051      struct rx_call *call;
1052      afs_int32 aid;
1053      afs_int32 gid;
1054 {
1055     register afs_int32 code;
1056     struct ubik_trans *tt;
1057     afs_int32 tempu;
1058     afs_int32 tempg;
1059     struct prentry uentry;
1060     struct prentry gentry;
1061     afs_int32 cid;
1062
1063     code = Initdb();
1064     if (code != PRSUCCESS)
1065         return code;
1066     code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1067     if (code)
1068         return code;
1069     code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1070     if (code)
1071         ABORT_WITH(tt, code);
1072     code = read_DbHeader(tt);
1073     if (code)
1074         ABORT_WITH(tt, code);
1075
1076     code = WhoIsThis(call, tt, &cid);
1077     if (code)
1078         ABORT_WITH(tt, PRPERM);
1079     tempu = FindByID(tt, aid);
1080     if (!tempu)
1081         ABORT_WITH(tt, PRNOENT);
1082     tempg = FindByID(tt, gid);
1083     if (!tempg)
1084         ABORT_WITH(tt, PRNOENT);
1085     memset(&uentry, 0, sizeof(uentry));
1086     memset(&gentry, 0, sizeof(gentry));
1087     code = pr_ReadEntry(tt, 0, tempu, &uentry);
1088     if (code != 0)
1089         ABORT_WITH(tt, code);
1090     code = pr_ReadEntry(tt, 0, tempg, &gentry);
1091     if (code != 0)
1092         ABORT_WITH(tt, code);
1093     if (!(gentry.flags & PRGRP))
1094         ABORT_WITH(tt, PRNOTGROUP);
1095 #if !defined(SUPERGROUPS)
1096     if (uentry.flags & PRGRP)
1097         ABORT_WITH(tt, PRNOTUSER);
1098 #endif
1099     if (!AccessOK(tt, cid, &gentry, PRP_REMOVE_MEM, 0))
1100         ABORT_WITH(tt, PRPERM);
1101     code = RemoveFromEntry(tt, aid, gid);
1102     if (code != PRSUCCESS)
1103         ABORT_WITH(tt, code);
1104 #if defined(SUPERGROUPS)
1105     if (!(uentry.flags & PRGRP))
1106 #endif
1107         code = RemoveFromEntry(tt, gid, aid);
1108 #if defined(SUPERGROUPS)
1109     else
1110         code = RemoveFromSGEntry(tt, gid, aid);
1111 #endif
1112     if (code != PRSUCCESS)
1113         ABORT_WITH(tt, code);
1114
1115     code = ubik_EndTrans(tt);
1116     if (code)
1117         return code;
1118     return PRSUCCESS;
1119 }
1120
1121
1122 afs_int32
1123 SPR_GetCPS(call, aid, alist, over)
1124      struct rx_call *call;
1125      afs_int32 aid;
1126      prlist *alist;
1127      afs_int32 *over;
1128 {
1129     afs_int32 code;
1130
1131     code = getCPS(call, aid, alist, over);
1132     osi_auditU(call, PTS_GetCPSEvent, code, AUD_LONG, aid, AUD_END);
1133     return code;
1134 }
1135
1136 afs_int32
1137 getCPS(call, aid, alist, over)
1138      struct rx_call *call;
1139      afs_int32 aid;
1140      prlist *alist;
1141      afs_int32 *over;
1142 {
1143     register afs_int32 code;
1144     struct ubik_trans *tt;
1145     afs_int32 temp;
1146     afs_int32 cid;
1147     struct prentry tentry;
1148
1149     *over = 0;
1150     alist->prlist_len = 0;
1151     alist->prlist_val = NULL;
1152     code = Initdb();
1153     if (code != PRSUCCESS)
1154         return code;
1155     code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1156     if (code)
1157         return code;
1158     code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1159     if (code)
1160         ABORT_WITH(tt, code);
1161     code = read_DbHeader(tt);
1162     if (code)
1163         ABORT_WITH(tt, code);
1164
1165     temp = FindByID(tt, aid);
1166     if (!temp)
1167         ABORT_WITH(tt, PRNOENT);
1168     code = pr_ReadEntry(tt, 0, temp, &tentry);
1169     if (code)
1170         ABORT_WITH(tt, code);
1171
1172     /* afs does authenticate now */
1173     code = WhoIsThis(call, tt, &cid);
1174     if (code || !AccessOK(tt, cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1175         ABORT_WITH(tt, PRPERM);
1176
1177     code = GetList(tt, &tentry, alist, 1);
1178     if (code != PRSUCCESS)
1179         ABORT_WITH(tt, code);
1180
1181     code = ubik_EndTrans(tt);
1182     return code;
1183 }
1184
1185
1186 #ifdef IP_WILDCARDS
1187 int
1188 inCPS(CPS, id)
1189      prlist CPS;
1190      afs_int32 id;
1191 {
1192     int i;
1193
1194     for (i = (CPS.prlist_len - 1); i >= 0; i--) {
1195         if (CPS.prlist_val[i] == id)
1196             return (1);
1197     }
1198     return (0);
1199 }
1200 #endif /* IP_WILDCARDS */
1201
1202
1203 afs_int32
1204 SPR_GetCPS2(call, aid, ahost, alist, over)
1205      struct rx_call *call;
1206      afs_int32 aid;
1207      afs_int32 ahost;
1208      prlist *alist;
1209      afs_int32 *over;
1210 {
1211     afs_int32 code;
1212
1213     code = getCPS2(call, aid, ahost, alist, over);
1214     osi_auditU(call, PTS_GetCPS2Event, code, AUD_LONG, aid, AUD_HOST, ahost,
1215                AUD_END);
1216     return code;
1217 }
1218
1219 afs_int32
1220 getCPS2(call, aid, ahost, alist, over)
1221      struct rx_call *call;
1222      afs_int32 aid;
1223      afs_int32 ahost;
1224      prlist *alist;
1225      afs_int32 *over;
1226 {
1227     register afs_int32 code;
1228     struct ubik_trans *tt;
1229     afs_int32 temp;
1230     afs_int32 cid;
1231     struct prentry tentry;
1232     struct prentry host_tentry;
1233     afs_int32 hostid;
1234     int host_list = 0;
1235     struct in_addr iaddr;
1236 #if IP_WILDCARDS
1237     extern afs_int32 addWildCards();
1238 #endif /* IP_WILDCARDS */
1239
1240     *over = 0;
1241     iaddr.s_addr = ntohl(ahost);
1242     alist->prlist_len = 0;
1243     alist->prlist_val = NULL;
1244     code = Initdb();
1245     if (code != PRSUCCESS)
1246         return code;
1247     code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1248     if (code)
1249         return code;
1250     code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1251     if (code)
1252         ABORT_WITH(tt, code);
1253     code = read_DbHeader(tt);
1254     if (code)
1255         ABORT_WITH(tt, code);
1256
1257     if (aid != PRBADID) {
1258         temp = FindByID(tt, aid);
1259         if (!temp)
1260             ABORT_WITH(tt, PRNOENT);
1261         code = pr_ReadEntry(tt, 0, temp, &tentry);
1262         if (code)
1263             ABORT_WITH(tt, code);
1264
1265         /* afs does authenticate now */
1266         code = WhoIsThis(call, tt, &cid);
1267         if (code
1268             || !AccessOK(tt, cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1269             ABORT_WITH(tt, PRPERM);
1270     }
1271     code = NameToID(tt, inet_ntoa(iaddr), &hostid);
1272     if (code == PRSUCCESS && hostid != 0) {
1273         temp = FindByID(tt, hostid);
1274         if (temp) {
1275             code = pr_ReadEntry(tt, 0, temp, &host_tentry);
1276             if (code == PRSUCCESS)
1277                 host_list = 1;
1278             else
1279                 fprintf(stderr, "pr_ReadEntry returned %d\n", code);
1280         } else
1281             fprintf(stderr, "FindByID Failed -- Not found\n");
1282     }
1283     if (host_list)
1284         code = GetList2(tt, &tentry, &host_tentry, alist, 1);
1285     else
1286         code = GetList(tt, &tentry, alist, 1);
1287 #if IP_WILDCARDS
1288     if (!code)
1289         code = addWildCards(tt, alist, ntohl(ahost));
1290 #endif /* IP_WILDCARDS */
1291     if (code != PRSUCCESS)
1292         ABORT_WITH(tt, code);
1293
1294     code = ubik_EndTrans(tt);
1295     return code;
1296 }
1297
1298
1299 afs_int32
1300 SPR_GetHostCPS(call, ahost, alist, over)
1301      struct rx_call *call;
1302      afs_int32 ahost;
1303      prlist *alist;
1304      afs_int32 *over;
1305 {
1306     afs_int32 code;
1307
1308     code = getHostCPS(call, ahost, alist, over);
1309     osi_auditU(call, PTS_GetHCPSEvent, code, AUD_HOST, ahost, AUD_END);
1310     return code;
1311 }
1312
1313 afs_int32
1314 getHostCPS(call, ahost, alist, over)
1315      struct rx_call *call;
1316      afs_int32 ahost;
1317      prlist *alist;
1318      afs_int32 *over;
1319 {
1320     register afs_int32 code, temp;
1321     struct ubik_trans *tt;
1322     struct prentry host_tentry;
1323     afs_int32 hostid;
1324     struct in_addr iaddr;
1325 #if IP_WILDCARDS
1326     extern afs_int32 addWildCards();
1327 #endif /* IP_WILDCARDS */
1328
1329     *over = 0;
1330     iaddr.s_addr = ntohl(ahost);
1331     alist->prlist_len = 0;
1332     alist->prlist_val = NULL;
1333     code = Initdb();
1334     if (code != PRSUCCESS)
1335         return code;
1336     code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1337     if (code)
1338         return code;
1339     code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1340     if (code)
1341         ABORT_WITH(tt, code);
1342     code = read_DbHeader(tt);
1343     if (code)
1344         ABORT_WITH(tt, code);
1345
1346     code = NameToID(tt, inet_ntoa(iaddr), &hostid);
1347     if (code == PRSUCCESS && hostid != 0) {
1348         temp = FindByID(tt, hostid);
1349         if (temp) {
1350             code = pr_ReadEntry(tt, 0, temp, &host_tentry);
1351             if (code == PRSUCCESS) {
1352                 code = GetList(tt, &host_tentry, alist, 0);
1353                 if (code)
1354                     goto bad;
1355             } else
1356                 fprintf(stderr, "pr_ReadEntry returned %d\n", code);
1357         } else
1358             fprintf(stderr, "FindByID Failed -- Not found\n");
1359     }
1360 #if IP_WILDCARDS
1361     code = addWildCards(tt, alist, ntohl(ahost));
1362 #endif /* IP_WILDCARDS */
1363   bad:
1364     if (code != PRSUCCESS)
1365         ABORT_WITH(tt, code);
1366
1367     code = ubik_EndTrans(tt);
1368     return code;
1369 }
1370
1371
1372 afs_int32
1373 SPR_ListMax(call, uid, gid)
1374      struct rx_call *call;
1375      afs_int32 *uid;
1376      afs_int32 *gid;
1377 {
1378     afs_int32 code;
1379
1380     code = listMax(call, uid, gid);
1381     osi_auditU(call, PTS_LstMaxEvent, code, AUD_END);
1382     return code;
1383 }
1384
1385 afs_int32
1386 listMax(call, uid, gid)
1387      struct rx_call *call;
1388      afs_int32 *uid;
1389      afs_int32 *gid;
1390 {
1391     register afs_int32 code;
1392     struct ubik_trans *tt;
1393
1394     code = Initdb();
1395     if (code != PRSUCCESS)
1396         return code;
1397     code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1398     if (code)
1399         return code;
1400     code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1401     if (code)
1402         ABORT_WITH(tt, code);
1403     code = read_DbHeader(tt);
1404     if (code)
1405         ABORT_WITH(tt, code);
1406
1407     code = GetMax(tt, uid, gid);
1408     if (code != PRSUCCESS)
1409         ABORT_WITH(tt, code);
1410
1411     code = ubik_EndTrans(tt);
1412     if (code)
1413         return code;
1414     return PRSUCCESS;
1415 }
1416
1417 afs_int32
1418 SPR_SetMax(call, aid, gflag)
1419      struct rx_call *call;
1420      afs_int32 aid;
1421      afs_int32 gflag;
1422 {
1423     afs_int32 code;
1424
1425     code = setMax(call, aid, gflag);
1426     osi_auditU(call, PTS_SetMaxEvent, code, AUD_LONG, aid, AUD_LONG, gflag,
1427                AUD_END);
1428     return code;
1429 }
1430
1431 afs_int32
1432 setMax(call, aid, gflag)
1433      struct rx_call *call;
1434      afs_int32 aid;
1435      afs_int32 gflag;
1436 {
1437     register afs_int32 code;
1438     struct ubik_trans *tt;
1439     afs_int32 cid;
1440
1441     code = Initdb();
1442     if (code != PRSUCCESS)
1443         return code;
1444     code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1445     if (code)
1446         return code;
1447     code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1448     if (code)
1449         ABORT_WITH(tt, code);
1450     code = read_DbHeader(tt);
1451     if (code)
1452         ABORT_WITH(tt, code);
1453
1454     code = WhoIsThis(call, tt, &cid);
1455     if (code)
1456         ABORT_WITH(tt, PRPERM);
1457     if (!AccessOK(tt, cid, 0, 0, 0))
1458         ABORT_WITH(tt, PRPERM);
1459     if (((gflag & PRGRP) && (aid > 0)) || (!(gflag & PRGRP) && (aid < 0)))
1460         ABORT_WITH(tt, PRBADARG);
1461
1462     code = SetMax(tt, aid, gflag);
1463     if (code != PRSUCCESS)
1464         ABORT_WITH(tt, code);
1465
1466     code = ubik_EndTrans(tt);
1467     if (code)
1468         return code;
1469     return PRSUCCESS;
1470 }
1471
1472 afs_int32
1473 SPR_ListEntry(call, aid, aentry)
1474      struct rx_call *call;
1475      afs_int32 aid;
1476      struct prcheckentry *aentry;
1477 {
1478     afs_int32 code;
1479
1480     code = listEntry(call, aid, aentry);
1481     osi_auditU(call, PTS_LstEntEvent, code, AUD_LONG, aid, AUD_END);
1482     return code;
1483 }
1484
1485 afs_int32
1486 listEntry(call, aid, aentry)
1487      struct rx_call *call;
1488      afs_int32 aid;
1489      struct prcheckentry *aentry;
1490 {
1491     register afs_int32 code;
1492     struct ubik_trans *tt;
1493     afs_int32 cid;
1494     afs_int32 temp;
1495     struct prentry tentry;
1496
1497     code = Initdb();
1498     if (code != PRSUCCESS)
1499         return code;
1500     code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1501     if (code)
1502         return code;
1503     code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1504     if (code)
1505         ABORT_WITH(tt, code);
1506     code = read_DbHeader(tt);
1507     if (code)
1508         ABORT_WITH(tt, code);
1509
1510     code = WhoIsThis(call, tt, &cid);
1511     if (code)
1512         ABORT_WITH(tt, PRPERM);
1513     temp = FindByID(tt, aid);
1514     if (!temp)
1515         ABORT_WITH(tt, PRNOENT);
1516     code = pr_ReadEntry(tt, 0, temp, &tentry);
1517     if (code != 0)
1518         ABORT_WITH(tt, code);
1519     if (!AccessOK(tt, cid, &tentry, PRP_STATUS_MEM, PRP_STATUS_ANY))
1520         ABORT_WITH(tt, PRPERM);
1521
1522     aentry->flags = tentry.flags >> PRIVATE_SHIFT;
1523     if (aentry->flags == 0) {
1524         if (tentry.flags & PRGRP)
1525             aentry->flags = prp_group_default >> PRIVATE_SHIFT;
1526         else
1527             aentry->flags = prp_user_default >> PRIVATE_SHIFT;
1528     }
1529     aentry->owner = tentry.owner;
1530     aentry->id = tentry.id;
1531     strncpy(aentry->name, tentry.name, PR_MAXNAMELEN);
1532     aentry->creator = tentry.creator;
1533     aentry->ngroups = tentry.ngroups;
1534     aentry->nusers = tentry.nusers;
1535     aentry->count = tentry.count;
1536     memset(aentry->reserved, 0, sizeof(aentry->reserved));
1537     code = ubik_EndTrans(tt);
1538     if (code)
1539         return code;
1540     return PRSUCCESS;
1541 }
1542
1543 afs_int32
1544 SPR_ListEntries(call, flag, startindex, bulkentries, nextstartindex)
1545      struct rx_call *call;
1546      afs_int32 flag;
1547      afs_int32 startindex;
1548      prentries *bulkentries;
1549      afs_int32 *nextstartindex;
1550 {
1551     afs_int32 code;
1552
1553     code = listEntries(call, flag, startindex, bulkentries, nextstartindex);
1554     osi_auditU(call, PTS_LstEntsEvent, code, AUD_LONG, flag, AUD_END);
1555     return code;
1556 }
1557
1558 afs_int32
1559 listEntries(call, flag, startindex, bulkentries, nextstartindex)
1560      struct rx_call *call;
1561      afs_int32 flag;
1562      afs_int32 startindex;
1563      prentries *bulkentries;
1564      afs_int32 *nextstartindex;
1565 {
1566     afs_int32 code;
1567     struct ubik_trans *tt;
1568     afs_int32 cid;
1569     afs_int32 i, eof, pos, maxentries, f;
1570     struct prentry tentry;
1571     afs_int32 pollcount = 0;
1572
1573     *nextstartindex = -1;
1574     bulkentries->prentries_val = 0;
1575     bulkentries->prentries_len = 0;
1576
1577     code = Initdb();
1578     if (code != PRSUCCESS)
1579         return code;
1580     code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1581     if (code)
1582         return code;
1583     code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1584     if (code)
1585         ABORT_WITH(tt, code);
1586     code = read_DbHeader(tt);
1587     if (code)
1588         ABORT_WITH(tt, code);
1589
1590     /* Make sure we are an authenticated caller and that we are on the
1591      * SYSADMIN list.
1592      */
1593     code = WhoIsThis(call, tt, &cid);
1594     if (code)
1595         ABORT_WITH(tt, PRPERM);
1596     code = IsAMemberOf(tt, cid, SYSADMINID);
1597     if (!code && !pr_noAuth)
1598         ABORT_WITH(tt, PRPERM);
1599
1600     eof = ntohl(cheader.eofPtr) - sizeof(cheader);
1601     maxentries = eof / sizeof(struct prentry);
1602     for (i = startindex; i < maxentries; i++) {
1603         pos = i * sizeof(struct prentry) + sizeof(cheader);
1604         code = pr_ReadEntry(tt, 0, pos, &tentry);
1605         if (code)
1606             goto done;
1607
1608         if (++pollcount > 50) {
1609             IOMGR_Poll();
1610             pollcount = 0;
1611         }
1612
1613         f = (tentry.flags & PRTYPE);
1614         if (((flag & PRUSERS) && (f == 0)) ||   /* User  entry */
1615             ((flag & PRGROUPS) && (f & PRGRP))) {       /* Group entry */
1616             code = put_prentries(&tentry, bulkentries);
1617             if (code == -1)
1618                 break;          /* Filled return array */
1619             if (code)
1620                 goto done;
1621         }
1622     }
1623     code = 0;
1624     if (i < maxentries)
1625         *nextstartindex = i;
1626
1627   done:
1628     if (code) {
1629         if (bulkentries->prentries_val)
1630             free(bulkentries->prentries_val);
1631         bulkentries->prentries_val = 0;
1632         bulkentries->prentries_len = 0;
1633         ABORT_WITH(tt, code);
1634     } else {
1635         code = ubik_EndTrans(tt);
1636     }
1637     if (code)
1638         return code;
1639     return PRSUCCESS;
1640 }
1641
1642 #define PR_MAXENTRIES 500
1643 afs_int32
1644 put_prentries(tentry, bulkentries)
1645      struct prentry *tentry;
1646      prentries *bulkentries;
1647 {
1648     struct prlistentries *entry;
1649
1650     if (bulkentries->prentries_val == 0) {
1651         bulkentries->prentries_len = 0;
1652         bulkentries->prentries_val =
1653             (struct prlistentries *)malloc(PR_MAXENTRIES *
1654                                            sizeof(struct prentry));
1655         if (!bulkentries->prentries_val) {
1656             return (PRNOMEM);
1657         }
1658     }
1659
1660     if (bulkentries->prentries_len >= PR_MAXENTRIES) {
1661         return (-1);
1662     }
1663
1664     entry = (struct prlistentries *)bulkentries->prentries_val;
1665     entry += bulkentries->prentries_len;
1666
1667     entry->flags = tentry->flags >> PRIVATE_SHIFT;
1668     if (entry->flags == 0) {
1669         entry->flags =
1670             ((tentry->
1671               flags & PRGRP) ? prp_group_default : prp_user_default) >>
1672             PRIVATE_SHIFT;
1673     }
1674     entry->owner = tentry->owner;
1675     entry->id = tentry->id;
1676     entry->creator = tentry->creator;
1677     entry->ngroups = tentry->ngroups;
1678     entry->nusers = tentry->nusers;
1679     entry->count = tentry->count;
1680     strncpy(entry->name, tentry->name, PR_MAXNAMELEN);
1681     memset(entry->reserved, 0, sizeof(entry->reserved));
1682     bulkentries->prentries_len++;
1683     return 0;
1684 }
1685
1686 afs_int32
1687 SPR_ChangeEntry(call, aid, name, oid, newid)
1688      struct rx_call *call;
1689      afs_int32 aid;
1690      char *name;
1691      afs_int32 oid;
1692      afs_int32 newid;
1693 {
1694     afs_int32 code;
1695
1696     code = changeEntry(call, aid, name, oid, newid);
1697     osi_auditU(call, PTS_ChgEntEvent, code, AUD_LONG, aid, AUD_STR, name,
1698                AUD_LONG, oid, AUD_LONG, newid, AUD_END);
1699     return code;
1700 }
1701
1702 afs_int32
1703 changeEntry(call, aid, name, oid, newid)
1704      struct rx_call *call;
1705      afs_int32 aid;
1706      char *name;
1707      afs_int32 oid;
1708      afs_int32 newid;
1709 {
1710     register afs_int32 code;
1711     struct ubik_trans *tt;
1712     afs_int32 pos;
1713     afs_int32 cid;
1714
1715     if (!name)
1716         return PRPERM;
1717     stolower(name);
1718
1719     code = Initdb();
1720     if (code)
1721         return code;
1722     if (aid == ANYUSERID || aid == AUTHUSERID || aid == ANONYMOUSID
1723         || aid == SYSADMINID)
1724         return PRPERM;
1725     if (code != PRSUCCESS)
1726         return code;
1727     code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1728     if (code)
1729         return code;
1730     code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1731     if (code)
1732         ABORT_WITH(tt, code);
1733     code = read_DbHeader(tt);
1734     if (code)
1735         ABORT_WITH(tt, code);
1736
1737     code = WhoIsThis(call, tt, &cid);
1738     if (code)
1739         ABORT_WITH(tt, PRPERM);
1740     pos = FindByID(tt, aid);
1741     if (!pos)
1742         ABORT_WITH(tt, PRNOENT);
1743     /* protection check in changeentry */
1744     code = ChangeEntry(tt, aid, cid, name, oid, newid);
1745     if (code != PRSUCCESS)
1746         ABORT_WITH(tt, code);
1747
1748     code = ubik_EndTrans(tt);
1749     return code;
1750 }
1751
1752 afs_int32
1753 SPR_SetFieldsEntry(call, id, mask, flags, ngroups, nusers, spare1, spare2)
1754      struct rx_call *call;
1755      afs_int32 id;
1756      afs_int32 mask;            /* specify which fields to update */
1757      afs_int32 flags, ngroups, nusers;
1758      afs_int32 spare1, spare2;
1759 {
1760     afs_int32 code;
1761
1762     code =
1763         setFieldsEntry(call, id, mask, flags, ngroups, nusers, spare1,
1764                        spare2);
1765     osi_auditU(call, PTS_SetFldEntEvent, code, AUD_LONG, id, AUD_END);
1766     return code;
1767 }
1768
1769 afs_int32
1770 setFieldsEntry(call, id, mask, flags, ngroups, nusers, spare1, spare2)
1771      struct rx_call *call;
1772      afs_int32 id;
1773      afs_int32 mask;            /* specify which fields to update */
1774      afs_int32 flags, ngroups, nusers;
1775      afs_int32 spare1, spare2;
1776 {
1777     register afs_int32 code;
1778     struct ubik_trans *tt;
1779     afs_int32 pos;
1780     afs_int32 cid;
1781     struct prentry tentry;
1782     afs_int32 tflags;
1783
1784     if (mask == 0)
1785         return 0;               /* no-op */
1786     code = Initdb();
1787     if (code)
1788         return code;
1789     if (id == ANYUSERID || id == AUTHUSERID || id == ANONYMOUSID)
1790         return PRPERM;
1791     if (code != PRSUCCESS)
1792         return code;
1793     code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1794     if (code)
1795         return code;
1796     code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1797     if (code)
1798         ABORT_WITH(tt, code);
1799     code = read_DbHeader(tt);
1800     if (code)
1801         ABORT_WITH(tt, code);
1802
1803     code = WhoIsThis(call, tt, &cid);
1804     if (code)
1805         ABORT_WITH(tt, PRPERM);
1806     pos = FindByID(tt, id);
1807     if (!pos)
1808         ABORT_WITH(tt, PRNOENT);
1809     code = pr_ReadEntry(tt, 0, pos, &tentry);
1810     if (code)
1811         ABORT_WITH(tt, code);
1812     tflags = tentry.flags;
1813
1814     if (mask & (PR_SF_NGROUPS | PR_SF_NUSERS)) {
1815         if (!AccessOK(tt, cid, 0, 0, 0))
1816             ABORT_WITH(tt, PRPERM);
1817         if ((tflags & PRQUOTA) == 0) {  /* default if only setting one */
1818             tentry.ngroups = tentry.nusers = 20;
1819         }
1820     } else {
1821         if (!AccessOK(tt, cid, &tentry, 0, 0))
1822             ABORT_WITH(tt, PRPERM);
1823     }
1824
1825     if (mask & 0xffff) {        /* if setting flag bits */
1826         afs_int32 flagsMask = mask & 0xffff;
1827         tflags &= ~(flagsMask << PRIVATE_SHIFT);
1828         tflags |= (flags & flagsMask) << PRIVATE_SHIFT;
1829         tflags |= PRACCESS;
1830     }
1831
1832     if (mask & PR_SF_NGROUPS) { /* setting group limit */
1833         if (ngroups < 0)
1834             ABORT_WITH(tt, PRBADARG);
1835         tentry.ngroups = ngroups;
1836         tflags |= PRQUOTA;
1837     }
1838
1839     if (mask & PR_SF_NUSERS) {  /* setting foreign user limit */
1840         if (nusers < 0)
1841             ABORT_WITH(tt, PRBADARG);
1842         tentry.nusers = nusers;
1843         tflags |= PRQUOTA;
1844     }
1845     tentry.flags = tflags;
1846
1847     code = pr_WriteEntry(tt, 0, pos, &tentry);
1848     if (code)
1849         ABORT_WITH(tt, code);
1850
1851     code = ubik_EndTrans(tt);
1852     return code;
1853 }
1854
1855 afs_int32
1856 SPR_ListElements(call, aid, alist, over)
1857      struct rx_call *call;
1858      afs_int32 aid;
1859      prlist *alist;
1860      afs_int32 *over;
1861 {
1862     afs_int32 code;
1863
1864     code = listElements(call, aid, alist, over);
1865     osi_auditU(call, PTS_LstEleEvent, code, AUD_LONG, aid, AUD_END);
1866     return code;
1867 }
1868
1869 afs_int32
1870 listElements(call, aid, alist, over)
1871      struct rx_call *call;
1872      afs_int32 aid;
1873      prlist *alist;
1874      afs_int32 *over;
1875 {
1876     register afs_int32 code;
1877     struct ubik_trans *tt;
1878     afs_int32 cid;
1879     afs_int32 temp;
1880     struct prentry tentry;
1881
1882     *over = 0;
1883     alist->prlist_len = 0;
1884     alist->prlist_val = NULL;
1885
1886     code = Initdb();
1887     if (code != PRSUCCESS)
1888         return code;
1889     code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1890     if (code)
1891         return code;
1892     code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1893     if (code)
1894         ABORT_WITH(tt, code);
1895     code = read_DbHeader(tt);
1896     if (code)
1897         ABORT_WITH(tt, code);
1898
1899     code = WhoIsThis(call, tt, &cid);
1900     if (code)
1901         ABORT_WITH(tt, PRPERM);
1902
1903     temp = FindByID(tt, aid);
1904     if (!temp)
1905         ABORT_WITH(tt, PRNOENT);
1906     code = pr_ReadEntry(tt, 0, temp, &tentry);
1907     if (code)
1908         ABORT_WITH(tt, code);
1909     if (!AccessOK(tt, cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1910         ABORT_WITH(tt, PRPERM);
1911
1912     code = GetList(tt, &tentry, alist, 0);
1913     if (code != PRSUCCESS)
1914         ABORT_WITH(tt, code);
1915
1916     code = ubik_EndTrans(tt);
1917     return code;
1918 }
1919
1920
1921 afs_int32
1922 SPR_ListSuperGroups(call, aid, alist, over)
1923      struct rx_call *call;
1924      afs_int32 aid;
1925      prlist *alist;
1926      afs_int32 *over;
1927 {
1928 #if defined(SUPERGROUPS)
1929     afs_int32 code;
1930
1931     code = listSuperGroups(call, aid, alist, over);
1932     osi_auditU(call, "PTS_LstSGrps", code, AUD_LONG, aid, AUD_END);
1933     return code;
1934 #else
1935     return RXGEN_OPCODE;
1936 #endif
1937 }
1938
1939 #if defined(SUPERGROUPS)
1940 afs_int32
1941 listSuperGroups(call, aid, alist, over)
1942      struct rx_call *call;
1943      afs_int32 aid;
1944      prlist *alist;
1945      afs_int32 *over;
1946 {
1947     register afs_int32 code;
1948     struct ubik_trans *tt;
1949     afs_int32 cid;
1950     afs_int32 temp;
1951     struct prentry tentry;
1952
1953     alist->prlist_len = 0;
1954     alist->prlist_val = (afs_int32 *) 0;
1955
1956     code = Initdb();
1957     if (code != PRSUCCESS)
1958         goto done;
1959     code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1960     if (code)
1961         goto done;
1962     code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1963     if (code)
1964         ABORT_WITH(tt, code);
1965     code = WhoIsThis(call, tt, &cid);
1966     if (code)
1967         ABORT_WITH(tt, PRPERM);
1968
1969     temp = FindByID(tt, aid);
1970     if (!temp)
1971         ABORT_WITH(tt, PRNOENT);
1972     code = pr_ReadEntry(tt, 0, temp, &tentry);
1973     if (code)
1974         ABORT_WITH(tt, code);
1975     if (!AccessOK(tt, cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1976         ABORT_WITH(tt, PRPERM);
1977
1978     code = GetSGList(tt, &tentry, alist);
1979     *over = 0;
1980     if (code == PRTOOMANY)
1981         *over = 1;
1982     else if (code != PRSUCCESS)
1983         ABORT_WITH(tt, code);
1984
1985     code = ubik_EndTrans(tt);
1986
1987   done:
1988     return code;
1989 }
1990
1991 #endif /* SUPERGROUPS */
1992
1993 /* 
1994  * SPR_ListOwned
1995  * List the entries owned by this id.  If the id is zero,
1996  * return the orphans list. This will return up to PR_MAXGROUPS
1997  * at a time with the lastP available to get the rest. The
1998  * maximum value is enforced in GetOwnedChain().
1999  */
2000 afs_int32
2001 SPR_ListOwned(call, aid, alist, lastP)
2002      struct rx_call *call;
2003      afs_int32 aid;
2004      prlist *alist;
2005      afs_int32 *lastP;
2006 {
2007     afs_int32 code;
2008
2009     code = listOwned(call, aid, alist, lastP);
2010     osi_auditU(call, PTS_LstOwnEvent, code, AUD_LONG, aid, AUD_END);
2011     return code;
2012 }
2013
2014 afs_int32
2015 listOwned(call, aid, alist, lastP)
2016      struct rx_call *call;
2017      afs_int32 aid;
2018      prlist *alist;
2019      afs_int32 *lastP;
2020 {
2021     register afs_int32 code;
2022     struct ubik_trans *tt;
2023     afs_int32 cid;
2024     struct prentry tentry;
2025     afs_int32 head = 0;
2026     afs_int32 start;
2027
2028     alist->prlist_len = 0;
2029     alist->prlist_val = NULL;
2030
2031     if (!lastP)
2032         return PRBADARG;
2033     start = *lastP;
2034     *lastP = 0;
2035
2036     code = Initdb();
2037     if (code != PRSUCCESS)
2038         return code;
2039     code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
2040     if (code)
2041         return code;
2042     code = ubik_SetLock(tt, 1, 1, LOCKREAD);
2043     if (code)
2044         ABORT_WITH(tt, code);
2045     code = read_DbHeader(tt);
2046     if (code)
2047         ABORT_WITH(tt, code);
2048
2049     code = WhoIsThis(call, tt, &cid);
2050     if (code)
2051         ABORT_WITH(tt, PRPERM);
2052
2053     if (start) {
2054         code = pr_ReadEntry(tt, 0, start, &tentry);
2055         if (!code && (tentry.owner == aid))
2056             head = start;       /* pick up where we left off */
2057     }
2058
2059     if (!head) {
2060         if (aid) {
2061             afs_int32 loc = FindByID(tt, aid);
2062             if (loc == 0)
2063                 ABORT_WITH(tt, PRNOENT);
2064             code = pr_ReadEntry(tt, 0, loc, &tentry);
2065             if (code)
2066                 ABORT_WITH(tt, code);
2067
2068             if (!AccessOK(tt, cid, &tentry, -1, PRP_OWNED_ANY))
2069                 ABORT_WITH(tt, PRPERM);
2070             head = tentry.owned;
2071         } else {
2072             if (!AccessOK(tt, cid, 0, 0, 0))
2073                 ABORT_WITH(tt, PRPERM);
2074             head = ntohl(cheader.orphan);
2075         }
2076     }
2077
2078     code = GetOwnedChain(tt, &head, alist);
2079     if (code) {
2080         if (code == PRTOOMANY)
2081             *lastP = head;
2082         else
2083             ABORT_WITH(tt, code);
2084     }
2085
2086     code = ubik_EndTrans(tt);
2087     return code;
2088 }
2089
2090 afs_int32
2091 SPR_IsAMemberOf(call, uid, gid, flag)
2092      struct rx_call *call;
2093      afs_int32 uid;
2094      afs_int32 gid;
2095      afs_int32 *flag;
2096 {
2097     afs_int32 code;
2098
2099     code = isAMemberOf(call, uid, gid, flag);
2100     osi_auditU(call, PTS_IsMemOfEvent, code, AUD_LONG, uid, AUD_LONG, gid,
2101                AUD_END);
2102     return code;
2103 }
2104
2105 afs_int32
2106 isAMemberOf(call, uid, gid, flag)
2107      struct rx_call *call;
2108      afs_int32 uid;
2109      afs_int32 gid;
2110      afs_int32 *flag;
2111 {
2112     register afs_int32 code;
2113     struct ubik_trans *tt;
2114
2115     code = Initdb();
2116     if (code != PRSUCCESS)
2117         return code;
2118     code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
2119     if (code)
2120         return code;
2121     code = ubik_SetLock(tt, 1, 1, LOCKREAD);
2122     if (code)
2123         ABORT_WITH(tt, code);
2124     code = read_DbHeader(tt);
2125     if (code)
2126         ABORT_WITH(tt, code);
2127
2128     {
2129         afs_int32 cid;
2130         afs_int32 uloc = FindByID(tt, uid);
2131         afs_int32 gloc = FindByID(tt, gid);
2132         struct prentry uentry, gentry;
2133
2134         if (!uloc || !gloc)
2135             ABORT_WITH(tt, PRNOENT);
2136         code = WhoIsThis(call, tt, &cid);
2137         if (code)
2138             ABORT_WITH(tt, PRPERM);
2139         code = pr_ReadEntry(tt, 0, uloc, &uentry);
2140         if (code)
2141             ABORT_WITH(tt, code);
2142         code = pr_ReadEntry(tt, 0, gloc, &gentry);
2143         if (code)
2144             ABORT_WITH(tt, code);
2145 #if !defined(SUPERGROUPS)
2146         if ((uentry.flags & PRGRP) || !(gentry.flags & PRGRP))
2147             ABORT_WITH(tt, PRBADARG);
2148 #else
2149         if (!(gentry.flags & PRGRP))
2150             ABORT_WITH(tt, PRBADARG);
2151 #endif
2152         if (!AccessOK(tt, cid, &uentry, 0, PRP_MEMBER_ANY)
2153             && !AccessOK(tt, cid, &gentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
2154             ABORT_WITH(tt, PRPERM);
2155     }
2156
2157     *flag = IsAMemberOf(tt, uid, gid);
2158     code = ubik_EndTrans(tt);
2159     return code;
2160 }
2161
2162
2163 static
2164 stolower(s)
2165      register char *s;
2166 {
2167     register int tc;
2168     while ((tc = *s)) {
2169         if (isupper(tc))
2170             *s = tolower(tc);
2171         s++;
2172     }
2173 }
2174
2175 #if IP_WILDCARDS
2176 afs_int32
2177 addWildCards(tt, alist, host)
2178      struct ubik_trans *tt;
2179      prlist *alist;
2180      afs_int32 host;
2181 {
2182     afs_int32 temp;
2183     struct prentry tentry;
2184     prlist wlist;
2185     unsigned wild = htonl(0xffffff00);
2186     struct in_addr iaddr;
2187     afs_int32 hostid;
2188     int size = 0, i, code;
2189     int added = 0;
2190
2191     while ((host = (host & wild))) {
2192         wild = htonl(ntohl(wild) << 8);
2193         iaddr.s_addr = host;
2194         code = NameToID(tt, inet_ntoa(iaddr), &hostid);
2195         if (code == PRSUCCESS && hostid != 0) {
2196             temp = FindByID(tt, hostid);
2197             if (temp) {
2198                 code = pr_ReadEntry(tt, 0, temp, &tentry);
2199                 if (code != PRSUCCESS)
2200                     continue;
2201             } else
2202                 continue;
2203         } else
2204             continue;
2205         wlist.prlist_len = 0;
2206         wlist.prlist_val = NULL;
2207
2208         code = GetList(tt, &tentry, &wlist, 0);
2209         if (code)
2210             return code;
2211         added += wlist.prlist_len;
2212         for (i = 0; i < wlist.prlist_len; i++) {
2213             if (!inCPS(*alist, wlist.prlist_val[i]))
2214                 if ((code = AddToPRList(alist, &size, wlist.prlist_val[i]))) {
2215                     free(wlist.prlist_val);
2216                     return (code);
2217                 }
2218         }
2219         if (wlist.prlist_val)
2220             free(wlist.prlist_val);
2221     }
2222     if (added)
2223         qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
2224     return 0;
2225 }
2226 #endif /* IP_WILDCARDS */
2227
2228
2229 afs_int32
2230 WhoIsThisWithName(acall, at, aid, aname)
2231      struct rx_call *acall;
2232      struct ubik_trans *at;
2233      afs_int32 *aid;
2234      char *aname;
2235 {
2236     /* aid is set to the identity of the caller, if known, else ANONYMOUSID */
2237     /* returns -1 and sets aid to ANONYMOUSID on any failure */
2238     register struct rx_connection *tconn;
2239     register afs_int32 code;
2240     char tcell[MAXKTCREALMLEN];
2241     char name[MAXKTCNAMELEN];
2242     char inst[MAXKTCNAMELEN];
2243     int ilen;
2244     char vname[256];
2245
2246     *aid = ANONYMOUSID;
2247     tconn = rx_ConnectionOf(acall);
2248     code = rx_SecurityClassOf(tconn);
2249     if (code == 0)
2250         return 0;
2251     else if (code == 1) {       /* vab class */
2252         goto done;              /* no longer supported */
2253     } else if (code == 2) {     /* kad class */
2254
2255         int clen;
2256         extern char *pr_realmName;
2257
2258         if ((code = rxkad_GetServerInfo(acall->conn, NULL, 0 /*was &exp */ ,
2259                                         name, inst, tcell, NULL)))
2260             goto done;
2261         strncpy(vname, name, sizeof(vname));
2262         if ((ilen = strlen(inst))) {
2263             if (strlen(vname) + 1 + ilen >= sizeof(vname))
2264                 goto done;
2265             strcat(vname, ".");
2266             strcat(vname, inst);
2267         }
2268         if ((clen = strlen(tcell))) {
2269
2270 #if     defined(AFS_ATHENA_STDENV) || defined(AFS_KERBREALM_ENV)
2271             static char local_realm[AFS_REALM_SZ] = "";
2272             if (!local_realm[0]) {
2273                 if (afs_krb_get_lrealm(local_realm, 0) != 0 /*KSUCCESS*/)
2274                     strncpy(local_realm, pr_realmName, AFS_REALM_SZ);
2275             }
2276 #endif
2277             if (
2278 #if     defined(AFS_ATHENA_STDENV) || defined(AFS_KERBREALM_ENV)
2279                    strcasecmp(local_realm, tcell) &&
2280 #endif
2281                    strcasecmp(pr_realmName, tcell)) {
2282                 if (strlen(vname) + 1 + clen >= sizeof(vname))
2283                     goto done;
2284                 strcat(vname, "@");
2285                 strcat(vname, tcell);
2286                 lcstring(vname, vname, sizeof(vname));
2287                 code = NameToID(at, vname, aid);
2288                 strcpy(aname, vname);
2289                 return 2;
2290             }
2291         }
2292
2293         if (strcmp(AUTH_SUPERUSER, vname) == 0)
2294             *aid = SYSADMINID;  /* special case for the fileserver */
2295         else {
2296             lcstring(vname, vname, sizeof(vname));
2297             code = NameToID(at, vname, aid);
2298         }
2299     }
2300   done:
2301     if (code && !pr_noAuth)
2302         return -1;
2303     return 0;
2304 }