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