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