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