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