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