Import Upstream version 1.8.5
[hcoop/debian/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 #include "afs/sysincludes.h"
20 #include "afsincludes.h"
21 #include "afs/afs_stats.h" /* statistics */
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 EINVAL;
34 }
35 #else
36
37 static int
38 afs_getgroups(struct ucred *cred, int ngroups, gid_t * gidset);
39
40 static int
41 afs_setgroups(struct proc *proc, struct ucred **cred, int ngroups,
42 gid_t * gidset, int change_parent);
43
44 int
45 Afs_xsetgroups(p, args, retval)
46 struct proc *p;
47 void *args;
48 int *retval;
49 {
50 int code = 0;
51 struct vrequest treq;
52 struct ucred *cr;
53
54 pcred_readlock(p);
55 cr = crdup(p->p_cred->pc_ucred);
56 pcred_unlock(p);
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(p, args, retval); /* afs has shut down */
66
67 code = setgroups(p, args, retval);
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 pcred_readlock(p);
72 cr = crdup(p->p_cred->pc_ucred);
73 pcred_unlock(p);
74
75 if (PagInCred(cr) == NOPAG) {
76 if (((treq.uid >> 24) & 0xff) == 'A') {
77 AFS_GLOCK();
78 /* we've already done a setpag, so now we redo it */
79 AddPag(p, treq.uid, &cr);
80 AFS_GUNLOCK();
81 }
82 }
83 crfree(cr);
84 return code;
85 }
86
87 int
88 setpag(proc, cred, pagvalue, newpag, change_parent)
89 struct proc *proc;
90 struct ucred **cred;
91 afs_uint32 pagvalue;
92 afs_uint32 *newpag;
93 afs_uint32 change_parent;
94 {
95 gid_t gidset[NGROUPS];
96 int ngroups, code;
97 int j;
98
99 AFS_STATCNT(setpag);
100 ngroups = afs_getgroups(*cred, NGROUPS, gidset);
101 if (afs_get_pag_from_groups(gidset[1], gidset[2]) == NOPAG) {
102 /* We will have to shift grouplist to make room for pag */
103 if (ngroups + 2 > NGROUPS) {
104 return (E2BIG);
105 }
106 for (j = ngroups - 1; j >= 1; j--) {
107 gidset[j + 2] = gidset[j];
108 }
109 ngroups += 2;
110 }
111 *newpag = (pagvalue == -1 ? genpag() : pagvalue);
112 afs_get_groups_from_pag(*newpag, &gidset[1], &gidset[2]);
113 code = afs_setgroups(proc, cred, ngroups, gidset, change_parent);
114 return code;
115 }
116
117
118 static int
119 afs_getgroups(struct ucred *cred, int ngroups, gid_t * gidset)
120 {
121 int ngrps, savengrps;
122 gid_t *gp;
123
124 AFS_STATCNT(afs_getgroups);
125 savengrps = ngrps = MIN(ngroups, cred->cr_ngroups);
126 gp = cred->cr_groups;
127 while (ngrps--)
128 *gidset++ = *gp++;
129 return savengrps;
130 }
131
132
133
134 static int
135 afs_setgroups(struct proc *proc, struct ucred **cred, int ngroups,
136 gid_t * gidset, int change_parent)
137 {
138 int ngrps;
139 int i;
140 gid_t *gp;
141 struct ucred *oldcr, *cr;
142
143 AFS_STATCNT(afs_setgroups);
144 /*
145 * The real setgroups() call does this, so maybe we should too.
146 *
147 */
148 if (ngroups > NGROUPS)
149 return EINVAL;
150 cr = *cred;
151 cr->cr_ngroups = ngroups;
152 gp = cr->cr_groups;
153 while (ngroups--)
154 *gp++ = *gidset++;
155 if (change_parent) {
156 crhold(cr);
157 pcred_writelock(proc->p_pptr);
158 oldcr = proc->p_pptr->p_cred->pc_ucred;
159 proc->p_pptr->p_cred->pc_ucred = cr;
160 pcred_unlock(proc->p_pptr);
161 crfree(oldcr);
162 }
163 crhold(cr);
164 pcred_writelock(proc);
165 oldcr = proc->p_cred->pc_ucred;
166 proc->p_cred->pc_ucred = cr;
167 pcred_unlock(proc);
168 crfree(oldcr);
169 return (0);
170 }
171 #endif