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