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