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