klog-krb5-link-order-20090122
[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_GLOCKP(p);
51
52     code = afs_InitReq(&treq, p->p_rcred);
53     AFS_GUNLOCKP(p);
54     if (code)
55         return code;
56
57     code = setgroups(p, args, retval);
58     /*
59      * Note that if there is a pag already in the new groups we don't
60      * overwrite it with the old pag.
61      */
62     if (PagInCred(p->p_rcred) == NOPAG) {
63         if (((treq.uid >> 24) & 0xff) == 'A') {
64             AFS_GLOCKP(p);
65             /* we've already done a setpag, so now we redo it */
66             AddPag(p, treq.uid, &p->p_rcred);
67             AFS_GUNLOCKP(p);
68         }
69     }
70     return code;
71 }
72
73
74 int
75 setpag(struct proc *proc, struct ucred **cred, afs_uint32 pagvalue,
76        afs_uint32 * newpag, int change_parent)
77 {
78     gid_t gidset[NGROUPS];
79     int ngroups, code;
80     int j;
81
82     AFS_STATCNT(setpag);
83     ngroups = afs_getgroups(*cred, NGROUPS, gidset);
84     if (afs_get_pag_from_groups(gidset[1], gidset[2]) == NOPAG) {
85         /* We will have to shift grouplist to make room for pag */
86         if (ngroups + 2 > NGROUPS) {
87             return (E2BIG);
88         }
89         for (j = ngroups - 1; j >= 0; j--) {
90             gidset[j + 2] = gidset[j];
91         }
92         ngroups += 2;
93     }
94     *newpag = (pagvalue == -1 ? genpag() : pagvalue);
95     afs_get_groups_from_pag(*newpag, &gidset[1], &gidset[2]);
96     code = afs_setgroups(proc, cred, ngroups, gidset, change_parent);
97     return code;
98 }
99
100
101 static int
102 afs_getgroups(struct ucred *cred, int ngroups, gid_t * gidset)
103 {
104     int ngrps, savengrps;
105     gid_t *gp;
106
107     AFS_STATCNT(afs_getgroups);
108     savengrps = ngrps = MIN(ngroups, cred->cr_ngroups);
109     gp = cred->cr_groups;
110     while (ngrps--)
111         *gidset++ = *gp++;
112     return savengrps;
113 }
114
115
116 static int
117 afs_setgroups(struct proc *proc, struct ucred **cred, int ngroups,
118               gid_t * gidset, int change_parent)
119 {
120     struct ucred *cr = *cred;
121     int i;
122
123     AFS_STATCNT(afs_setgroups);
124
125     if (ngroups > NGROUPS)
126         return EINVAL;
127
128     if (!change_parent)
129         cr = crcopy(cr);
130
131     for (i = 0; i < ngroups; i++)
132         cr->cr_groups[i] = gidset[i];
133     for (i = ngroups; i < NGROUPS; i++)
134         cr->cr_groups[i] = NOGROUP;
135     cr->cr_ngroups = ngroups;
136
137     *cred = cr;
138     return (0);
139 }