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