death-to-permit-xprt-h-20010327
[openafs.git] / src / ptserver / ptuser.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #if defined(UKERNEL)
11 #include "../afs/param.h"
12 #include "../afs/sysincludes.h"
13 #include "../afs/afs_usrops.h"
14 #include "../afs/afsincludes.h"
15 #include "../afs/stds.h"
16 #include "../rx/rx.h"
17 #include "../rx/xdr.h"
18 #include "../rx/rxkad.h"
19 #include "../afs/auth.h"
20 #include "../afs/cellconfig.h"
21 #include "../afs/afsutil.h"
22
23 #include "../afs/ptclient.h"
24 #include "../afs/pterror.h"
25
26 #else /* defined(UKERNEL) */
27 #include <afs/param.h>
28 #include <afs/stds.h>
29 #include <ctype.h>
30 #include <sys/types.h>
31 #ifdef AFS_NT40_ENV 
32 #include <winsock2.h>
33 #else
34 #include <netinet/in.h>
35 #endif
36 #include <stdio.h>
37 #include <rx/rx.h>
38 #include <rx/xdr.h>
39 #include <rx/rxkad.h>
40 #include <afs/auth.h>
41 #include <afs/cellconfig.h>
42 #include <afs/afsutil.h>
43 #include "ptclient.h"
44 #include "pterror.h"
45 #endif /* defined(UKERNEL) */
46
47
48 struct ubik_client *pruclient = 0;
49 static afs_int32 lastLevel;                     /* security level pruclient, if any */
50
51 static char *whoami = "libprot";
52
53 afs_int32 pr_Initialize (secLevel, confDir, cell)
54   IN afs_int32 secLevel;
55   IN char *confDir;
56   IN char *cell;
57 {
58     afs_int32 code;
59     struct rx_connection *serverconns[MAXSERVERS];
60     struct rx_securityClass *sc[3];
61     static struct afsconf_dir *tdir = 0; /* only do this once */
62     static char tconfDir[100];
63     struct ktc_token ttoken;
64     afs_int32 scIndex;
65     static struct afsconf_cell info;
66     afs_int32 i;
67     char cellstr[64];
68
69     initialize_pt_error_table();
70     initialize_rxk_error_table();
71     initialize_acfg_error_table();
72     initialize_ktc_error_table();
73 /*
74     initialize_lwp_error_table();
75     initialize_rx_error_table();
76 */
77
78     if (strcmp(confDir, tconfDir)) {
79         /*
80          * Different conf dir; force re-evaluation.
81          */
82         tdir = (struct afsconf_dir *)0;
83         pruclient = (struct ubik_client *)0;
84     }
85     if (tdir == 0) {
86         strncpy(tconfDir, confDir, sizeof(tconfDir));
87 #if defined(UKERNEL)
88         tdir = afs_cdir;
89         if (!cell) {
90             cell = afs_LclCellName;
91         }
92 #else /* defined(UKERNEL) */  
93         tdir = afsconf_Open(confDir);
94         if (!tdir) {
95             fprintf(stderr,
96                     "libprot: Could not open configuration directory: %s.\n",
97                     confDir);
98             return -1;
99         }
100
101         if (!cell) {
102            code = afsconf_GetLocalCell(tdir, cellstr, sizeof(cellstr));
103            if (code) {
104               fprintf(stderr,
105                       "vos: can't get local cell name - check %s/%s\n",
106                       confDir, AFSDIR_THISCELL_FILE);
107               exit(1);
108            }
109            cell = cellstr;
110         }
111 #endif /* defined(UKERNEL) */  
112
113         code = afsconf_GetCellInfo(tdir,cell,"afsprot",&info);
114         if (code) {
115             fprintf(stderr, "libprot: Could not locate cell %s in %s/%s\n",
116                     cell, confDir, AFSDIR_CELLSERVDB_FILE);
117             return code;
118         }
119     }
120
121     /* If we already have a client and it is at the security level we
122      * want, don't get a new one. Unless the security level is 2 in
123      * which case we will get one (and re-read the key file).
124      */
125     if (pruclient && (lastLevel == secLevel) && (secLevel != 2))
126        return 0;
127     
128     code = rx_Init(0);
129     if (code) {
130         fprintf(stderr,"libprot:  Could not initialize rx.\n");
131         return code;
132     }
133
134     scIndex = secLevel;
135     sc[0] = 0;
136     sc[1] = 0;
137     sc[2] = 0;
138     /* Most callers use secLevel==1, however, the fileserver uses secLevel==2
139      * to force use of the KeyFile.  secLevel == 0 implies -noauth was
140      * specified. */
141     if ((secLevel == 2) && (afsconf_GetLatestKey (tdir, 0,0) == 0)) {
142         /* If secLevel is two assume we're on a file server and use
143          * ClientAuthSecure if possible. */
144         code = afsconf_ClientAuthSecure (tdir, &sc[2], &scIndex);
145         if (code) scIndex = 0;          /* use noauth */
146         if (scIndex != 2)
147             /* if there was a problem, an unauthenticated conn is returned */
148             sc[scIndex] = sc[2];
149     }
150     else if (secLevel > 0) {
151         struct ktc_principal sname;
152         strcpy(sname.cell,info.name);
153         sname.instance[0] = 0;
154         strcpy(sname.name, "afs");
155         code = ktc_GetToken(&sname,&ttoken, sizeof(ttoken), (char *)0);
156         if (code) scIndex = 0;
157         else {
158             if (ttoken.kvno >= 0 && ttoken.kvno <= 255)
159                 /* this is a kerberos ticket, set scIndex accordingly */
160                 scIndex = 2;
161             else {
162                 fprintf (stderr,
163                          "libprot: funny kvno (%d) in ticket, proceeding\n",
164                          ttoken.kvno);
165                 scIndex = 2;
166             }
167             sc[2] = (struct rx_securityClass *) rxkad_NewClientSecurityObject
168                 (rxkad_clear, &ttoken.sessionKey, ttoken.kvno,
169                  ttoken.ticketLen, ttoken.ticket);
170         }
171     }
172     if (scIndex == 1) return PRBADARG;
173     if ((scIndex == 0) && (sc[0] == 0))
174         sc[0] = (struct rx_securityClass *) rxnull_NewClientSecurityObject();
175     if ((scIndex == 0) && (secLevel != 0))
176         com_err (whoami, code,
177                  "Could not get afs tokens, running unauthenticated.");
178
179     bzero (serverconns, sizeof(serverconns)); /* terminate list!!! */
180     for (i = 0;i<info.numServers;i++) 
181         serverconns[i] = rx_NewConnection
182             (info.hostAddr[i].sin_addr.s_addr, info.hostAddr[i].sin_port,
183              PRSRV, sc[scIndex], scIndex);
184
185     code = ubik_ClientInit(serverconns, &pruclient);
186     if (code) {
187         com_err (whoami, code, "ubik client init failed.");
188         return code;
189     }
190     lastLevel = scIndex;
191
192     code = rxs_Release (sc[scIndex]);
193     return code;
194 }
195
196
197 pr_End()
198 {
199    int code = 0;
200
201     if (pruclient) {
202         code = ubik_ClientDestroy (pruclient);
203         pruclient = 0;
204     }
205    return code;
206 }
207
208
209
210 pr_CreateUser(name,id)
211 char name[PR_MAXNAMELEN];
212 afs_int32 *id;
213 {
214     register afs_int32 code;
215
216     stolower(name);
217     if (*id) {
218         code = ubik_Call(PR_INewEntry,pruclient,0,name,*id,0);
219         return code;
220     }
221     else {
222         code = ubik_Call(PR_NewEntry, pruclient, 0, name,0,0,id);
223         return code;
224     }
225     
226 }
227
228 pr_CreateGroup(name,owner, id)
229 char name[PR_MAXNAMELEN];
230 char owner[PR_MAXNAMELEN];
231 afs_int32 *id;
232 {
233     register afs_int32 code;
234     afs_int32 oid = 0;
235     afs_int32 flags = 0;
236     
237     stolower(name);
238     if (owner) {
239         code = pr_SNameToId(owner,&oid);
240         if (code) return code;
241         if (oid == ANONYMOUSID) return PRNOENT;
242     }
243     flags |= PRGRP;
244     if (*id) {
245         code = ubik_Call(PR_INewEntry,pruclient,0,name,*id,oid);
246         return code;
247     }
248     else {
249         code = ubik_Call(PR_NewEntry,pruclient, 0, name,flags,oid,id);
250         return code;
251     }
252 }
253
254 pr_Delete(name)
255 char *name;
256 {
257     register afs_int32 code;
258     afs_int32 id;
259     
260     stolower(name);
261     code = pr_SNameToId(name,&id);
262     if (code) return code;
263     if (id == ANONYMOUSID) return PRNOENT;
264     code = ubik_Call(PR_Delete,pruclient,0,id);
265     return code;
266 }
267
268 pr_DeleteByID(id)
269 afs_int32 id;
270 {
271     register afs_int32 code;
272
273     code = ubik_Call(PR_Delete,pruclient,0,id);
274     return code;
275 }
276
277 pr_AddToGroup(user,group)
278 char *user;
279 char *group;
280 {
281     register afs_int32 code;
282     namelist lnames;
283     idlist lids;
284
285     lnames.namelist_len = 2;
286     lnames.namelist_val = (prname *)malloc(2*PR_MAXNAMELEN);
287     strncpy(lnames.namelist_val[0],user,PR_MAXNAMELEN);
288     strncpy(lnames.namelist_val[1],group,PR_MAXNAMELEN);
289     lids.idlist_val = 0;
290     lids.idlist_len = 0;
291     code = pr_NameToId(&lnames,&lids);
292     if (code) goto done;
293     /* if here, still could be missing an entry */
294     if (lids.idlist_val[0] == ANONYMOUSID || lids.idlist_val[1] == ANONYMOUSID) {
295         code = PRNOENT;
296         goto done;
297     }
298     code = ubik_Call(PR_AddToGroup, pruclient, 0, lids.idlist_val[0], lids.idlist_val[1]);
299   done:
300     if (lnames.namelist_val) free(lnames.namelist_val);
301     if (lids.idlist_val) free(lids.idlist_val);
302     return code;
303 }
304
305 pr_RemoveUserFromGroup(user,group)
306 char *user;
307 char *group;
308 {
309     register afs_int32 code;
310     namelist lnames;
311     idlist lids;
312
313     lnames.namelist_len = 2;
314     lnames.namelist_val = (prname *)malloc(2*PR_MAXNAMELEN);
315     strncpy(lnames.namelist_val[0],user,PR_MAXNAMELEN);
316     strncpy(lnames.namelist_val[1],group,PR_MAXNAMELEN);
317     lids.idlist_val = 0;
318     lids.idlist_len = 0;
319     code = pr_NameToId(&lnames,&lids);
320     if (code) goto done;
321
322     if (lids.idlist_val[0] == ANONYMOUSID || lids.idlist_val[1] == ANONYMOUSID) {
323         code = PRNOENT;
324         goto done;
325     }
326     code = ubik_Call(PR_RemoveFromGroup, pruclient, 0, lids.idlist_val[0], lids.idlist_val[1]);
327 done:
328     if (lnames.namelist_val) free(lnames.namelist_val);
329     if (lids.idlist_val) free(lids.idlist_val);
330     return code;
331
332 }
333
334 pr_NameToId(names, ids)
335 namelist *names;
336 idlist *ids;
337 {
338     register afs_int32 code;
339     register afs_int32 i;
340
341     for (i=0;i<names->namelist_len;i++)
342         stolower(names->namelist_val[i]);
343     code = ubik_Call(PR_NameToID,pruclient,0,names,ids);
344     return code;
345 }
346
347 pr_SNameToId(name,id)
348 char name[PR_MAXNAMELEN];
349 afs_int32 *id;
350 {
351     namelist lnames;
352     idlist lids;
353     register afs_int32 code;
354
355     lids.idlist_len = 0;
356     lids.idlist_val = 0;
357     lnames.namelist_len = 1;
358     lnames.namelist_val = (prname *)malloc(PR_MAXNAMELEN);
359     stolower(name);
360     strncpy(lnames.namelist_val[0],name,PR_MAXNAMELEN);
361     code = ubik_Call(PR_NameToID,pruclient,0,&lnames,&lids);
362     if (lids.idlist_val) {
363         *id = *lids.idlist_val;
364         free(lids.idlist_val);
365     }
366     if (lnames.namelist_val) free(lnames.namelist_val);
367     return code;
368 }
369     
370
371
372 pr_IdToName(ids,names)
373 idlist *ids;
374 namelist *names;
375 {
376     register afs_int32 code;
377
378     code = ubik_Call(PR_IDToName,pruclient,0,ids,names);
379     return code;
380 }
381
382 pr_SIdToName(id,name)
383 afs_int32 id;
384 char name[PR_MAXNAMELEN];
385 {
386     namelist lnames;
387     idlist lids;
388     register afs_int32 code;
389
390     lids.idlist_len = 1;
391     lids.idlist_val = (afs_int32 *)malloc(sizeof(afs_int32));
392     *lids.idlist_val = id;
393     lnames.namelist_len = 0;
394     lnames.namelist_val = 0;
395     code = ubik_Call(PR_IDToName,pruclient,0,&lids,&lnames);
396     if (lnames.namelist_val) {
397         strncpy(name,lnames.namelist_val[0],PR_MAXNAMELEN);
398         free(lnames.namelist_val);
399     }
400     if (lids.idlist_val) free(lids.idlist_val);
401     return code;
402 }
403     
404         
405
406 pr_GetCPS(id, CPS)
407 afs_int32 id;
408 prlist *CPS;
409 {
410     register afs_int32 code;
411     afs_int32 over;
412
413     over = 0;
414     code = ubik_Call(PR_GetCPS,pruclient,0,id,CPS,&over);
415     if (code != PRSUCCESS) return code;
416     if (over) {
417         /* do something about this, probably make a new call */
418         /* don't forget there's a hard limit in the interface */
419         fprintf (stderr, "membership list for id %d exceeds display limit\n", id);
420     }
421     return 0;
422 }
423
424
425 pr_GetCPS2(id, host, CPS)
426     afs_int32 id;
427     afs_int32 host;
428     prlist *CPS;
429 {
430     register afs_int32 code;
431     afs_int32 over;
432
433     over = 0;
434     code = ubik_Call(PR_GetCPS2,pruclient,0,id,host,CPS,&over);
435     if (code != PRSUCCESS) return code;
436     if (over) {
437         /* do something about this, probably make a new call */
438         /* don't forget there's a hard limit in the interface */
439         fprintf (stderr, "membership list for id %d exceeds display limit\n", id);
440     }
441     return 0;
442 }
443
444 pr_GetHostCPS(host, CPS)
445     afs_int32 host;
446     prlist *CPS;
447 {
448     register afs_int32 code;
449     afs_int32 over;
450
451     over = 0;
452     code = ubik_Call(PR_GetHostCPS,pruclient,0,host,CPS,&over);
453     if (code != PRSUCCESS) return code;
454     if (over) {
455         /* do something about this, probably make a new call */
456         /* don't forget there's a hard limit in the interface */
457         fprintf (stderr, "membership list for host id %d exceeds display limit\n", host);
458     }
459     return 0;
460 }
461
462
463 pr_ListMembers(group,lnames)
464 char *group;
465 namelist *lnames;
466 {
467     register afs_int32 code;
468     afs_int32 gid;
469
470     code = pr_SNameToId(group,&gid);
471     if (code) return code;
472     if (gid == ANONYMOUSID) return PRNOENT;
473     code = pr_IDListMembers(gid, lnames);
474     return code;
475 }
476
477 pr_ListOwned (oid,lnames,moreP)
478   afs_int32 oid;
479   namelist *lnames;
480   afs_int32 *moreP;
481 {
482     register afs_int32 code;
483     prlist alist;
484     idlist *lids;
485
486     alist.prlist_len = 0;
487     alist.prlist_val = 0;
488     code = ubik_Call(PR_ListOwned,pruclient,0,oid,&alist,moreP);
489     if (code) return code;
490     if (*moreP == 1) {
491       /* Remain backwards compatible when moreP was a T/F bit */
492       fprintf (stderr, "membership list for id %d exceeds display limit\n",
493                oid);
494       *moreP = 0;
495     }
496     lids = (idlist *)&alist;
497     code = pr_IdToName(lids,lnames);
498     if (code) return code;
499     if (alist.prlist_val) free(alist.prlist_val);
500     return PRSUCCESS;
501 }
502
503 pr_IDListMembers(gid,lnames)
504 afs_int32 gid;
505 namelist *lnames;
506 {
507     register afs_int32 code;
508     prlist alist;
509     idlist *lids;
510     afs_int32 over;
511
512     alist.prlist_len = 0;
513     alist.prlist_val = 0;
514     code = ubik_Call(PR_ListElements,pruclient,0,gid,&alist,&over);
515     if (code) return code;
516     if (over) {
517        fprintf (stderr, "membership list for id %d exceeds display limit\n", gid);
518     }
519     lids = (idlist *)&alist;
520     code = pr_IdToName(lids,lnames);
521     if (code) return code;
522     if (alist.prlist_val) free(alist.prlist_val);
523     return PRSUCCESS;
524 }
525
526
527 pr_ListEntry(id, aentry)
528   afs_int32 id;
529   struct prcheckentry *aentry;
530 {
531     register afs_int32 code;
532
533     code = ubik_Call (PR_ListEntry, pruclient, 0, id, aentry);
534     return code;
535 }
536
537 afs_int32 pr_ListEntries(flag, startindex, nentries, entries, nextstartindex)
538   afs_int32                startindex;
539   afs_int32                *nentries;
540   struct prlistentries **entries;
541   afs_int32                *nextstartindex;
542 {
543   afs_int32     code;
544   prentries bulkentries;
545
546   *nentries = 0;
547   *entries  = (struct prlistentries *)0;
548   *nextstartindex = -1;
549   bulkentries.prentries_val = 0;
550   bulkentries.prentries_len = 0;
551
552   code = ubik_Call(PR_ListEntries, pruclient, 0,
553                    flag, startindex, &bulkentries, nextstartindex);
554   *nentries = bulkentries.prentries_len;
555   *entries  = bulkentries.prentries_val;
556   return code;
557 }
558
559 pr_CheckEntryByName(name,id,owner,creator)
560 char *name;
561 afs_int32 *id;
562 char *owner;
563 char *creator;
564 {
565     /* struct prcheckentry returns other things, which aren't useful to show at this time. */
566     register afs_int32 code;
567     struct prcheckentry aentry;
568
569     code = pr_SNameToId(name,id);
570     if (code) return code;
571     if (*id == ANONYMOUSID) return PRNOENT;
572     code = ubik_Call(PR_ListEntry,pruclient,0,*id,&aentry);
573     if (code) return code;
574     /* this should be done in one RPC, but I'm lazy. */
575     code = pr_SIdToName(aentry.owner,owner);
576     if (code) return code;
577     code = pr_SIdToName(aentry.creator,creator);
578     if (code) return code;
579     return PRSUCCESS;
580 }
581
582 pr_CheckEntryById(name,id,owner,creator)
583 char *name;
584 afs_int32 id;
585 char *owner;
586 char *creator;
587 {
588     /* struct prcheckentry returns other things, which aren't useful to show at this time. */
589     register afs_int32 code;
590     struct prcheckentry aentry;
591
592     code = pr_SIdToName(id,name);
593     if (code) return code;
594     if (id == ANONYMOUSID) return PRNOENT;
595     code = ubik_Call(PR_ListEntry,pruclient,0,id,&aentry);
596     if (code) return code;
597     /* this should be done in one RPC, but I'm lazy. */
598     code = pr_SIdToName(aentry.owner,owner);
599     if (code) return code;
600     code = pr_SIdToName(aentry.creator,creator);
601     if (code) return code;
602     return PRSUCCESS;
603 }
604
605 pr_ChangeEntry(oldname,newname,newid,newowner)
606 char *oldname;
607 char *newname;
608 afs_int32 *newid;
609 char *newowner;
610 {
611     register afs_int32 code;
612     afs_int32 id;
613     afs_int32 oid =0;
614
615     code = pr_SNameToId(oldname,&id);
616     if (code) return code;
617     if (id == ANONYMOUSID) return PRNOENT;
618     if (newowner && *newowner) {
619         code = pr_SNameToId(newowner,&oid);
620         if (code) return code;
621         if (oid == ANONYMOUSID) return PRNOENT;
622     }
623     code = ubik_Call(PR_ChangeEntry,pruclient, 0,id,newname,oid,newid);
624     return code;
625 }
626
627 pr_IsAMemberOf(uname,gname,flag)
628 char *uname;
629 char *gname;
630 afs_int32 *flag;
631 {
632     register afs_int32 code;
633     namelist lnames;
634     idlist lids;
635
636     stolower(uname);
637     stolower(gname);
638     lnames.namelist_len = 2;
639     lnames.namelist_val = (prname *)malloc(2*PR_MAXNAMELEN);
640     strncpy(lnames.namelist_val[0],uname,PR_MAXNAMELEN);
641     strncpy(lnames.namelist_val[1],gname,PR_MAXNAMELEN);
642     lids.idlist_val= 0;
643     lids.idlist_len = 0;
644     code = pr_NameToId(&lnames,&lids);
645     if (code) {
646         if (lnames.namelist_val) free(lnames.namelist_val);
647         if (lids.idlist_val) free(lids.idlist_val);
648         return code;
649     }
650     code = ubik_Call(PR_IsAMemberOf,pruclient,0,lids.idlist_val[0],lids.idlist_val[1],flag);
651     if (lnames.namelist_val) free(lnames.namelist_val);
652     if (lids.idlist_val) free(lids.idlist_val);
653     return code;
654 }
655
656
657 pr_ListMaxUserId(mid)
658 afs_int32 *mid;
659 {
660     register afs_int32 code;
661     afs_int32 gid;
662     code = ubik_Call(PR_ListMax,pruclient,0,mid,&gid);
663     return code;
664 }
665
666 pr_SetMaxUserId(mid)
667 afs_int32 mid;
668 {
669     register afs_int32 code;
670     afs_int32 flag = 0;
671     code = ubik_Call(PR_SetMax,pruclient,0,mid,flag);
672     return code;
673 }
674
675 pr_ListMaxGroupId(mid)
676 afs_int32 *mid;
677 {
678     register afs_int32 code;
679     afs_int32 id;
680     code = ubik_Call(PR_ListMax,pruclient,0,&id,mid);
681     return code;
682 }
683
684 pr_SetMaxGroupId(mid)
685 afs_int32 mid;
686 {
687     register afs_int32 code;
688     afs_int32 flag = 0;
689
690     flag |= PRGRP;
691     code = ubik_Call(PR_SetMax,pruclient,0,mid,flag);
692     return code;
693 }
694
695 afs_int32 pr_SetFieldsEntry (id, mask, flags, ngroups, nusers)
696   afs_int32 id;
697   afs_int32 mask;
698   afs_int32 flags, ngroups, nusers;
699 {
700     register afs_int32 code;
701
702     code = ubik_Call(PR_SetFieldsEntry,pruclient,0,id,mask, flags, ngroups, nusers, 0,0);
703     return code;
704 }
705
706
707 stolower(s)
708 char *s;
709 {
710     while (*s) {
711         if (isupper(*s)) *s = tolower(*s);
712         s++;
713     }
714 }
715