Import Upstream version 1.8.5
[hcoop/debian/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 #if 0 /* for debugging ONLY! */
235 && rx_PortOf(rx_PeerOf(rx_ConnectionOf(a_call))) != htons(7901)
236 #endif
237 ) {
238 RX_AFS_GUNLOCK();
239 return UAEPERM;
240 }
241
242 ObtainWriteLock(&afs_xuser, 823);
243
244 /* count them first */
245 bucket = UHash(a_uid);
246 for (count = 0, tu = afs_users[bucket]; tu; tu = tu->next) {
247 if (tu->uid == a_uid) count++;
248 }
249
250 if (!count) {
251 ReleaseWriteLock(&afs_xuser);
252 RX_AFS_GUNLOCK();
253 return UAESRCH;
254 }
255
256 a_creds->CredInfos_val = afs_osi_Alloc(count * sizeof(CredInfo));
257 if (!a_creds->CredInfos_val)
258 goto out;
259 a_creds->CredInfos_len = count;
260 memset(a_creds->CredInfos_val, 0, count * sizeof(CredInfo));
261
262 for (i = 0, tu = afs_users[bucket]; tu; tu = tu->next, i++) {
263 if (tu->uid == a_uid && tu->cellinfo &&
264 (tu->states & UHasTokens) && !(tu->states & UTokensBad)) {
265
266 tu->refCount++;
267 ReleaseWriteLock(&afs_xuser);
268
269 afs_LockUser(tu, READ_LOCK, 0);
270
271 token = afs_FindToken(tu->tokens, RX_SECIDX_KAD);
272
273 tci = &a_creds->CredInfos_val[i];
274 tci->vid = token->rxkad.clearToken.ViceId;
275 tci->ct.AuthHandle = token->rxkad.clearToken.AuthHandle;
276 memcpy(tci->ct.HandShakeKey,
277 token->rxkad.clearToken.HandShakeKey, 8);
278 tci->ct.ViceId = token->rxkad.clearToken.ViceId;
279 tci->ct.BeginTimestamp = token->rxkad.clearToken.BeginTimestamp;
280 tci->ct.EndTimestamp = token->rxkad.clearToken.EndTimestamp;
281
282 cellname = ((struct afspag_cell *)(tu->cellinfo))->cellname;
283 clen = strlen(cellname) + 1;
284 tci->cellname = afs_osi_Alloc(clen);
285 if (!tci->cellname) {
286 afs_PutUser(tu, READ_LOCK);
287 ObtainWriteLock(&afs_xuser, 370);
288 goto out;
289 }
290 memcpy(tci->cellname, cellname, clen);
291
292 tci->st.st_len = token->rxkad.ticketLen;
293 tci->st.st_val = afs_osi_Alloc(token->rxkad.ticketLen);
294 if (!tci->st.st_val) {
295 afs_PutUser(tu, READ_LOCK);
296 afs_osi_Free(tci->cellname, clen);
297 ObtainWriteLock(&afs_xuser, 371);
298 goto out;
299 }
300 memcpy(tci->st.st_val,
301 token->rxkad.ticket, token->rxkad.ticketLen);
302 if (tu->states & UPrimary)
303 tci->states |= UPrimary;
304
305 afs_PutUser(tu, READ_LOCK);
306 ObtainWriteLock(&afs_xuser, 372);
307 }
308 }
309
310 ReleaseWriteLock(&afs_xuser);
311 RX_AFS_GUNLOCK();
312 return 0;
313
314 out:
315 if (a_creds->CredInfos_val) {
316 while (i-- > 0) {
317 afs_osi_Free(a_creds->CredInfos_val[i].st.st_val,
318 a_creds->CredInfos_val[i].st.st_len);
319 afs_osi_Free(a_creds->CredInfos_val[i].cellname,
320 strlen(a_creds->CredInfos_val[i].cellname) + 1);
321 }
322 afs_osi_Free(a_creds->CredInfos_val, count * sizeof(CredInfo));
323 }
324
325 ReleaseWriteLock(&afs_xuser);
326 RX_AFS_GUNLOCK();
327 return UAENOMEM;
328 }
329
330
331 int
332 afspag_PSetSysName(char *ain, afs_int32 ainSize, afs_ucred_t **acred)
333 {
334 int setsysname, count, t;
335 char *cp, *setp;
336
337 setp = ain;
338 memcpy((char *)&setsysname, ain, sizeof(afs_int32));
339 ain += sizeof(afs_int32);
340 if (!setsysname)
341 return 0; /* nothing to do locally */
342
343 /* Check my args */
344 if (setsysname < 0 || setsysname > MAXNUMSYSNAMES)
345 return EINVAL;
346 if (!afs_osi_suser(*acred))
347 return EACCES;
348 for (cp = ain, count = 0; count < setsysname; count++) {
349 /* won't go past end of ain since maxsysname*num < ain length */
350 t = strlen(cp);
351 if (t >= MAXSYSNAME || t <= 0)
352 return EINVAL;
353 /* check for names that can shoot us in the foot */
354 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
355 return EINVAL;
356 cp += t + 1;
357 }
358
359 ObtainWriteLock(&afs_xpagsys, 824);
360 for (cp = ain, count = 0; count < setsysname; count++) {
361 t = strlen(cp);
362 memcpy(afs_sysnamelist[count], cp, t + 1);
363 cp += t + 1;
364 }
365 afs_sysnamecount = setsysname;
366 afs_sysnamegen++;
367 ReleaseWriteLock(&afs_xpagsys);
368
369 /* Change the arguments so we pass the allpags flag to the server */
370 setsysname |= 0x8000;
371 memcpy(setp, (char *)&setsysname, sizeof(afs_int32));
372 return 0;
373 }
374
375
376 int
377 SPAGCB_GetSysName(struct rx_call *a_call, afs_int32 a_uid,
378 SysNameList *a_sysnames)
379 {
380 int i = 0;
381
382 RX_AFS_GLOCK();
383
384 ObtainReadLock(&afs_xpagsys);
385 memset(a_sysnames, 0, sizeof(struct SysNameList));
386
387 a_sysnames->SysNameList_len = afs_sysnamecount;
388 a_sysnames->SysNameList_val =
389 afs_osi_Alloc(afs_sysnamecount * sizeof(SysNameEnt));
390 if (!a_sysnames->SysNameList_val)
391 goto out;
392
393 for (i = 0; i < afs_sysnamecount; i++) {
394 a_sysnames->SysNameList_val[i].sysname =
395 afs_osi_Alloc(strlen(afs_sysnamelist[i]) + 1);
396 if (!a_sysnames->SysNameList_val[i].sysname)
397 goto out;
398 strcpy(a_sysnames->SysNameList_val[i].sysname, afs_sysnamelist[i]);
399 }
400
401 ReleaseReadLock(&afs_xpagsys);
402 RX_AFS_GUNLOCK();
403 return 0;
404
405 out:
406 if (a_sysnames->SysNameList_val) {
407 while (i-- > 0) {
408 afs_osi_Free(a_sysnames->SysNameList_val[i].sysname,
409 strlen(a_sysnames->SysNameList_val[i].sysname) + 1);
410 }
411 afs_osi_Free(a_sysnames->SysNameList_val,
412 afs_sysnamecount * sizeof(SysNameEnt));
413 }
414
415 ReleaseWriteLock(&afs_xpagsys);
416 RX_AFS_GUNLOCK();
417 return UAENOMEM;
418 }