1 /* Copyright (C) 1995, 1989, 1998 Transarc Corporation - All rights reserved */
3 * (C) COPYRIGHT IBM CORPORATION 1987, 1988
4 * LICENSED MATERIALS - PROPERTY OF IBM
10 * afsDFS_SetPagInCred (shared with SGI)
11 * osi_DFSGetPagFromCred (shared with SGI)
12 * Afs_xsetgroups (syscall)
16 #include "../afs/param.h"
17 #include "../afs/sysincludes.h"
18 #include "../afs/afsincludes.h"
19 #include "../afs/afs_stats.h" /* statistics */
36 /* This is common code between SGI's DFS and our AFS. Do *not* alter it's
37 * interface or semantics without notifying SGI.
40 /* fixup_pags returns error code if relevant or 0 on no error.
41 * Sets up the cred for the call to estgroups. This is pretty convoluted
42 * in order to avoid including the private proc.h header file.
44 int fixup_pags(int **credpp, int ngroups, gid_t *gidset, int old_afs_pag,
52 gid_t groups[NGROUPS_UMAX];
55 if (ngroups < 0 || ngroups > ngroups_max)
59 AFS_COPYIN(gidset, groups, ngroups * sizeof(gid_t), code);
64 if (ngroups >= 2) { /* possibly an AFS PAG */
65 new_afs_pag = (afs_get_pag_from_groups(groups[0], groups[1]) != NOPAG);
67 if (ngroups >= 1) { /* possibly a DFS PAG */
68 new_dfs_pag = (int) groups[ngroups-1];
69 if (((new_dfs_pag >> 24) & 0xff) == 'A')
70 new_dfs_pag = (int) groups[ngroups-1];
75 /* Now compute the number of groups we will need. */
77 if (old_afs_pag && !new_afs_pag) /* prepend old AFS pag */
79 if (old_dfs_pag && !new_dfs_pag) /* append old DFS pag */
82 if (new > ngroups_max)
83 return EINVAL; /* sorry */
85 cr = crdup(OSI_GET_CURRENT_CRED()); /* we will replace all the groups. */
86 bzero((char*)&cr->cr_groups, ngroups_max * sizeof(gid_t));
88 /* Now cobble the new groups list together. */
91 if (old_afs_pag && !new_afs_pag) { /* prepend old AFS pag */
94 afs_get_groups_from_pag(old_afs_pag, &g0, &g1);
95 cr->cr_groups[new++] = g0;
96 cr->cr_groups[new++] = g1;
99 for (old = 0; old < ngroups; old++)
100 cr->cr_groups[new++] = groups[old];
102 if (old_dfs_pag && !new_dfs_pag) { /* append old DFS pag */
104 cr->cr_groups[new++] = old_dfs_pag;
107 /* Now, did we do anything? */
109 cr->cr_ngroups = new;
120 * Generic routine to set the PAG in the cred for AFS and DFS.
121 * If flag = 0 this is a DFS pag held in one group.
122 * If flag = 1 this is a AFS pag held in two group entries
124 static int afsDFS_SetPagInCred(struct ucred *credp, int pag, int flag)
130 struct ucred *newcredp;
131 int groups_taken = (flag ? 2 : 1);
133 ngrps = credp->cr_ngroups + groups_taken;
134 if (ngrps >= ngroups_max)
139 /* Break out the AFS pag into two groups */
140 afs_get_groups_from_pag(pag, &g0, &g1);
143 newcredp = crdup(credp);
144 newcredp->cr_ngroups = ngrps;
148 newcredp->cr_groups[0] = g0;
149 newcredp->cr_groups[1] = g1;
152 if (PagInCred(newcredp) != NOPAG){
153 /* found an AFS PAG is set in this cred */
156 newcredp->cr_groups[n] = pag;
158 for (i=n; i<credp->cr_ngroups; i++)
159 newcredp->cr_groups[i+groups_taken] = credp->cr_groups[i];
161 /* estgroups sets current threads cred from newcredp and crfree's credp */
162 estgroups(credp, newcredp);
166 #endif /* AFS_SGI65_ENV */
168 /* SGI's osi_GetPagFromCred - They return a long. */
169 int osi_DFSGetPagFromCred(struct ucred *credp)
175 * For IRIX, the PAG is stored in the first entry
176 * of the gruop list in the cred structure. gid_t's
177 * are 32 bits on 64 bit and 32 bit hardware types.
178 * As of Irix 6.5, the DFS pag is the last group in the list.
180 ngroups = credp->cr_ngroups;
184 * Keep in mind that we might be living with AFS here.
185 * This means we don't really know if our DFS PAG is in
186 * the first or third group entry.
189 pag = credp->cr_groups[ngroups-1];
191 pag = credp->cr_groups[0];
192 if (PagInCred(credp) != NOPAG ){
193 /* AFS has a PAG value in the first two group entries */
196 pag = credp->cr_groups[2];
199 if (((pag >> 24) & 0xff) == 'A')
206 Afs_xsetgroups(int ngroups, gid_t *gidset)
208 int old_afs_pag = NOPAG;
209 int old_dfs_pag = NOPAG;
211 struct ucred *credp = OSI_GET_CURRENT_CRED();
212 struct ucred *modcredp;
215 credp = OSI_GET_CURRENT_CRED();
216 /* First get any old PAG's */
217 old_afs_pag = PagInCred(credp);
218 old_dfs_pag = osi_DFSGetPagFromCred(credp);
220 /* Set the passed in group list. */
221 if (code = setgroups(ngroups, gidset))
225 if (old_afs_pag == NOPAG && old_dfs_pag == NOPAG)
228 /* Well, we could get the cred, except it's in the proc struct which
229 * is not a publicly available header. And the cred won't be valid on
230 * the uthread until we return to user space. So, we examine the passed
231 * in groups in fixup_pags.
233 code = fixup_pags(&modcredp, ngroups, gidset,
234 (old_afs_pag == NOPAG) ? 0 : old_afs_pag,
235 (old_dfs_pag == NOPAG) ? 0 : old_dfs_pag);
236 if (!code && modcredp)
237 estgroups(OSI_GET_CURRENT_PROCP(), modcredp);
241 * The setgroups gave our curent thread a new cred pointer
242 * Get the value again
244 credp = OSI_GET_CURRENT_CRED();
245 if ((PagInCred(credp) == NOPAG) && (old_afs_pag != NOPAG)) {
246 /* reset the AFS PAG */
247 code = afsDFS_SetPagInCred(credp, old_afs_pag, 1);
250 * Once again get the credp because the afsDFS_SetPagInCred might have
251 * assigned a new one.
253 credp = OSI_GET_CURRENT_CRED();
254 if ((osi_DFSGetPagFromCred(credp)==NOPAG)
255 && (old_dfs_pag != NOPAG)) {
256 code = afsDFS_SetPagInCred(credp, old_dfs_pag, 0);
258 #endif /* AFS_SGI65_ENV */
264 setpag(cred, pagvalue, newpag, change_parent)
268 afs_uint32 change_parent;
270 gid_t gidset[NGROUPS];
276 ngroups = afs_getgroups(*cred, NGROUPS, gidset);
277 if (afs_get_pag_from_groups(gidset[0], gidset[1]) == NOPAG) {
278 /* We will have to shift grouplist to make room for pag */
279 if (ngroups + 2 > NGROUPS) {
283 return (setuerror(E2BIG), E2BIG);
286 for (j = ngroups -1; j >= 0; j--) {
287 gidset[j+2] = gidset[j];
291 *newpag = (pagvalue == -1 ? genpag(): pagvalue);
292 afs_get_groups_from_pag(*newpag, &gidset[0], &gidset[1]);
293 if (code = afs_setgroups(cred, ngroups, gidset, change_parent)) {
297 return (setuerror(code), code);
310 int ngrps, savengrps;
313 gidset[0] = gidset[1] = 0;
314 AFS_STATCNT(afs_getgroups);
315 savengrps = ngrps = MIN(ngroups, cred->cr_ngroups);
316 gp = cred->cr_groups;
334 AFS_STATCNT(afs_setgroups);
336 if (ngroups > ngroups_max)
343 newcr->cr_ngroups = ngroups;
344 gp = newcr->cr_groups;
347 if (!change_parent) {
349 estgroups(OSI_GET_CURRENT_PROCP(), newcr);
351 estgroups(cr, newcr);