]> andersk Git - moira.git/blob - afssync/ptprocs.c
Used /bin/sh format instead of /bin/csh format, by accident.
[moira.git] / afssync / ptprocs.c
1 /* Copyright (C) 1990, 1989 Transarc Corporation - All rights reserved */
2 /*
3  * P_R_P_Q_# (C) COPYRIGHT IBM CORPORATION 1988
4  * LICENSED MATERIALS - PROPERTY OF IBM
5  * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
6  */
7
8 /*      
9        Sherri Nichols
10        Information Technology Center
11        November, 1988
12 */
13
14 #include <afs/param.h>
15 #include <afs/stds.h>
16 #include <ctype.h>
17 #include <stdio.h>
18 #ifdef AFS_HPUX_ENV
19 #include <string.h>
20 #else
21 #include <strings.h>
22 #endif
23 #include <lock.h>
24 #include <ubik.h>
25 #include <rx/xdr.h>
26 #include <rx/rx.h>
27 #include <rx/rxkad.h>
28 #include <afs/auth.h>
29 #include <netinet/in.h>
30 #include "ptserver.h"
31 #include "pterror.h"
32
33 #if defined(CROSS_CELL) && !defined(WhoIsThisWithName)
34 static long WhoIsThisWithName();
35 #endif
36
37
38 RCSID ("$Header$")
39
40 extern struct ubik_dbase *dbase;
41 extern long Initdb();
42 extern int pr_noAuth;
43 extern char *prdir;
44
45 static int CreateOK (ut, cid, oid, flag, admin)
46   struct ubik_trans *ut;
47   long cid;                             /* id of caller */
48   long oid;                             /* id of owner */
49   long flag;                            /* indicates type of entry */
50   int  admin;                           /* sysadmin membership */
51 {
52     if (flag & (PRGRP | PRFOREIGN)) {
53         /* Allow anonymous group creation only if owner specified and running
54          * noAuth. */
55         if (cid == ANONYMOUSID) {
56             if ((oid == 0) || !pr_noAuth) return 0;
57         }
58     }
59     else { /* creating a user */
60         if (!admin && !pr_noAuth) return 0;
61     }
62     return 1;                           /* OK! */
63 }
64
65 #if !defined(WhoIsThis)
66 long WhoIsThis (acall, at, aid)
67   struct rx_call *acall;
68   struct ubik_trans *at;
69   long *aid;
70 {
71     /* aid is set to the identity of the caller, if known, else ANONYMOUSID */
72     /* returns -1 and sets aid to ANONYMOUSID on any failure */
73     register struct rx_connection *tconn;
74     register long code;
75     char tcell[MAXKTCREALMLEN];
76     char name[MAXKTCNAMELEN];
77     char inst[MAXKTCNAMELEN];
78     int  ilen;
79     char vname[256];
80 #ifdef CROSS_CELL
81     int foreign = 0;
82 #endif
83
84     *aid = SYSADMINID;
85     return 0;
86
87     *aid = ANONYMOUSID;
88     tconn = rx_ConnectionOf(acall);
89     code = rx_SecurityClassOf(tconn);
90     if (code == 0) return 0;
91     else if (code == 1) {               /* vab class */
92         goto done;                      /* no longer supported */
93     }
94     else if (code == 2) {               /* kad class */
95         if (code = rxkad_GetServerInfo
96             (acall->conn, (long *) 0, 0/*was &exp*/,
97              name, inst, tcell, (long *) 0))
98             goto done;
99 #if 0
100         /* This test is unnecessary, since rxkad_GetServerInfo already check.
101          * In addition, this is wrong since exp must be unsigned. */
102         if (exp < FT_ApproxTime()) goto done;
103 #endif
104         if (strlen (tcell)) {
105             if (!afsconf_LocalRealm(prdir, tcell)) {
106 #ifdef CROSS_CELL
107                 foreign = 1;
108 #else
109                 goto done;
110 #endif
111             }
112         }
113         strncpy (vname, name, sizeof(vname));
114         if (ilen = strlen (inst)) {
115             if (strlen(vname) + 1 + ilen >= sizeof(vname)) goto done;
116             strcat (vname, ".");
117             strcat (vname, inst);
118         }
119 #ifdef CROSS_CELL
120         if (foreign) {
121             if ((strlen(name)+strlen(tcell)+1) >= sizeof(vname)) {
122                 goto done;
123             }
124             strcat (vname, "@");
125             strcat (vname, tcell);
126         }
127 #endif
128         if (strcmp (AUTH_SUPERUSER, vname) == 0)
129             *aid = SYSADMINID;          /* special case for the fileserver */
130         else {
131             lcstring(vname, vname, sizeof(vname));
132             code = NameToID(at,vname,aid);
133         }
134     }
135   done:
136     if (code && !pr_noAuth) return -1;
137     return 0;
138 }
139 #endif
140
141 long PR_INewEntry(call,aname,aid,oid)
142   struct rx_call *call;
143   char aname[PR_MAXNAMELEN];
144   long aid;
145   long oid;
146 {
147     /* used primarily for conversion - not intended to be used as usual means
148        of entering people into the database. */
149     struct ubik_trans *tt;
150     register long code;
151     long gflag = 0;
152     long cid;
153     int  admin;
154
155 #define abort_with(code) return (ubik_AbortTrans(tt),code)
156
157     stolower(aname);
158     code = Initdb();
159     if (code != PRSUCCESS) return code;
160     code = ubik_BeginTrans(dbase,UBIK_WRITETRANS, &tt);
161     if (code) return code;
162     code = ubik_SetLock(tt, 1,1,LOCKWRITE);
163     if (code) abort_with (code);
164
165     code = WhoIsThis(call,tt,&cid);
166     if (code) abort_with (PRPERM);
167     admin = IsAMemberOf(tt,cid,SYSADMINID);
168
169     /* first verify the id is good */
170     if (aid == 0) abort_with (PRPERM);
171     if (aid < 0) {
172         gflag |= PRGRP;
173         /* only sysadmin can reuse a group id */
174         if (!admin && !pr_noAuth && (aid != ntohl(cheader.maxGroup)-1))
175             abort_with (PRPERM);
176     }
177     if (FindByID (tt, aid)) abort_with (PRIDEXIST);
178
179     /* check a few other things */
180     if (!CreateOK (tt, cid, oid, gflag, admin)) abort_with (PRPERM);
181
182     code = CreateEntry (tt,aname,&aid,1,gflag,oid,cid);
183     if (code != PRSUCCESS) {
184         ubik_AbortTrans(tt);
185         return code;
186     }
187     /* finally, commit transaction */
188     code = ubik_EndTrans(tt);
189     if (code) return code;
190     return PRSUCCESS;
191 }
192
193
194 long PR_NewEntry (call, aname, flag, oid, aid)
195   struct rx_call *call;
196   char aname[PR_MAXNAMELEN];
197   long flag;
198   long oid;
199   long *aid;
200 {
201     register long code;
202     struct ubik_trans *tt;
203     long cid;
204     int  admin;
205 #ifdef CROSS_CELL
206     char cname[PR_MAXNAMELEN];
207 #endif
208
209     stolower(aname);
210     code = Initdb();
211     if (code) return code;
212     code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
213     if (code) return code;
214     code = ubik_SetLock(tt,1,1,LOCKWRITE);
215     if (code) {
216       abort:
217         ubik_AbortTrans(tt);
218         return code;
219     }
220
221 #ifdef CROSS_CELL
222     /* this is for cross-cell self registration */
223     code = WhoIsThisWithName(call,tt,&cid,cname);
224     if (code != 2) {    /* 2 specifies that this is a foreign cell request */
225         if (code) {
226         perm:
227             ubik_AbortTrans(tt);
228             return PRPERM;
229         }
230         admin = IsAMemberOf(tt,cid,SYSADMINID);
231     } else {
232         admin = (!strcmp(aname,cname)) || IsAMemberOf(tt,cid,SYSADMINID);
233         oid = cid = SYSADMINID;
234     }
235 #else
236     code = WhoIsThis(call,tt,&cid);
237     if (code) {
238       perm:
239         ubik_AbortTrans(tt);
240         return PRPERM;
241     }
242     admin = IsAMemberOf(tt,cid,SYSADMINID);
243 #endif
244     
245     if (!CreateOK (tt, cid, oid, flag, admin)) goto perm;
246
247     code = CreateEntry (tt,aname,aid,0,flag,oid,cid);
248     if (code != PRSUCCESS) goto abort;
249
250     code = ubik_EndTrans(tt);
251     if (code) return code;
252     return PRSUCCESS;
253 }
254
255
256
257 PR_WhereIsIt(call,aid,apos)
258 struct rx_call *call;
259 long aid;
260 long *apos;
261 {
262     register long code;
263     struct ubik_trans *tt;
264     long temp;
265
266     code = Initdb();
267     if (code != PRSUCCESS) return code;
268     code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
269     if (code) return code;
270     code = ubik_SetLock(tt,1,1,LOCKREAD);
271     if (code) {
272         ubik_AbortTrans(tt);
273         return code;
274     }
275     temp = FindByID(tt,aid);
276     if (!temp) {
277         ubik_AbortTrans(tt);
278         return PRNOENT;
279     }
280     *apos = temp;
281     code = ubik_EndTrans(tt);
282     if (code) return code;
283     return PRSUCCESS;
284 }
285
286
287 PR_DumpEntry(call,apos, aentry)
288 struct rx_call *call;
289 long apos;
290 struct prdebugentry *aentry;
291 {
292     register long code;
293     struct ubik_trans *tt;
294
295     code = Initdb();
296     if (code != PRSUCCESS) return code;
297     code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt);
298     if (code) return code;
299     code = ubik_SetLock(tt,1,1,LOCKREAD);
300     if (code) {
301       abort:
302         ubik_AbortTrans(tt);
303         return code;
304     }
305     code = pr_ReadEntry(tt, 0, apos, aentry);
306     if (code) goto abort;
307
308     /* Since prdebugentry is in the form of a prentry not a coentry, we will
309      * return the coentry slots in network order where the string is. */
310 #if 0
311     if (aentry->flags & PRCONT) {       /* wrong type, get coentry instead */
312         code = pr_ReadCoEntry(tt, 0, apos, aentry);
313         if (code) goto abort;
314     }
315 #endif
316     code = ubik_EndTrans(tt);
317     if (code) return code;
318     return PRSUCCESS;
319 }
320
321 PR_AddToGroup(call,aid,gid)
322 struct rx_call *call;
323 long aid;
324 long gid;
325 {
326     register long code;
327     struct ubik_trans *tt;
328     long tempu;
329     long tempg;
330     struct prentry tentry;
331     struct prentry uentry;
332     long cid;
333
334     code = Initdb();
335     if (code != PRSUCCESS) return code;
336     if (gid == ANYUSERID || gid == AUTHUSERID) return PRPERM;
337     if (aid == ANONYMOUSID) return PRPERM;
338     code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
339     if (code) return code;
340     code = ubik_SetLock(tt,1,1,LOCKWRITE);
341     if (code) {
342         ubik_AbortTrans(tt);
343         return code;
344     }
345     code = WhoIsThis(call, tt, &cid);
346     if (code) {
347         ubik_AbortTrans(tt);
348         return PRPERM;
349     }
350     tempu = FindByID(tt,aid);
351     if (!tempu) { 
352         ubik_AbortTrans(tt);
353         return PRNOENT;
354     }
355     bzero(&uentry,sizeof(uentry));
356     code = pr_ReadEntry(tt,0,tempu,&uentry);
357     if (code != 0)  {
358         ubik_AbortTrans(tt);
359         return code;
360     }
361     /* we don't allow groups as members of groups at present */
362     if (uentry.flags & PRGRP) {
363         ubik_AbortTrans(tt);
364         return PRNOTUSER;
365     }
366     tempg = FindByID(tt,gid);
367     if (!tempg) {
368         ubik_AbortTrans(tt);
369         return PRNOENT;
370     }
371     code = pr_ReadEntry(tt,0,tempg,&tentry);
372     if (code != 0) {
373         ubik_AbortTrans(tt);
374         return code;
375     }
376     /* make sure that this is a group */
377     if (!(tentry.flags & PRGRP)) {
378         ubik_AbortTrans(tt);
379         return PRNOTGROUP;
380     }
381     if (!AccessOK (tt, cid, &tentry, PRP_ADD_MEM, PRP_ADD_ANY)) {
382         ubik_AbortTrans(tt);
383         return PRPERM;
384     }
385     
386     code = AddToEntry (tt, &tentry, tempg, aid);
387     if (code != PRSUCCESS) {
388         ubik_AbortTrans(tt);
389         return code;
390     }
391     /* now, modify the user's entry as well */
392     code = AddToEntry (tt, &uentry, tempu, gid);
393     if (code != PRSUCCESS) {
394         ubik_AbortTrans(tt);
395         return code;
396     }
397     code = ubik_EndTrans(tt);
398     if (code) return code;
399     return PRSUCCESS;
400 }
401
402 long PR_NameToID (call, aname, aid)
403   struct rx_call *call;
404   namelist *aname;
405   idlist *aid;
406 {
407     register long code;
408     struct ubik_trans *tt;
409     long i;
410     int size;
411     int count = 0;
412
413     /* must do this first for RPC stub to work */
414     size = aname->namelist_len;
415     if ((size <= 0) || (size > PR_MAXLIST)) size = 0;
416     aid->idlist_val = (long *)malloc(size*sizeof(long));
417     aid->idlist_len = 0;
418     if (aname->namelist_len == 0) return 0;
419     if (size == 0) return PRTOOMANY;    /* rxgen will probably handle this */
420
421     code = Initdb();
422     if (code != PRSUCCESS) return code;
423     code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt);
424     if (code) return code;
425     code = ubik_SetLock(tt,1,1,LOCKREAD);
426     if (code) {
427         ubik_AbortTrans(tt);
428         return code;
429     }
430     for (i=0;i<aname->namelist_len;i++) {
431         code = NameToID(tt,aname->namelist_val[i],&aid->idlist_val[i]);
432         if (code != PRSUCCESS) aid->idlist_val[i] = ANONYMOUSID;
433         if (count++ > 50) IOMGR_Poll(), count = 0;
434     }
435     aid->idlist_len = aname->namelist_len;
436
437     code = ubik_EndTrans(tt);
438     if (code) return code;
439     return PRSUCCESS;
440 }
441
442 long PR_IDToName (call, aid, aname)
443   struct rx_call *call;
444   idlist *aid;
445   namelist *aname;
446 {
447     register long code;
448     struct ubik_trans *tt;
449     long i;
450     int size;
451     int count = 0;
452
453     /* leave this first for rpc stub */
454     size = aid->idlist_len;
455     if ((size <= 0) || (size > PR_MAXLIST)) size = 0;
456     aname->namelist_val = (prname *)malloc(size*PR_MAXNAMELEN);
457     aname->namelist_len = 0;
458     if (aid->idlist_len == 0) return 0;
459     if (size == 0) return PRTOOMANY;    /* rxgen will probably handle this */
460
461     code = Initdb();
462     if (code != PRSUCCESS) return code;
463     code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt);
464     if (code) return code;
465     code = ubik_SetLock(tt,1,1,LOCKREAD);
466     if (code) {
467         ubik_AbortTrans(tt);
468         return code;
469     }
470     for (i=0;i<aid->idlist_len;i++) {
471         /* interface won't allow more than PR_MAXLIST to be sent in */
472         code = IDToName(tt,aid->idlist_val[i],aname->namelist_val[i]);
473         if (code != PRSUCCESS)
474             sprintf(aname->namelist_val[i],"%d",aid->idlist_val[i]);
475         if (count++ > 50) IOMGR_Poll(), count = 0;
476     }
477     aname->namelist_len = aid->idlist_len;
478
479     code = ubik_EndTrans(tt);
480     if (code) return code;
481     return PRSUCCESS;
482 }
483
484 long PR_Delete (call, aid)
485   struct rx_call *call;
486   long aid;
487 {
488     register long code;
489     struct ubik_trans *tt;
490     long cid;
491     struct prentry tentry;
492     long loc, nptr;
493     int count;
494
495     code = Initdb();
496     if (code) return code;
497     if (code != PRSUCCESS) return code;
498     if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID ||
499         aid == ANONYMOUSID) return PRPERM;
500     code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
501     if (code) return code;
502     code = ubik_SetLock(tt,1,1,LOCKWRITE);
503     if (code) {
504       abort:
505         ubik_AbortTrans(tt);
506         return code;
507     }
508     code = WhoIsThis(call,tt,&cid);
509     if (code) {
510         ubik_AbortTrans(tt);
511         return PRPERM;
512     }
513
514     /* Read in entry to be deleted */
515     loc = FindByID (tt, aid);
516     if (loc == 0) {code = PRNOENT; goto abort;}
517     code = pr_ReadEntry (tt, 0, loc, &tentry);
518     if (code) {code = PRDBFAIL; goto abort;}
519
520     /* Do some access checking */
521     if (tentry.owner != cid &&
522         !IsAMemberOf (tt, cid, SYSADMINID) &&
523         !IsAMemberOf (tt, cid, tentry.owner) && !pr_noAuth)
524         {code = PRPERM; goto abort;}
525
526     /* Delete each continuation block as a separate transaction so that no one
527      * transaction become to large to complete. */
528     nptr = tentry.next;
529     while (nptr != NULL) {
530         struct contentry centry;
531         int i;
532
533         code = pr_ReadCoEntry(tt, 0, nptr, &centry);
534         if (code != 0) {code = PRDBFAIL; goto abort;}
535         for (i=0;i<COSIZE;i++) {
536             if (centry.entries[i] == PRBADID) continue;
537             if (centry.entries[i] == 0) break;
538             code = RemoveFromEntry (tt, aid, centry.entries[i]);
539             if (code) goto abort;
540             tentry.count--;             /* maintain count */
541             if ((i&3) == 0) IOMGR_Poll();
542         }
543         tentry.next = centry.next;      /* thread out this block */
544         code = FreeBlock (tt, nptr);    /* free continuation block */
545         if (code) goto abort;
546         code = pr_WriteEntry (tt, 0, loc, &tentry); /* update main entry */
547         if (code) goto abort;
548
549         /* end this trans and start a new one */
550         code = ubik_EndTrans(tt);
551         if (code) return code;
552         IOMGR_Poll();                   /* just to keep the connection alive */
553         code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
554         if (code) return code;
555         code = ubik_SetLock(tt,1,1,LOCKWRITE);
556         if (code) goto abort;
557
558         /* re-read entry to get consistent uptodate info */
559         loc = FindByID (tt, aid);
560         if (loc == 0) {code = PRNOENT; goto abort;}
561         code = pr_ReadEntry (tt, 0, loc, &tentry);
562         if (code) {code = PRDBFAIL; goto abort;}
563
564         nptr = tentry.next;
565     }
566
567     /* Then move the owned chain, except possibly ourself to the orphan list.
568      * Because this list can be very long and so exceed the size of a ubik
569      * transaction, we start a new transaction every 50 entries. */
570     count = 0;
571     nptr = tentry.owned;
572     while (nptr != NULL) {
573         struct prentry nentry;
574
575         code = pr_ReadEntry (tt, 0, nptr, &nentry);
576         if (code) {code = PRDBFAIL; goto abort;}
577         nptr = tentry.owned = nentry.nextOwned; /* thread out */
578         
579         if (nentry.id != tentry.id) {   /* don't add us to orphan chain! */
580             code = AddToOrphan (tt, nentry.id);
581             if (code) goto abort;
582             count++;
583             if ((count & 3) == 0) IOMGR_Poll();
584         }
585         if (count < 50) continue;
586         code = pr_WriteEntry (tt, 0, loc, &tentry); /* update main entry */
587         if (code) goto abort;
588
589         /* end this trans and start a new one */
590         code = ubik_EndTrans(tt);
591         if (code) return code;
592         IOMGR_Poll();                   /* just to keep the connection alive */
593         code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
594         if (code) return code;
595         code = ubik_SetLock(tt,1,1,LOCKWRITE);
596         if (code) goto abort;
597
598         /* re-read entry to get consistent uptodate info */
599         loc = FindByID (tt, aid);
600         if (loc == 0) {code = PRNOENT; goto abort;}
601         code = pr_ReadEntry (tt, 0, loc, &tentry);
602         if (code) {code = PRDBFAIL; goto abort;}
603
604         nptr = tentry.owned;
605     }
606
607     /* now do what's left of the deletion stuff */
608     code = DeleteEntry (tt, &tentry, loc);
609     if (code != PRSUCCESS) {
610         ubik_AbortTrans(tt);
611         return code;
612     }
613     code = ubik_EndTrans(tt);
614     if (code) return code;
615     return PRSUCCESS;
616 }
617
618 PR_RemoveFromGroup(call,aid,gid)
619 struct rx_call *call;
620 long aid;
621 long gid;
622 {
623     register long code;
624     struct ubik_trans *tt;
625     long tempu;
626     long tempg;
627     struct prentry uentry;
628     struct prentry gentry;
629     long cid;
630
631     code = Initdb();
632     if (code != PRSUCCESS) return code;
633     code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
634     if (code) return code;
635     code = ubik_SetLock(tt,1,1,LOCKWRITE);
636     if (code) {
637         ubik_AbortTrans(tt);
638         return code;
639     }
640     code = WhoIsThis(call,tt,&cid);
641     if (code) {
642         ubik_AbortTrans(tt);
643         return PRPERM;
644     }
645     tempu = FindByID(tt,aid);
646     if (!tempu) { 
647         ubik_AbortTrans(tt);
648         return PRNOENT;
649     }
650     tempg = FindByID(tt,gid);
651     if (!tempg) {
652         ubik_AbortTrans(tt);
653         return PRNOENT;
654     }
655     bzero(&uentry,sizeof(uentry));
656     bzero(&gentry,sizeof(gentry));
657     code = pr_ReadEntry(tt,0,tempu,&uentry);
658     if (code != 0) {
659         ubik_AbortTrans(tt);
660         return code;
661     }
662     code = pr_ReadEntry(tt,0,tempg,&gentry);
663     if (code != 0) {
664         ubik_AbortTrans(tt);
665         return code;
666     }
667     if (!(gentry.flags & PRGRP)) {
668         ubik_AbortTrans(tt);
669         return PRNOTGROUP;
670     }
671     if (uentry.flags & PRGRP) {
672         ubik_AbortTrans(tt);
673         return PRNOTUSER;
674     }
675     if (!AccessOK (tt, cid, &gentry, PRP_REMOVE_MEM, 0)) {
676         ubik_AbortTrans(tt);
677         return PRPERM;
678     }
679     code = RemoveFromEntry(tt,aid,gid);
680     if (code != PRSUCCESS) {
681         ubik_AbortTrans(tt);
682         return code;
683     }
684     code = RemoveFromEntry(tt,gid,aid);
685     if (code != PRSUCCESS) {
686         ubik_AbortTrans(tt);
687         return code;
688     }
689     code = ubik_EndTrans(tt);
690     if (code) return code;
691     return PRSUCCESS;
692 }
693
694 long PR_GetCPS (call, aid, alist, over)
695   struct rx_call *call;
696   long aid;
697   prlist *alist;
698   long *over;
699 {
700     register long code;
701     struct ubik_trans *tt;
702     long temp;
703     long cid;
704     struct prentry tentry;
705
706     alist->prlist_len = 0;
707     alist->prlist_val = (long *) 0;
708     code = Initdb();
709     if (code != PRSUCCESS) goto done;
710     code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt);
711     if (code) goto done;
712     code = ubik_SetLock(tt,1,1,LOCKREAD);
713     if (code) {
714       abort:
715         ubik_AbortTrans(tt);
716         goto done;
717     }
718
719     temp = FindByID (tt, aid);
720     if (!temp) {code = PRNOENT; goto abort;}
721     code = pr_ReadEntry (tt, 0, temp, &tentry);
722     if (code) goto abort;
723
724     /* afs does authenticate now */
725     code = WhoIsThis (call, tt, &cid);
726     if (code || !AccessOK (tt, cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY)) {
727         code = PRPERM;
728         goto abort;
729     }
730         
731     code = GetList(tt, &tentry, alist, 1);
732     *over = 0;
733     if (code == PRTOOMANY) *over = 1;
734     else if (code != PRSUCCESS) {
735         ubik_AbortTrans(tt);
736         goto done;
737     }
738
739     code = ubik_EndTrans(tt);
740
741 done:
742     /* return code, making sure that prlist_val points to malloc'd memory */
743     if (!alist->prlist_val)
744         alist->prlist_val = (long *) malloc(0); /* make xdr stub happy */
745     return code;
746 }
747
748 PR_ListMax(call,uid,gid)
749 struct rx_call *call;
750 long *uid;
751 long *gid;
752 {
753     register long code;
754     struct ubik_trans *tt;
755
756     code = Initdb();
757     if (code != PRSUCCESS) return code;
758     code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt);
759     if (code) return code;
760     code = ubik_SetLock(tt,1,1,LOCKREAD);
761     if (code) {
762         ubik_AbortTrans(tt);
763         return code;
764     }
765     code = GetMax(tt,uid,gid);
766     if (code != PRSUCCESS) {
767         ubik_AbortTrans(tt);
768         return code;
769     }
770     code = ubik_EndTrans(tt);
771     if (code) return code;
772     return PRSUCCESS;
773 }
774
775 PR_SetMax(call,aid,gflag)
776 struct rx_call *call;
777 long aid;
778 long gflag;
779 {
780     register long code;
781     struct ubik_trans *tt;
782     long cid;
783
784     code = Initdb();
785     if (code != PRSUCCESS) return code;
786     code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
787     if (code) return code;
788     code = ubik_SetLock(tt,1,1,LOCKWRITE);
789     if (code) {
790         ubik_AbortTrans(tt);
791         return code;
792     }
793     code = WhoIsThis(call,tt,&cid);
794     if (code) {
795         ubik_AbortTrans(tt);
796         return PRPERM;
797     }
798     if (!AccessOK (tt, cid, 0, 0, 0)) {
799         ubik_AbortTrans(tt);
800         return PRPERM;
801     }
802     if (((gflag & PRGRP) && (aid > 0)) ||
803         (!(gflag & PRGRP) && (aid < 0))) {
804         code = PRBADARG;
805         goto abort;
806     }
807
808     code = SetMax(tt,aid,gflag);
809     if (code != PRSUCCESS) {
810       abort:
811         ubik_AbortTrans(tt);
812         return code;
813     }
814     code = ubik_EndTrans(tt);
815     if (code) return code;
816     return PRSUCCESS;
817 }
818
819 PR_ListEntry(call,aid,aentry)
820 struct rx_call *call;
821 long aid;
822 struct prcheckentry *aentry;
823 {
824     register long code;
825     struct ubik_trans *tt;
826     long cid;
827     long temp;
828     struct prentry tentry;
829
830     code = Initdb();
831     if (code != PRSUCCESS) return code;
832     code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt);
833     if (code) return code;
834     code = ubik_SetLock(tt,1,1,LOCKREAD);
835     if (code) {
836         ubik_AbortTrans(tt);
837         return code;
838     }
839     code = WhoIsThis(call,tt,&cid);
840     if (code) {
841       perm:
842         ubik_AbortTrans(tt);
843         return PRPERM;
844     }
845     temp = FindByID(tt,aid);
846     if (!temp) { 
847         ubik_AbortTrans(tt);
848         return PRNOENT;
849     }
850     code = pr_ReadEntry(tt, 0, temp, &tentry);
851     if (code != 0) {
852         ubik_AbortTrans(tt);
853         return code;
854     } 
855     if (!AccessOK (tt, cid, &tentry, PRP_STATUS_MEM, PRP_STATUS_ANY))
856         goto perm;
857
858     aentry->flags = tentry.flags >> PRIVATE_SHIFT;
859     if (aentry->flags == 0)
860         if (tentry.flags & PRGRP)
861             aentry->flags = PRP_GROUP_DEFAULT >> PRIVATE_SHIFT;
862         else aentry->flags = PRP_USER_DEFAULT >> PRIVATE_SHIFT;
863     aentry->owner = tentry.owner;
864     aentry->id = tentry.id;
865     strncpy(aentry->name,tentry.name,PR_MAXNAMELEN);
866     aentry->creator = tentry.creator;
867     aentry->ngroups = tentry.ngroups;
868     aentry->nusers = tentry.nusers;
869     aentry->count = tentry.count;
870     bzero (aentry->reserved, sizeof(aentry->reserved));
871     code = ubik_EndTrans(tt);
872     if (code) return code;
873     return PRSUCCESS;
874 }
875
876 PR_ChangeEntry(call,aid,name,oid,newid)
877 struct rx_call *call;
878 long aid;
879 char *name;
880 long oid;
881 long newid;
882 {
883     register long code;
884     struct ubik_trans *tt;
885     long pos;
886     long cid;
887
888     stolower(name);
889     code = Initdb();
890     if (code) return code;
891     if (aid == ANYUSERID || aid == AUTHUSERID || aid == ANONYMOUSID ||
892         aid == SYSADMINID) return PRPERM;
893     if (code != PRSUCCESS) return code;
894     code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
895     if (code) return code;
896     code = ubik_SetLock(tt,1,1,LOCKWRITE);
897     if (code) {
898         ubik_AbortTrans(tt);
899         return code;
900     }
901     code = WhoIsThis(call,tt,&cid);
902     if (code) {
903         ubik_AbortTrans(tt);
904         return PRPERM;
905     }
906     pos = FindByID(tt,aid);
907     if (!pos) { 
908         ubik_AbortTrans(tt);
909         return PRNOENT;
910     }
911     /* protection check in changeentry */
912     code = ChangeEntry(tt,aid,cid,name,oid,newid);
913     if (code != PRSUCCESS) {
914         ubik_AbortTrans(tt);
915         return code;
916     }
917     code = ubik_EndTrans(tt);
918     return code;
919 }
920
921 PR_SetFieldsEntry(call, id, mask, flags, ngroups, nusers, spare1, spare2)
922   struct rx_call *call;
923   long id;
924   long mask;                            /* specify which fields to update */
925   long flags, ngroups, nusers;
926   long spare1, spare2;
927 {
928     register long code;
929     struct ubik_trans *tt;
930     long pos;
931     long cid;
932     struct prentry tentry;
933     long tflags;
934
935     if (mask == 0) return 0;            /* no-op */
936     code = Initdb();
937     if (code) return code;
938     if (id == ANYUSERID || id == AUTHUSERID || id == ANONYMOUSID)
939         return PRPERM;
940     if (code != PRSUCCESS) return code;
941     code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
942     if (code) return code;
943     code = ubik_SetLock(tt,1,1,LOCKWRITE);
944     if (code) {
945       abort:
946         ubik_AbortTrans(tt);
947         return code;
948     }
949     code = WhoIsThis(call,tt,&cid);
950     if (code) {
951       perm:
952         ubik_AbortTrans(tt);
953         return PRPERM;
954     }
955     pos = FindByID(tt,id);
956     if (!pos) { 
957         ubik_AbortTrans(tt);
958         return PRNOENT;
959     }
960     code = pr_ReadEntry (tt, 0, pos, &tentry);
961     if (code) goto abort;
962     tflags = tentry.flags;
963
964     if (mask & (PR_SF_NGROUPS | PR_SF_NUSERS)) {
965         if (!AccessOK (tt, cid, 0, 0, 0)) goto perm;
966         if ((tflags & PRQUOTA) == 0) {  /* default if only setting one */
967             tentry.ngroups = tentry.nusers = 20;
968         }
969     } else {
970         if (!AccessOK (tt, cid, &tentry, 0, 0)) goto perm;
971     }
972
973     if (mask & 0xffff) {                /* if setting flag bits */
974         long flagsMask = mask & 0xffff;
975         tflags &= ~(flagsMask << PRIVATE_SHIFT);
976         tflags |= (flags & flagsMask) << PRIVATE_SHIFT;
977         tflags |= PRACCESS;
978     }
979
980     if (mask & PR_SF_NGROUPS) {         /* setting group limit */
981         if (ngroups < 0) {code = PRBADARG; goto abort;}
982         tentry.ngroups = ngroups;
983         tflags |= PRQUOTA;
984     }
985
986     if (mask & PR_SF_NUSERS) {          /* setting foreign user limit */
987         if (nusers < 0) {code = PRBADARG; goto abort;}
988         tentry.nusers = nusers;
989         tflags |= PRQUOTA;
990     }
991     tentry.flags = tflags;
992
993     code = pr_WriteEntry (tt, 0, pos, &tentry);
994     if (code) goto abort;
995
996     code = ubik_EndTrans(tt);
997     return code;
998 }
999
1000 long PR_ListElements (call, aid, alist, over)
1001   struct rx_call *call;
1002   long aid;
1003   prlist *alist;
1004   long *over;
1005 {
1006     register long code;
1007     struct ubik_trans *tt;
1008     long cid;
1009     long temp;
1010     struct prentry tentry;
1011
1012     alist->prlist_len = 0;
1013     alist->prlist_val = (long *) 0;
1014
1015     code = Initdb();
1016     if (code != PRSUCCESS) goto done;
1017     code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt);
1018     if (code) goto done;
1019     code = ubik_SetLock(tt,1,1,LOCKREAD);
1020     if (code) {
1021       abort:
1022         ubik_AbortTrans(tt);
1023         goto done;
1024     }
1025     code = WhoIsThis(call,tt,&cid);
1026     if (code) {
1027       perm:
1028         code = PRPERM;
1029         ubik_AbortTrans(tt);
1030         goto done;
1031     }
1032
1033     temp = FindByID(tt,aid);
1034     if (!temp) {code = PRNOENT; goto abort;}
1035     code = pr_ReadEntry (tt, 0, temp, &tentry);
1036     if (code) goto abort;
1037     if (!AccessOK (tt, cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1038         goto perm;
1039         
1040     code = GetList (tt, &tentry, alist, 0);
1041     *over = 0;
1042     if (code == PRTOOMANY) *over = 1;
1043     else if (code != PRSUCCESS) goto abort;
1044
1045     code = ubik_EndTrans(tt);
1046
1047 done:
1048     if (!alist->prlist_val)
1049         alist->prlist_val = (long *) malloc(0); /* make calling stub happy */
1050     return code;
1051 }
1052
1053 /* List the entries owned by this id.  If the id is zero return the orphans
1054  * list. */
1055
1056 PR_ListOwned (call, aid, alist, over)
1057   struct rx_call *call;
1058   long aid;
1059   prlist *alist;
1060   long *over;
1061 {
1062     register long code;
1063     struct ubik_trans *tt;
1064     long cid;
1065     struct prentry tentry;
1066     long head;
1067
1068     alist->prlist_len = 0;
1069     alist->prlist_val = (long *) 0;
1070
1071     code = Initdb();
1072     if (code != PRSUCCESS) goto done;
1073     code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt);
1074     if (code) goto done;
1075     code = ubik_SetLock(tt,1,1,LOCKREAD);
1076     if (code) {
1077       abort:
1078         ubik_AbortTrans(tt);
1079         goto done;
1080     }
1081     code = WhoIsThis(call,tt,&cid);
1082     if (code) {
1083       perm:
1084         code = PRPERM;
1085         ubik_AbortTrans(tt);
1086         goto done;
1087     }
1088
1089     if (aid) {
1090         long loc = FindByID (tt, aid);
1091         if (loc == 0) { code =  PRNOENT; goto abort; }
1092         code = pr_ReadEntry (tt, 0, loc, &tentry);
1093         if (code) goto abort;
1094 ;
1095         if (!AccessOK (tt, cid, &tentry, -1, PRP_OWNED_ANY)) goto perm;
1096         head = tentry.owned;
1097     } else {
1098         if (!AccessOK (tt, cid, 0, 0, 0)) goto perm;
1099         head = ntohl(cheader.orphan);
1100     }
1101
1102     code = GetOwnedChain (tt, head, alist);
1103     *over = 0;
1104     if (code == PRTOOMANY) *over = 1;
1105     else if (code) goto abort;
1106
1107     code = ubik_EndTrans(tt);
1108
1109 done:
1110     if (!alist->prlist_val)
1111         alist->prlist_val = (long *) malloc(0); /* make calling stub happy */
1112     return code;
1113 }
1114
1115 PR_IsAMemberOf(call,uid,gid,flag)
1116 struct rx_call *call;
1117 long uid;
1118 long gid;
1119 long *flag;
1120 {
1121     register long code;
1122     struct ubik_trans *tt;
1123
1124     code = Initdb();
1125     if (code != PRSUCCESS) return code;
1126     code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt);
1127     if (code) return code;
1128     code = ubik_SetLock(tt,1,1,LOCKREAD);
1129     if (code) {
1130       abort:
1131         ubik_AbortTrans(tt);
1132         return code;
1133     }
1134     {   long cid;
1135         long uloc = FindByID (tt, uid);
1136         long gloc = FindByID (tt, gid);
1137         struct prentry uentry, gentry;
1138
1139         if (!uloc || !gloc) {
1140             code = PRNOENT;
1141             goto abort;
1142         }
1143         code = WhoIsThis(call, tt, &cid);
1144         if (code) {
1145           perm:
1146             code = PRPERM;
1147             goto abort;
1148         }
1149         code = pr_ReadEntry (tt, 0, uloc, &uentry);
1150         if (code) goto abort;
1151         code = pr_ReadEntry (tt, 0, gloc, &gentry);
1152         if (code) goto abort;
1153         if ((uentry.flags & PRGRP) || !(gentry.flags & PRGRP)) {
1154             code = PRBADARG;
1155             goto abort;
1156         }
1157         if (!AccessOK (tt, cid, &uentry, 0, PRP_MEMBER_ANY) &&
1158             !AccessOK (tt, cid, &gentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1159             goto perm;
1160     }
1161         
1162     *flag = IsAMemberOf(tt,uid,gid);
1163     code = ubik_EndTrans(tt);
1164     return code;
1165 }
1166
1167
1168 static stolower(s)
1169 register char *s;
1170 {
1171     register int tc;
1172     while (tc = *s) {
1173         if (isupper(tc)) *s = tolower(tc);
1174         s++;
1175     }
1176 }
1177
1178 #if defined(CROSS_CELL) && !defined(WhoIsThisWithName)
1179 static long WhoIsThisWithName(acall, at, aid, aname)
1180     struct rx_call *acall;
1181     struct ubik_trans *at;
1182     long *aid;
1183     char *aname;
1184 {
1185     /* aid is set to the identity of the caller, if known, else ANONYMOUSID */
1186     /* returns -1 and sets aid to ANONYMOUSID on any failure */
1187
1188     register struct rx_connection *tconn;
1189     register long code;
1190     char tcell[MAXKTCREALMLEN];
1191     char name[MAXKTCNAMELEN];
1192     char inst[MAXKTCNAMELEN];
1193     int  ilen;
1194     char vname[256];
1195
1196     *aid = SYSADMINID;
1197     return 0;
1198     
1199     *aid = ANONYMOUSID;
1200     tconn = rx_ConnectionOf(acall);
1201     code = rx_SecurityClassOf(tconn);
1202     if (code == 0) return 0;
1203     else if (code == 1) {                       /* vab class */
1204         goto done;                              /* no longer supported */
1205     }
1206     else if (code == 2) {                       /* kad class */
1207
1208         int clen;
1209         extern char *pr_realmName;
1210
1211         if (code = rxkad_GetServerInfo
1212             (acall->conn, (long *)0, 0          /*was &exp*/,
1213              name, inst, tcell, (long *)0))
1214             goto done;
1215         strncpy (vname, name, sizeof(vname));
1216         if (ilen = strlen (inst)) {
1217             if (strlen(vname) + 1 + ilen >= sizeof(vname)) goto done;
1218             strcat (vname, ".");
1219             strcat (vname, inst);
1220         }
1221         if (clen = strlen (tcell)) {
1222             if (!afsconf_LocalRealm(prdir, tcell)) {
1223                 if (strlen(vname) + 1 + clen >= sizeof(vname)) goto done;
1224                 strcat(vname,"@");
1225                 strcat(vname,tcell);
1226                 lcstring(vname, vname, sizeof(vname));
1227                 code = NameToID(at,vname,aid);
1228                 strcpy(aname,vname);
1229                 return 2;
1230             }
1231         }
1232
1233         if (strcmp (AUTH_SUPERUSER, vname) == 0)
1234             /* special case for the fileserver */
1235             *aid = SYSADMINID;
1236         else {
1237             lcstring(vname, vname, sizeof(vname));
1238             code = NameToID(at,vname,aid);
1239         }
1240     }
1241 done:
1242     if (code && !pr_noAuth) return -1;
1243     return 0;
1244 }
1245 #endif
This page took 0.178632 seconds and 5 git commands to generate.