307973ae954dcacb38966375c8094c121fdc6492
[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
65     code = kauth_cred_setgroups(cred, args, retval, osi_crgetruid(cred));
66     /*
67      * Note that if there is a pag already in the new groups we don't
68      * overwrite it with the old pag.
69      */
70     if (PagInCred(cred) == NOPAG) {
71         if (((treq.uid >> 24) & 0xff) == 'A') {
72             AFS_GLOCK();
73             /* we've already done a setpag, so now we redo it */
74             AddPag(p, treq.uid, &cred);
75             AFS_GUNLOCK();
76         }
77     }
78     return code;
79 }
80
81
82 int
83 setpag(struct proc *proc, afs_ucred_t *cred, afs_uint32 pagvalue,
84        afs_uint32 * newpag, int change_parent)
85 {
86     gid_t gidset[NGROUPS];
87     int ngroups, code;
88     int j;
89
90     AFS_STATCNT(setpag);
91     ngroups = osi_getgroups(*cred, NGROUPS, gidset);
92     if (afs_get_pag_from_groups(gidset[1], gidset[2]) == NOPAG) {
93         /* We will have to shift grouplist to make room for pag */
94         if (ngroups + 2 > NGROUPS) {
95             return (E2BIG);
96         }
97         for (j = ngroups - 1; j >= 0; j--) {
98             gidset[j + 2] = gidset[j];
99         }
100         ngroups += 2;
101     }
102     *newpag = (pagvalue == -1 ? genpag() : pagvalue);
103     afs_get_groups_from_pag(*newpag, &gidset[1], &gidset[2]);
104     code = osi_setgroups(proc, cred, ngroups, gidset, change_parent);
105     return code;
106 }
107
108
109 static int
110 osi_getgroups(kauth_cred_t cred, int ngroups, gid_t * gidset)
111 {
112     int ngrps, savengrps;
113     struct kauth_cred *cr;
114     gid_t *gp;
115
116     AFS_STATCNT(afs_getgroups);
117
118     cr = (struct kauth_cred *) cred;
119     savengrps = ngrps = MIN(ngroups, kauth_cred_ngroups(cred));
120     gp = cred->cr_groups;
121     while (ngrps--)
122         *gidset++ = *gp++;
123     return savengrps;
124 }
125
126
127 static int
128 osi_setgroups(struct proc *proc, kauth_cred_t *cred, int ngroups,
129               gid_t * gidset, int change_parent)
130 {
131     int i;
132     struct kauth_cred *cr;
133
134     AFS_STATCNT(afs_setgroups); /* XXX rename statcnt */
135
136     if (ngroups > NGROUPS)
137         return EINVAL;
138
139     cr = (struct kauth_cred *) *cred;
140     if (!change_parent)
141         cr = kauth_cred_copy(cr);
142
143     for (i = 0; i < ngroups; i++)
144         cr->cr_groups[i] = gidset[i];
145     for (i = ngroups; i < NGROUPS; i++)
146         cr->cr_groups[i] = NOGROUP;
147     cr->cr_ngroups = ngroups;
148
149     *cred = cr;
150     return (0);
151 }