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