afs: Remove afs_xosi
[openafs.git] / src / afs / AIX / 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 /*
11  * Implements:
12  * setgroups (syscall)
13  * setpag
14  *
15  */
16 #include <afsconfig.h>
17 #include "afs/param.h"
18
19
20 #include "afs/sysincludes.h"
21 #include "afsincludes.h"
22 #include "afs/afs_stats.h"      /* statistics */
23
24
25 static int
26   afs_getgroups(struct ucred *cred, int ngroups, gid_t * gidset);
27
28 static int
29   afs_setgroups(struct ucred **cred, int ngroups, gid_t * gidset,
30                 int change_parent);
31
32 #ifndef AFS_AIX51_ENV
33 int
34 setgroups(ngroups, gidset)
35      int ngroups;
36      gid_t *gidset;
37 {
38     int code = 0;
39     struct vrequest treq;
40     struct ucred *credp;
41     struct ucred *credp0;
42
43     AFS_STATCNT(afs_xsetgroups);
44
45     credp = crref();
46     AFS_GLOCK();
47     code = afs_InitReq(&treq, credp);
48     AFS_GUNLOCK();
49     crfree(credp);
50     if (code)
51         return code;
52
53     code = osetgroups(ngroups, gidset);
54
55     /* Note that if there is a pag already in the new groups we don't
56      * overwrite it with the old pag.
57      */
58     credp = crref();
59     credp0 = credp;
60
61     if (PagInCred(credp) == NOPAG) {
62         if (((treq.uid >> 24) & 0xff) == 'A') {
63             AFS_GLOCK();
64             AddPag(treq.uid, &credp);
65             AFS_GUNLOCK();
66         }
67     }
68
69     /* If AddPag() didn't make a new cred, then free our cred ref */
70     if (credp == credp0) {
71         crfree(credp);
72     }
73     return code;
74 }
75 #endif
76
77 int
78 setpag(cred, pagvalue, newpag, change_parent)
79      struct ucred **cred;
80      afs_uint32 pagvalue;
81      afs_uint32 *newpag;
82      afs_uint32 change_parent;
83 {
84     gid_t gidset[NGROUPS];
85     int ngroups, code;
86     int j;
87
88     AFS_STATCNT(setpag);
89 #ifndef AFS_AIX51_ENV
90     ngroups = afs_getgroups(*cred, NGROUPS, gidset);
91     if (afs_get_pag_from_groups(gidset[0], gidset[1]) == NOPAG) {
92         /* We will have to shift grouplist to make room for pag */
93         if (ngroups + 2 > NGROUPS) {
94             return (setuerror(E2BIG), E2BIG);
95         }
96         for (j = ngroups - 1; j >= 0; j--) {
97             gidset[j + 2] = gidset[j];
98         }
99         ngroups += 2;
100     }
101 #endif
102     *newpag = (pagvalue == -1 ? genpag() : pagvalue);
103 #ifdef AFS_AIX51_ENV
104     if (change_parent) {
105         code = kcred_setpag(*cred, PAG_AFS, *newpag);
106     } else {
107         struct ucred *newcr = crdup(*cred);
108
109         crset(newcr);
110         code = kcred_setpag(newcr, PAG_AFS, *newpag);
111         *cred = newcr;
112     }
113 #else
114     afs_get_groups_from_pag(*newpag, &gidset[0], &gidset[1]);
115     if (code = afs_setgroups(cred, ngroups, gidset, change_parent)) {
116         return (setuerror(code), code);
117     }
118 #endif
119     return code;
120 }
121
122
123 #ifndef AFS_AIX51_ENV
124 static int
125 afs_getgroups(struct ucred *cred, int ngroups, gid_t * gidset)
126 {
127     int ngrps, savengrps;
128     gid_t *gp;
129
130     gidset[0] = gidset[1] = 0;
131     AFS_STATCNT(afs_getgroups);
132
133     savengrps = ngrps = MIN(ngroups, cred->cr_ngrps);
134     gp = cred->cr_groups;
135     while (ngrps--)
136         *gidset++ = *gp++;
137     return savengrps;
138 }
139
140 /* the caller is responsible for checking that ngroups <= NGROUPS */
141
142 static void
143 copy_to_cred(newcr, ngroups, gidset)
144      struct ucred *newcr;
145      int ngroups;
146      gid_t *gidset;
147 {
148     gid_t *gp;
149     int newngroups;
150
151     newngroups = ngroups;
152     gp = newcr->cr_groups;
153     while (ngroups--)
154         *gp++ = *gidset++;
155     newcr->cr_ngrps = newngroups;
156 }
157
158 /*
159  * If change_parent is true, then we want to affect the parent process as well
160  * as the current process.  We do this by writing into the given cred, on
161  * the assumption that it is shared with the parent process.
162  *
163  * Note that it is important that we do NOT actually do anything to the
164  * parent process, because the NFS/AFS translator uses this routine to
165  * write into a given cred, and it has no intention of affecting the parent
166  * process.
167  *
168  * If change_parent is false, then we want to affect only the current process.
169  */
170
171 static int
172 afs_setgroups(struct ucred **cred, int ngroups, gid_t * gidset,
173               int change_parent)
174 {
175     AFS_STATCNT(afs_setgroups);
176
177     if (ngroups > NGROUPS)
178         return EINVAL;
179
180     if (change_parent) {
181
182         /*
183          * klog -setpag goes through this code to change the cred
184          * shared with the parent process.  Historically this did
185          * not work on AIX, but the problem in AIX has now been
186          * fixed.
187          *
188          * The NFS/AFS translator also uses this code in order to
189          * write into a given cred; it certainly doesn't use it
190          * in order to affect any other process.
191          */
192         copy_to_cred(*cred, ngroups, gidset);
193
194     } else {
195
196         struct ucred *newcr = crdup(*cred);
197
198         copy_to_cred(newcr, ngroups, gidset);
199
200         crset(newcr);
201         *cred = newcr;
202     }
203     return 0;
204 }
205 #endif