f1e26e3dc6e887e0f6bf844c40a1a8d3f58e0174
[openafs.git] / src / afs / afs_pag_cred.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 #include "afs/param.h"
12
13
14 #include "afs/sysincludes.h"    /* Standard vendor system headers */
15 #include "afsincludes.h"        /* Afs-based standard headers */
16 #include "afs/afs_stats.h"
17 #include "afs/unified_afs.h"
18 #include "rx/rx_globals.h"
19 #include "pagcb.h"
20
21
22 struct afspag_cell {
23     struct afspag_cell *next;
24     char *cellname;
25     afs_int32 cellnum;
26 };
27
28 afs_rwlock_t afs_xpagcell;
29 afs_rwlock_t afs_xpagsys;
30 static int lastcell = 0;
31 static struct afspag_cell *cells = 0;
32 static struct afspag_cell *primary_cell = 0;
33
34
35 struct afspag_cell *afspag_GetCell(char *acell)
36 {
37     struct afspag_cell *tcell;
38
39     ObtainWriteLock(&afs_xpagcell, 820);
40
41     for (tcell = cells; tcell; tcell = tcell->next) {
42         if (!strcmp(acell, tcell->cellname))
43             break;
44     }
45
46     if (!tcell) {
47         tcell = (struct afspag_cell *)afs_osi_Alloc(sizeof(struct afspag_cell));
48         if (!tcell)
49             goto out;
50         tcell->cellname = (char *)afs_osi_Alloc(strlen(acell) + 1);
51         if (!tcell->cellname) {
52             afs_osi_Free(tcell, sizeof(struct afspag_cell));
53             tcell = 0;
54             goto out;
55         }
56         strcpy(tcell->cellname, acell);
57         tcell->cellnum = ++lastcell;
58         tcell->next = cells;
59         cells = tcell;
60         if (!primary_cell) primary_cell = tcell;
61     }
62
63 out:
64     ReleaseWriteLock(&afs_xpagcell);
65     return tcell;
66 }
67
68
69 struct afspag_cell *afspag_GetPrimaryCell()
70 {
71     struct afspag_cell *tcell;
72
73     ObtainWriteLock(&afs_xpagcell, 821);
74     tcell = primary_cell;
75     ReleaseWriteLock(&afs_xpagcell);
76     return tcell;
77 }
78
79
80 void afspag_SetPrimaryCell(char *acell)
81 {
82     struct afspag_cell *tcell;
83
84     tcell = afspag_GetCell(acell);
85     ObtainWriteLock(&afs_xpagcell, 822);
86     primary_cell = tcell;
87     ReleaseWriteLock(&afs_xpagcell);
88 }
89
90
91 int afspag_PUnlog(char *ain, afs_int32 ainSize, afs_ucred_t **acred)
92 {
93     register afs_int32 i;
94     register struct unixuser *tu;
95     afs_int32 pag, uid;
96
97     AFS_STATCNT(PUnlog);
98     if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
99         return EIO;             /* Inappropriate ioctl for device */
100
101     pag = PagInCred(*acred);
102     uid = (pag == NOPAG) ? afs_cr_uid(*acred) : pag;
103     i = UHash(uid);
104     ObtainWriteLock(&afs_xuser, 823);
105     for (tu = afs_users[i]; tu; tu = tu->next) {
106         if (tu->uid == uid) {
107             tu->vid = UNDEFVID;
108             tu->states &= ~UHasTokens;
109             /* security is not having to say you're sorry */
110             memset(&tu->ct, 0, sizeof(struct ClearToken));
111 #ifdef UKERNEL
112             /* set the expire times to 0, causes
113              * afs_GCUserData to remove this entry
114              */
115             tu->ct.EndTimestamp = 0;
116             tu->tokenTime = 0;
117 #endif /* UKERNEL */
118         }
119     }
120     ReleaseWriteLock(&afs_xuser);
121     return 0;
122 }
123
124
125 int afspag_PSetTokens(char *ain, afs_int32 ainSize, afs_ucred_t **acred)
126 {
127     afs_int32 i;
128     register struct unixuser *tu;
129     struct afspag_cell *tcell;
130     struct ClearToken clear;
131     char *stp;
132     int stLen;
133     afs_int32 flag, set_parent_pag = 0;
134     afs_int32 pag, uid;
135
136     AFS_STATCNT(PSetTokens);
137     if (!afs_resourceinit_flag) {
138         return EIO;
139     }
140     memcpy((char *)&i, ain, sizeof(afs_int32));
141     ain += sizeof(afs_int32);
142     stp = ain;                  /* remember where the ticket is */
143     if (i < 0 || i > MAXKTCTICKETLEN)
144         return EINVAL;          /* malloc may fail */
145     stLen = i;
146     ain += i;                   /* skip over ticket */
147     memcpy((char *)&i, ain, sizeof(afs_int32));
148     ain += sizeof(afs_int32);
149     if (i != sizeof(struct ClearToken)) {
150         return EINVAL;
151     }
152     memcpy((char *)&clear, ain, sizeof(struct ClearToken));
153     if (clear.AuthHandle == -1)
154         clear.AuthHandle = 999; /* more rxvab compat stuff */
155     ain += sizeof(struct ClearToken);
156     if (ainSize != 2 * sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
157         /* still stuff left?  we've got primary flag and cell name.  Set these */
158         memcpy((char *)&flag, ain, sizeof(afs_int32));  /* primary id flag */
159         ain += sizeof(afs_int32);       /* skip id field */
160         /* rest is cell name, look it up */
161         /* some versions of gcc appear to need != 0 in order to get this right */
162         if ((flag & 0x8000) != 0) {     /* XXX Use Constant XXX */
163             flag &= ~0x8000;
164             set_parent_pag = 1;
165         }
166         tcell = afspag_GetCell(ain);
167     } else {
168         /* default to primary cell, primary id */
169         flag = 1;               /* primary id */
170         tcell = afspag_GetPrimaryCell();
171     }
172     if (!tcell) return ESRCH;
173     if (set_parent_pag) {
174 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
175 # if defined(AFS_DARWIN_ENV)
176         afs_proc_t *p = current_proc(); /* XXX */
177         char procname[256];
178         proc_selfname(procname, 256);
179 # else
180         afs_proc_t *p = curproc;        /* XXX */
181         char *procname = p->p_comm;
182 # endif
183         afs_warnuser("Process %d (%s) tried to change pags in PSetTokens\n",
184                      MyPidxx2Pid(MyPidxx), procname);
185         setpag(p, acred, -1, &pag, 1);
186 #else
187         setpag(acred, -1, &pag, 1);
188 #endif
189     }
190     pag = PagInCred(*acred);
191     uid = (pag == NOPAG) ? afs_cr_uid(*acred) : pag;
192     /* now we just set the tokens */
193     tu = afs_GetUser(uid, tcell->cellnum, WRITE_LOCK);
194     if (!tu->cellinfo)
195         tu->cellinfo = (void *)tcell;
196     tu->vid = clear.ViceId;
197     if (tu->stp != NULL) {
198         afs_osi_Free(tu->stp, tu->stLen);
199     }
200     tu->stp = (char *)afs_osi_Alloc(stLen);
201     tu->stLen = stLen;
202     memcpy(tu->stp, stp, stLen);
203     tu->ct = clear;
204 #ifndef AFS_NOSTATS
205     afs_stats_cmfullperf.authent.TicketUpdates++;
206     afs_ComputePAGStats();
207 #endif /* AFS_NOSTATS */
208     tu->states |= UHasTokens;
209     tu->states &= ~UTokensBad;
210     afs_SetPrimary(tu, flag);
211     tu->tokenTime = osi_Time();
212     afs_PutUser(tu, WRITE_LOCK);
213
214     return 0;
215 }
216
217
218 int
219 SPAGCB_GetCreds(struct rx_call *a_call, afs_int32 a_uid,
220                 CredInfos *a_creds)
221 {
222     struct unixuser *tu;
223     CredInfo *tci;
224     int bucket, count, i = 0, clen;
225     char *cellname;
226
227     RX_AFS_GLOCK();
228
229     memset(a_creds, 0, sizeof(struct CredInfos));
230     if ((rx_HostOf(rx_PeerOf(rx_ConnectionOf(a_call))) != afs_nfs_server_addr
231         ||  rx_PortOf(rx_PeerOf(rx_ConnectionOf(a_call))) != htons(7001))
232 #if 0 /* for debugging ONLY! */
233         &&  rx_PortOf(rx_PeerOf(rx_ConnectionOf(a_call))) != htons(7901)
234 #endif
235         ) {
236         RX_AFS_GUNLOCK();
237         return UAEPERM;
238     }
239
240     ObtainWriteLock(&afs_xuser, 823);
241
242     /* count them first */
243     bucket = UHash(a_uid);
244     for (count = 0, tu = afs_users[bucket]; tu; tu = tu->next) {
245         if (tu->uid == a_uid) count++;
246     }
247
248     if (!count) {
249         ReleaseWriteLock(&afs_xuser);
250         RX_AFS_GUNLOCK();
251         return UAESRCH;
252     }
253
254     a_creds->CredInfos_val =
255         (CredInfo *)afs_osi_Alloc(count * sizeof(CredInfo));
256     if (!a_creds->CredInfos_val)
257         goto out;
258     a_creds->CredInfos_len = count;
259     memset(a_creds->CredInfos_val, 0, count * sizeof(CredInfo));
260
261     for (i = 0, tu = afs_users[bucket]; tu; tu = tu->next, i++) {
262         if (tu->uid == a_uid && tu->cellinfo &&
263             (tu->states & UHasTokens) && !(tu->states & UTokensBad)) {
264
265             tci = &a_creds->CredInfos_val[i];
266             tci->vid               = tu->vid;
267             tci->ct.AuthHandle     = tu->ct.AuthHandle;
268             memcpy(tci->ct.HandShakeKey, tu->ct.HandShakeKey, 8);
269             tci->ct.ViceId         = tu->ct.ViceId;
270             tci->ct.BeginTimestamp = tu->ct.BeginTimestamp;
271             tci->ct.EndTimestamp   = tu->ct.EndTimestamp;
272
273             cellname = ((struct afspag_cell *)(tu->cellinfo))->cellname;
274             clen = strlen(cellname) + 1;
275             tci->cellname = afs_osi_Alloc(clen);
276             if (!tci->cellname)
277                 goto out;
278             memcpy(tci->cellname, cellname, clen);
279
280             tci->st.st_len = tu->stLen;
281             tci->st.st_val = afs_osi_Alloc(tu->stLen);
282             if (!tci->st.st_val) {
283                 afs_osi_Free(tci->cellname, clen);
284                 goto out;
285             }
286             memcpy(tci->st.st_val, tu->stp, tu->stLen);
287             if (tu->states & UPrimary)
288                 tci->states |= UPrimary;
289         }
290     }
291
292     ReleaseWriteLock(&afs_xuser);
293     RX_AFS_GUNLOCK();
294     return 0;
295
296 out:
297     if (a_creds->CredInfos_val) {
298         while (i-- > 0) {
299             afs_osi_Free(a_creds->CredInfos_val[i].st.st_val,
300                          a_creds->CredInfos_val[i].st.st_len);
301             afs_osi_Free(a_creds->CredInfos_val[i].cellname,
302                          strlen(a_creds->CredInfos_val[i].cellname) + 1);
303         }
304         afs_osi_Free(a_creds->CredInfos_val, count * sizeof(CredInfo));
305     }
306
307     ReleaseWriteLock(&afs_xuser);
308     RX_AFS_GUNLOCK();
309     return UAENOMEM;
310 }
311
312
313 int afspag_PSetSysName(char *ain, afs_int32 ainSize, afs_ucred_t **acred)
314 {
315     int setsysname, count, t;
316     char *cp, *setp;
317
318     setp = ain;
319     memcpy((char *)&setsysname, ain, sizeof(afs_int32));
320     ain += sizeof(afs_int32);
321     if (!setsysname)
322         return 0; /* nothing to do locally */
323
324     /* Check my args */
325     if (setsysname < 0 || setsysname > MAXNUMSYSNAMES)
326         return EINVAL;
327     if (!afs_osi_suser(*acred))
328         return EACCES;
329     for (cp = ain, count = 0; count < setsysname; count++) {
330         /* won't go past end of ain since maxsysname*num < ain length */
331         t = strlen(cp);
332         if (t >= MAXSYSNAME || t <= 0)
333             return EINVAL;
334         /* check for names that can shoot us in the foot */
335         if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
336             return EINVAL;
337         cp += t + 1;
338     }
339
340     ObtainWriteLock(&afs_xpagsys, 824);
341     for (cp = ain, count = 0; count < setsysname; count++) {
342         t = strlen(cp);
343         memcpy(afs_sysnamelist[count], cp, t + 1);
344         cp += t + 1;
345     }
346     afs_sysnamecount = setsysname;
347     afs_sysnamegen++;
348     ReleaseWriteLock(&afs_xpagsys);
349
350     /* Change the arguments so we pass the allpags flag to the server */
351     setsysname |= 0x8000;
352     memcpy(setp, (char *)&setsysname, sizeof(afs_int32));
353     return 0;
354 }
355
356
357 int
358 SPAGCB_GetSysName(struct rx_call *a_call, afs_int32 a_uid,
359                   SysNameList *a_sysnames)
360 {
361     int i = 0;
362
363     RX_AFS_GLOCK();
364
365     ObtainReadLock(&afs_xpagsys);
366     memset(a_sysnames, 0, sizeof(struct SysNameList));
367
368     a_sysnames->SysNameList_len = afs_sysnamecount;
369     a_sysnames->SysNameList_val =
370         afs_osi_Alloc(afs_sysnamecount * sizeof(SysNameEnt));
371     if (!a_sysnames->SysNameList_val)
372         goto out;
373
374     for (i = 0; i < afs_sysnamecount; i++) {
375         a_sysnames->SysNameList_val[i].sysname =
376             afs_osi_Alloc(strlen(afs_sysnamelist[i]) + 1);
377         if (!a_sysnames->SysNameList_val[i].sysname)
378             goto out;
379         strcpy(a_sysnames->SysNameList_val[i].sysname, afs_sysnamelist[i]);
380     }
381
382     ReleaseReadLock(&afs_xpagsys);
383     RX_AFS_GUNLOCK();
384     return 0;
385
386 out:
387     if (a_sysnames->SysNameList_val) {
388         while (i-- > 0) {
389             afs_osi_Free(a_sysnames->SysNameList_val[i].sysname,
390                          strlen(a_sysnames->SysNameList_val[i].sysname) + 1);
391         }
392         afs_osi_Free(a_sysnames->SysNameList_val,
393                      afs_sysnamecount * sizeof(SysNameEnt));
394     }
395
396     ReleaseWriteLock(&afs_xpagsys);
397     RX_AFS_GUNLOCK();
398     return UAENOMEM;
399 }