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