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