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