setpag-proto-20030623
[openafs.git] / src / afs / FBSD / osi_groups.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  * osi_groups.c
11  *
12  * Implements:
13  * Afs_xsetgroups (syscall)
14  * setpag
15  *
16  */
17 #include <afsconfig.h>
18 #include "afs/param.h"
19 #include <sys/param.h>
20 #ifdef AFS_FBSD50_ENV
21 #include <sys/sysproto.h>
22 #endif
23
24 RCSID("$Header$");
25
26 #include "afs/sysincludes.h"
27 #include "afsincludes.h"
28 #include "afs/afs_stats.h"  /* statistics */
29
30 static int
31 afs_getgroups(
32     struct ucred *cred,
33     int ngroups,
34     gid_t *gidset);
35
36 static int
37 afs_setgroups(
38     struct proc *proc,
39     struct ucred **cred,
40     int ngroups,
41     gid_t *gidset,
42     int change_parent);
43
44 #ifdef AFS_FBSD50_ENV
45 /*
46  * This does nothing useful yet.
47  * In 5.0, creds are associated not with a process, but with a thread.
48  * Probably the right thing to do is replace struct proc with struct thread
49  * everywhere, including setpag.
50  * That will be a tedious undertaking.
51  * For now, I'm just passing curproc to AddPag.
52  * This is probably wrong and I don't know what the consequences might be.
53  */
54
55 int
56 Afs_xsetgroups(struct thread *td, struct setgroups_args *uap)
57 {
58     int code = 0;
59     struct vrequest treq;
60     struct ucred *cr;
61
62     cr = crdup(td->td_ucred);
63
64     AFS_STATCNT(afs_xsetgroups);
65     AFS_GLOCK();
66
67     code = afs_InitReq(&treq, cr);
68     AFS_GUNLOCK();
69     crfree(cr);
70     if (code) return setgroups(td, uap); /* afs has shut down */
71
72     code = setgroups(td, uap);
73     /* Note that if there is a pag already in the new groups we don't
74      * overwrite it with the old pag.
75      */
76     cr = crdup(td->td_ucred);
77
78     if (PagInCred(cr) == NOPAG) {
79         if (((treq.uid >> 24) & 0xff) == 'A') {
80             AFS_GLOCK();
81             /* we've already done a setpag, so now we redo it */
82             AddPag(curproc, treq.uid, &cr);
83             AFS_GUNLOCK();
84         }
85     }
86     crfree(cr);
87     return code;
88 }
89 #else /* FBSD50 */
90 int
91 Afs_xsetgroups(p, args, retval)
92     struct proc *p;
93     void *args;
94     int *retval;
95 {
96     int code = 0;
97     struct vrequest treq;
98     struct ucred *cr;
99
100     cr=crdup(p->p_cred->pc_ucred);
101
102     AFS_STATCNT(afs_xsetgroups);
103     AFS_GLOCK();
104     
105     code = afs_InitReq(&treq, cr);
106     AFS_GUNLOCK();
107     crfree(cr);
108     if (code) return setgroups(p, args, retval); /* afs has shut down */
109
110     code = setgroups(p, args, retval);
111     /* Note that if there is a pag already in the new groups we don't
112      * overwrite it with the old pag.
113      */
114     cr=crdup(p->p_cred->pc_ucred);
115
116     if (PagInCred(cr) == NOPAG) {
117         if (((treq.uid >> 24) & 0xff) == 'A') {
118             AFS_GLOCK();
119             /* we've already done a setpag, so now we redo it */
120             AddPag(p, treq.uid, &cr );
121             AFS_GUNLOCK();
122         }
123     }
124     crfree(cr);
125     return code;
126 }
127 #endif
128
129
130 int
131 setpag(struct proc *proc, struct ucred **cred, afs_uint32 pagvalue,
132        afs_uint32 *newpag, int change_parent)
133 {
134     gid_t gidset[NGROUPS];
135     int ngroups, code;
136     int j;
137
138     AFS_STATCNT(setpag);
139     ngroups = afs_getgroups(*cred, NGROUPS, gidset);
140     if (afs_get_pag_from_groups(gidset[1], gidset[2]) == NOPAG) {
141         /* We will have to shift grouplist to make room for pag */
142         if (ngroups + 2 > NGROUPS) {
143             return (E2BIG);
144         }
145         for (j = ngroups -1; j >= 1; j--) {
146             gidset[j+2] = gidset[j];
147         }
148         ngroups += 2;
149     }
150     *newpag = (pagvalue == -1 ? genpag(): pagvalue);
151     afs_get_groups_from_pag(*newpag, &gidset[1], &gidset[2]);
152     code = afs_setgroups(proc, cred, ngroups, gidset, change_parent);
153     return code;
154 }
155
156
157 static int
158 afs_getgroups(
159     struct ucred *cred,
160     int ngroups,
161     gid_t *gidset)
162 {
163     int ngrps, savengrps;
164     gid_t *gp;
165
166     AFS_STATCNT(afs_getgroups);
167     savengrps = ngrps = MIN(ngroups, cred->cr_ngroups);
168     gp = cred->cr_groups;
169     while (ngrps--)
170         *gidset++ = *gp++;   
171     return savengrps;
172 }
173
174
175 static int
176 afs_setgroups(
177     struct proc *proc,
178     struct ucred **cred,
179     int ngroups,
180     gid_t *gidset,
181     int change_parent)
182 {
183 #ifndef AFS_FBSD50_ENV
184     int ngrps;
185     int i;
186     gid_t *gp;
187     struct ucred *oldcr, *cr;
188
189     AFS_STATCNT(afs_setgroups);
190     /*
191      * The real setgroups() call does this, so maybe we should too.
192      *
193      */
194     if (ngroups > NGROUPS)
195         return EINVAL;
196     cr = *cred;
197     cr->cr_ngroups = ngroups;
198     gp = cr->cr_groups;
199     while (ngroups--)
200         *gp++ = *gidset++;
201     if (change_parent) {
202         crhold(cr);
203         oldcr=proc->p_pptr->p_cred->pc_ucred;
204         proc->p_pptr->p_cred->pc_ucred=cr;
205         crfree(oldcr);
206     }
207     crhold(cr);
208     oldcr=proc->p_cred->pc_ucred;
209     proc->p_cred->pc_ucred=cr;
210     crfree(oldcr);
211 #endif
212     return(0);
213 }