Updates to the Cache Manager to include NetBSD5 support
[openafs.git] / src / afs / NBSD / 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  * osi_groups.c
12  *
13  * Implements:
14  * Afs_xsetgroups (syscall)
15  * setpag
16  *
17  */
18 #include <afsconfig.h>
19 #include "afs/param.h"
20
21
22 #include "afs/sysincludes.h"
23 #include "afs/afsincludes.h"
24 #include "afs/afs_stats.h"      /* statistics */
25 #include "sys/syscallargs.h"
26
27 #define NOUID   ((uid_t) -1)
28 #define NOGID   ((gid_t) -1)
29
30 /*
31  * NetBSD has a very flexible and elegant replacement for Unix
32  * groups KPIs, see KAUTH(9).
33  *
34  */
35
36 static int
37 osi_getgroups(kauth_cred_t cred, int ngroups, gid_t * gidset);
38
39
40 /* why **? are we returning or reallocating creat? */
41 static int
42 osi_setgroups(struct proc *proc, kauth_cred_t *cred, int ngroups,
43               gid_t * gidset, int change_parent);
44
45 int
46 Afs_xsetgroups(struct proc *p, void *args, int *retval)
47 {
48     int code = 0;
49     struct vrequest treq;
50     kauth_cred_t cred = osi_proccred(p);
51
52     AFS_STATCNT(afs_xsetgroups);
53
54     AFS_GLOCK();
55     code = afs_InitReq(&treq, (afs_ucred_t *) cred);
56     AFS_GUNLOCK();
57
58     if (code)
59         return code;
60
61     /*
62      * XXX Does treq.uid == osi_crgetruid(cred)?
63      */
64 #ifdef AFS_NBSD50_ENV
65         code = kauth_cred_setgroups(cred, args, retval, osi_crgetruid(cred), UIO_SYSSPACE);
66 #else
67         code = kauth_cred_setgroups(cred, args, retval, osi_crgetruid(cred));
68 #endif
69     /*
70      * Note that if there is a pag already in the new groups we don't
71      * overwrite it with the old pag.
72      */
73     if (PagInCred(cred) == 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(p, treq.uid, &cred);
78             AFS_GUNLOCK();
79         }
80     }
81     return code;
82 }
83
84
85 int
86 setpag(struct proc *proc, afs_ucred_t *cred, afs_uint32 pagvalue,
87        afs_uint32 * newpag, int change_parent)
88 {
89     gid_t gidset[NGROUPS];
90     int ngroups, code;
91     int j;
92
93     AFS_STATCNT(setpag);
94     ngroups = osi_getgroups(*cred, NGROUPS, gidset);
95     if (afs_get_pag_from_groups(gidset[1], gidset[2]) == NOPAG) {
96         /* We will have to shift grouplist to make room for pag */
97         if (ngroups + 2 > NGROUPS) {
98             return (E2BIG);
99         }
100         for (j = ngroups - 1; j >= 0; j--) {
101             gidset[j + 2] = gidset[j];
102         }
103         ngroups += 2;
104     }
105     *newpag = (pagvalue == -1 ? genpag() : pagvalue);
106     afs_get_groups_from_pag(*newpag, &gidset[1], &gidset[2]);
107     code = osi_setgroups(proc, cred, ngroups, gidset, change_parent);
108     return code;
109 }
110
111
112 static int
113 osi_getgroups(kauth_cred_t cred, int ngroups, gid_t * gidset)
114 {
115     int ngrps, savengrps;
116     struct kauth_cred *cr;
117     gid_t *gp;
118
119     AFS_STATCNT(afs_getgroups);
120
121     cr = (struct kauth_cred *) cred;
122     savengrps = ngrps = MIN(ngroups, kauth_cred_ngroups(cred));
123     gp = cred->cr_groups;
124     while (ngrps--)
125         *gidset++ = *gp++;
126     return savengrps;
127 }
128
129
130 static int
131 osi_setgroups(struct proc *proc, kauth_cred_t *cred, int ngroups,
132               gid_t * gidset, int change_parent)
133 {
134     int i;
135     struct kauth_cred *cr;
136
137     AFS_STATCNT(afs_setgroups); /* XXX rename statcnt */
138
139     if (ngroups > NGROUPS)
140         return EINVAL;
141
142     cr = (struct kauth_cred *) *cred;
143     if (!change_parent)
144         cr = kauth_cred_copy(cr);
145
146     for (i = 0; i < ngroups; i++)
147         cr->cr_groups[i] = gidset[i];
148     for (i = ngroups; i < NGROUPS; i++)
149         cr->cr_groups[i] = NOGROUP;
150     cr->cr_ngroups = ngroups;
151
152     *cred = cr;
153     return (0);
154 }