initial-freebsd-port-work-20010414
[openafs.git] / src / afs / FBSD / 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 "../afs/param.h"
19 #include "../afs/sysincludes.h"
20 #include "../afs/afsincludes.h"
21 #include "../afs/afs_stats.h"  /* statistics */
22
23 #define NOCRED  ((struct ucred *) -1)
24 #define NOUID   ((uid_t) -1)
25 #define NOGID   ((gid_t) -1)
26
27
28 static int
29 afs_getgroups(
30     struct ucred *cred,
31     int ngroups,
32     gid_t *gidset);
33
34 static int
35 afs_setgroups(
36     struct proc *proc,
37     struct ucred **cred,
38     int ngroups,
39     gid_t *gidset,
40     int change_parent);
41
42 int
43 Afs_xsetgroups(p, args, retval)
44     struct proc *p;
45     void *args;
46     int *retval;
47 {
48     int code = 0;
49     struct vrequest treq;
50
51     AFS_STATCNT(afs_xsetgroups);
52     AFS_GLOCK();
53
54     /*    code = afs_InitReq(&treq, u.u_cred); */
55     code = afs_InitReq(&treq, curproc->p_cred->pc_ucred);
56     AFS_GUNLOCK();
57     if (code) return code;
58
59     code = setgroups(p, args, retval);
60     /* Note that if there is a pag already in the new groups we don't
61      * overwrite it with the old pag.
62      */
63     if (PagInCred(curproc->p_cred->pc_ucred) == NOPAG) {
64         if (((treq.uid >> 24) & 0xff) == 'A') {
65             AFS_GLOCK();
66             /* we've already done a setpag, so now we redo it */
67             AddPag(p, treq.uid, &p->p_rcred);
68             AFS_GUNLOCK();
69         }
70     }
71     return code;
72 }
73
74
75 int
76 setpag(proc, cred, pagvalue, newpag, change_parent)
77     struct proc *proc;
78     struct ucred **cred;
79     afs_uint32 pagvalue;
80     afs_uint32 *newpag;
81     afs_uint32 change_parent;
82 {
83     gid_t gidset[NGROUPS];
84     int ngroups, code;
85     int j;
86
87     AFS_STATCNT(setpag);
88     ngroups = afs_getgroups(*cred, NGROUPS, gidset);
89     if (afs_get_pag_from_groups(gidset[0], gidset[1]) == NOPAG) {
90         /* We will have to shift grouplist to make room for pag */
91         if (ngroups + 2 > NGROUPS) {
92             return (E2BIG);
93         }
94         for (j = ngroups -1; j >= 0; j--) {
95             gidset[j+2] = gidset[j];
96         }
97         ngroups += 2;
98     }
99     *newpag = (pagvalue == -1 ? genpag(): pagvalue);
100     afs_get_groups_from_pag(*newpag, &gidset[0], &gidset[1]);
101     code = afs_setgroups(proc, cred, ngroups, gidset, change_parent);
102     return code;
103 }
104
105
106 static int
107 afs_getgroups(
108     struct ucred *cred,
109     int ngroups,
110     gid_t *gidset)
111 {
112     int ngrps, savengrps;
113     gid_t *gp;
114
115     AFS_STATCNT(afs_getgroups);
116     savengrps = ngrps = MIN(ngroups, cred->cr_ngroups);
117     gp = cred->cr_groups;
118     while (ngrps--)
119         *gidset++ = *gp++;   
120     return savengrps;
121 }
122
123
124
125 static int
126 afs_setgroups(
127     struct proc *proc,
128     struct ucred **cred,
129     int ngroups,
130     gid_t *gidset,
131     int change_parent)
132 {
133     int ngrps;
134     int i;
135     gid_t *gp;
136     struct ucred *newcr, *cr;
137
138     AFS_STATCNT(afs_setgroups);
139     /*
140      * The real setgroups() call does this, so maybe we should too.
141      *
142      */
143     if (ngroups > NGROUPS)
144         return EINVAL;
145     cr = *cred;
146     if (!change_parent) {
147         crhold(cr);
148         newcr = crcopy(cr);
149     } else
150         newcr = cr;
151     newcr->cr_ngroups = ngroups;
152     gp = newcr->cr_groups;
153     while (ngroups--)
154         *gp++ = *gidset++;
155     if (!change_parent) {
156         substitute_real_creds(proc, NOUID, NOUID, NOGID, NOGID, newcr);
157     }
158     *cred = newcr;
159     return(0);
160 }