macos-rollup-20051013
[openafs.git] / src / afs / DARWIN / 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
20 RCSID
21     ("$Header$");
22
23 /* We should be doing something better anyway */
24 #ifdef AFS_DARWIN80_ENV
25 int
26 setpag(proc, cred, pagvalue, newpag, change_parent)
27      struct proc *proc;
28      struct ucred **cred;
29      afs_uint32 pagvalue;
30      afs_uint32 *newpag;
31      afs_uint32 change_parent;
32
33     return -1;
34 }
35 #else
36 #include "afs/sysincludes.h"
37 #include "afsincludes.h"
38 #include "afs/afs_stats.h"      /* statistics */
39
40 static int
41   afs_getgroups(struct ucred *cred, int ngroups, gid_t * gidset);
42
43 static int
44   afs_setgroups(struct proc *proc, struct ucred **cred, int ngroups,
45                 gid_t * gidset, int change_parent);
46
47 int
48 Afs_xsetgroups(p, args, retval)
49      struct proc *p;
50      void *args;
51      int *retval;
52 {
53     int code = 0;
54     struct vrequest treq;
55     struct ucred *cr;
56
57     pcred_readlock(p);
58     cr = crdup(p->p_cred->pc_ucred);
59     pcred_unlock(p);
60
61     AFS_STATCNT(afs_xsetgroups);
62     AFS_GLOCK();
63
64     code = afs_InitReq(&treq, cr);
65     AFS_GUNLOCK();
66     crfree(cr);
67     if (code)
68         return setgroups(p, args, retval);      /* afs has shut down */
69
70     code = setgroups(p, args, retval);
71     /* Note that if there is a pag already in the new groups we don't
72      * overwrite it with the old pag.
73      */
74     pcred_readlock(p);
75     cr = crdup(p->p_cred->pc_ucred);
76     pcred_unlock(p);
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(p, treq.uid, &cr);
83             AFS_GUNLOCK();
84         }
85     }
86     crfree(cr);
87     return code;
88 }
89
90
91     gid_t gidset[NGROUPS];
92     int ngroups, code;
93     int j;
94
95     AFS_STATCNT(setpag);
96     ngroups = afs_getgroups(*cred, NGROUPS, gidset);
97     if (afs_get_pag_from_groups(gidset[1], gidset[2]) == NOPAG) {
98         /* We will have to shift grouplist to make room for pag */
99         if (ngroups + 2 > NGROUPS) {
100             return (E2BIG);
101         }
102         for (j = ngroups - 1; j >= 1; j--) {
103             gidset[j + 2] = gidset[j];
104         }
105         ngroups += 2;
106     }
107     *newpag = (pagvalue == -1 ? genpag() : pagvalue);
108     afs_get_groups_from_pag(*newpag, &gidset[1], &gidset[2]);
109     code = afs_setgroups(proc, cred, ngroups, gidset, change_parent);
110     return code;
111 }
112
113
114 static int
115 afs_getgroups(struct ucred *cred, int ngroups, gid_t * gidset)
116 {
117     int ngrps, savengrps;
118     gid_t *gp;
119
120     AFS_STATCNT(afs_getgroups);
121     savengrps = ngrps = MIN(ngroups, cred->cr_ngroups);
122     gp = cred->cr_groups;
123     while (ngrps--)
124         *gidset++ = *gp++;
125     return savengrps;
126 }
127
128
129
130 static int
131 afs_setgroups(struct proc *proc, struct ucred **cred, int ngroups,
132               gid_t * gidset, int change_parent)
133 {
134     int ngrps;
135     int i;
136     gid_t *gp;
137     struct ucred *oldcr, *cr;
138
139     AFS_STATCNT(afs_setgroups);
140     /*
141      * The real setgroups() call does this, so maybe we should too.
142      *
143      */
144     if (ngroups > NGROUPS)
145         return EINVAL;
146     cr = *cred;
147     cr->cr_ngroups = ngroups;
148     gp = cr->cr_groups;
149     while (ngroups--)
150         *gp++ = *gidset++;
151     if (change_parent) {
152         crhold(cr);
153         pcred_writelock(proc->p_pptr);
154         oldcr = proc->p_pptr->p_cred->pc_ucred;
155         proc->p_pptr->p_cred->pc_ucred = cr;
156         pcred_unlock(proc->p_pptr);
157         crfree(oldcr);
158     }
159     crhold(cr);
160     pcred_writelock(proc);
161     oldcr = proc->p_cred->pc_ucred;
162     proc->p_cred->pc_ucred = cr;
163     pcred_unlock(proc);
164     crfree(oldcr);
165     return (0);
166 }
167 #endif