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