Remove struct from AFS_UCRED instantiations (opaque credential type support)
[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 **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) ? (*acred)->cr_uid : 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((char *)&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 **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         struct proc *p = current_proc();        /* XXX */
177 #else
178         struct proc *p = curproc;       /* XXX */
179 #endif
180 #ifndef AFS_DARWIN80_ENV
181         uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
182                 p->p_pid, p->p_comm);
183 #endif
184         setpag(p, acred, -1, &pag, 1);
185 #else
186 #ifdef  AFS_OSF_ENV
187         setpag(u.u_procp, acred, -1, &pag, 1);  /* XXX u.u_procp is a no-op XXX */
188 #else
189         setpag(acred, -1, &pag, 1);
190 #endif
191 #endif
192     }
193     pag = PagInCred(*acred);
194     uid = (pag == NOPAG) ? (*acred)->cr_uid : pag;
195     /* now we just set the tokens */
196     tu = afs_GetUser(uid, tcell->cellnum, WRITE_LOCK);
197     if (!tu->cellinfo)
198         tu->cellinfo = (void *)tcell;
199     tu->vid = clear.ViceId;
200     if (tu->stp != NULL) {
201         afs_osi_Free(tu->stp, tu->stLen);
202     }
203     tu->stp = (char *)afs_osi_Alloc(stLen);
204     tu->stLen = stLen;
205     memcpy(tu->stp, stp, stLen);
206     tu->ct = clear;
207 #ifndef AFS_NOSTATS
208     afs_stats_cmfullperf.authent.TicketUpdates++;
209     afs_ComputePAGStats();
210 #endif /* AFS_NOSTATS */
211     tu->states |= UHasTokens;
212     tu->states &= ~UTokensBad;
213     afs_SetPrimary(tu, flag);
214     tu->tokenTime = osi_Time();
215     afs_PutUser(tu, WRITE_LOCK);
216
217     return 0;
218 }
219
220
221 int
222 SPAGCB_GetCreds(struct rx_call *a_call, afs_int32 a_uid,
223                 CredInfos *a_creds)
224 {
225     struct unixuser *tu;
226     CredInfo *tci;
227     int bucket, count, i = 0, clen;
228     char *cellname;
229
230     RX_AFS_GLOCK();
231
232     memset(a_creds, 0, sizeof(struct CredInfos));
233     if ((rx_HostOf(rx_PeerOf(rx_ConnectionOf(a_call))) != afs_nfs_server_addr
234         ||  rx_PortOf(rx_PeerOf(rx_ConnectionOf(a_call))) != htons(7001))
235 #if 0 /* for debugging ONLY! */
236         &&  rx_PortOf(rx_PeerOf(rx_ConnectionOf(a_call))) != htons(7901)
237 #endif
238         ) {
239         RX_AFS_GUNLOCK();
240         return UAEPERM;
241     }
242
243     ObtainWriteLock(&afs_xuser, 823);
244
245     /* count them first */
246     bucket = UHash(a_uid);
247     for (count = 0, tu = afs_users[bucket]; tu; tu = tu->next) {
248         if (tu->uid == a_uid) count++;
249     }
250
251     if (!count) {
252         ReleaseWriteLock(&afs_xuser);
253         RX_AFS_GUNLOCK();
254         return UAESRCH;
255     }
256
257     a_creds->CredInfos_val =
258         (CredInfo *)afs_osi_Alloc(count * sizeof(CredInfo));
259     if (!a_creds->CredInfos_val)
260         goto out;
261     a_creds->CredInfos_len = count;
262     memset(a_creds->CredInfos_val, 0, count * sizeof(CredInfo));
263
264     for (i = 0, tu = afs_users[bucket]; tu; tu = tu->next, i++) {
265         if (tu->uid == a_uid && tu->cellinfo &&
266             (tu->states & UHasTokens) && !(tu->states & UTokensBad)) {
267
268             tci = &a_creds->CredInfos_val[i];
269             tci->vid               = tu->vid;
270             tci->ct.AuthHandle     = tu->ct.AuthHandle;
271             memcpy(tci->ct.HandShakeKey, tu->ct.HandShakeKey, 8);
272             tci->ct.ViceId         = tu->ct.ViceId;
273             tci->ct.BeginTimestamp = tu->ct.BeginTimestamp;
274             tci->ct.EndTimestamp   = tu->ct.EndTimestamp;
275
276             cellname = ((struct afspag_cell *)(tu->cellinfo))->cellname;
277             clen = strlen(cellname) + 1;
278             tci->cellname = afs_osi_Alloc(clen);
279             if (!tci->cellname)
280                 goto out;
281             memcpy(tci->cellname, cellname, clen);
282
283             tci->st.st_len = tu->stLen;
284             tci->st.st_val = afs_osi_Alloc(tu->stLen);
285             if (!tci->st.st_val) {
286                 afs_osi_Free(tci->cellname, clen);
287                 goto out;
288             }
289             memcpy(tci->st.st_val, tu->stp, tu->stLen);
290             if (tu->states & UPrimary)
291                 tci->states |= UPrimary;
292         }
293     }
294
295     ReleaseWriteLock(&afs_xuser);
296     RX_AFS_GUNLOCK();
297     return 0;
298
299 out:
300     if (a_creds->CredInfos_val) {
301         while (i-- > 0) {
302             afs_osi_Free(a_creds->CredInfos_val[i].st.st_val,
303                          a_creds->CredInfos_val[i].st.st_len);
304             afs_osi_Free(a_creds->CredInfos_val[i].cellname,
305                          strlen(a_creds->CredInfos_val[i].cellname) + 1);
306         }
307         afs_osi_Free(a_creds->CredInfos_val, count * sizeof(CredInfo));
308     }
309
310     ReleaseWriteLock(&afs_xuser);
311     RX_AFS_GUNLOCK();
312     return UAENOMEM;
313 }
314
315
316 int afspag_PSetSysName(char *ain, afs_int32 ainSize, AFS_UCRED **acred)
317 {
318     int setsysname, count, t;
319     char *cp, *setp;
320
321     setp = ain;
322     memcpy((char *)&setsysname, ain, sizeof(afs_int32));
323     ain += sizeof(afs_int32);
324     if (!setsysname)
325         return 0; /* nothing to do locally */
326
327     /* Check my args */
328     if (setsysname < 0 || setsysname > MAXNUMSYSNAMES)
329         return EINVAL;
330     if (!afs_osi_suser(*acred))
331         return EACCES;
332     for (cp = ain, count = 0; count < setsysname; count++) {
333         /* won't go past end of ain since maxsysname*num < ain length */
334         t = strlen(cp);
335         if (t >= MAXSYSNAME || t <= 0)
336             return EINVAL;
337         /* check for names that can shoot us in the foot */
338         if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
339             return EINVAL;
340         cp += t + 1;
341     }
342
343     ObtainWriteLock(&afs_xpagsys, 824);
344     for (cp = ain, count = 0; count < setsysname; count++) {
345         t = strlen(cp);
346         memcpy(afs_sysnamelist[count], cp, t + 1);
347         cp += t + 1;
348     }
349     afs_sysnamecount = setsysname;
350     afs_sysnamegen++;
351     ReleaseWriteLock(&afs_xpagsys);
352
353     /* Change the arguments so we pass the allpags flag to the server */
354     setsysname |= 0x8000;
355     memcpy(setp, (char *)&setsysname, sizeof(afs_int32));
356     return 0;
357 }
358
359
360 int
361 SPAGCB_GetSysName(struct rx_call *a_call, afs_int32 a_uid,
362                   SysNameList *a_sysnames)
363 {
364     int i = 0;
365
366     RX_AFS_GLOCK();
367
368     ObtainReadLock(&afs_xpagsys);
369     memset(a_sysnames, 0, sizeof(struct SysNameList));
370
371     a_sysnames->SysNameList_len = afs_sysnamecount;
372     a_sysnames->SysNameList_val =
373         afs_osi_Alloc(afs_sysnamecount * sizeof(SysNameEnt));
374     if (!a_sysnames->SysNameList_val)
375         goto out;
376
377     for (i = 0; i < afs_sysnamecount; i++) {
378         a_sysnames->SysNameList_val[i].sysname =
379             afs_osi_Alloc(strlen(afs_sysnamelist[i]) + 1);
380         if (!a_sysnames->SysNameList_val[i].sysname)
381             goto out;
382         strcpy(a_sysnames->SysNameList_val[i].sysname, afs_sysnamelist[i]);
383     }
384
385     ReleaseReadLock(&afs_xpagsys);
386     RX_AFS_GUNLOCK();
387     return 0;
388
389 out:
390     if (a_sysnames->SysNameList_val) {
391         while (i-- > 0) {
392             afs_osi_Free(a_sysnames->SysNameList_val[i].sysname,
393                          strlen(a_sysnames->SysNameList_val[i].sysname) + 1);
394         }
395         afs_osi_Free(a_sysnames->SysNameList_val,
396                      afs_sysnamecount * sizeof(SysNameEnt));
397     }
398
399     ReleaseWriteLock(&afs_xpagsys);
400     RX_AFS_GUNLOCK();
401     return UAENOMEM;
402 }