creds.c revision 1.4 1 /* $NetBSD: creds.c,v 1.4 2007/03/20 18:28:08 pooka Exp $ */
2
3 /*
4 * Copyright (c) 2006 Antti Kantee. All Rights Reserved.
5 *
6 * Development of this software was supported by the Ulla Tuominen Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the company nor the name of the author may be used to
17 * endorse or promote products derived from this software without specific
18 * prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
21 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #include <sys/cdefs.h>
34 #if !defined(lint)
35 __RCSID("$NetBSD: creds.c,v 1.4 2007/03/20 18:28:08 pooka Exp $");
36 #endif /* !lint */
37
38 /*
39 * Interface for dealing with credits.
40 */
41
42 #include <sys/types.h>
43 #include <sys/param.h>
44
45 #include <puffs.h>
46 #include <errno.h>
47 #include <string.h>
48
49 #define UUCCRED(a) (a->pcr_type == PUFFCRED_TYPE_UUC)
50 #define INTCRED(a) (a->pcr_type == PUFFCRED_TYPE_INTERNAL)
51
52 int
53 puffs_cred_getuid(const struct puffs_cred *pcr, uid_t *ruid)
54 {
55
56 if (!UUCCRED(pcr))
57 return EINVAL;
58 *ruid = pcr->pcr_uuc.cr_uid;
59
60 return 0;
61 }
62
63 int
64 puffs_cred_getgid(const struct puffs_cred *pcr, gid_t *rgid)
65 {
66
67 if (!UUCCRED(pcr))
68 return EINVAL;
69 *rgid = pcr->pcr_uuc.cr_gid;
70
71 return 0;
72 }
73
74 int
75 puffs_cred_getgroups(const struct puffs_cred *pcr, gid_t *rgids, short *ngids)
76 {
77 size_t ncopy;
78
79 if (!UUCCRED(pcr))
80 return EINVAL;
81
82 ncopy = MIN(*ngids, NGROUPS);
83 (void)memcpy(rgids, pcr->pcr_uuc.cr_groups, ncopy);
84 *ngids = (short)ncopy;
85
86 return 0;
87 }
88
89 int
90 puffs_cred_isuid(const struct puffs_cred *pcr, uid_t uid)
91 {
92
93 return UUCCRED(pcr) && pcr->pcr_uuc.cr_uid == uid;
94 }
95
96 int
97 puffs_cred_hasgroup(const struct puffs_cred *pcr, gid_t gid)
98 {
99 short i;
100
101 if (!UUCCRED(pcr))
102 return 0;
103
104 if (pcr->pcr_uuc.cr_gid == gid)
105 return 1;
106 for (i = 0; i < pcr->pcr_uuc.cr_ngroups; i++)
107 if (pcr->pcr_uuc.cr_groups[i] == gid)
108 return 1;
109
110 return 0;
111 }
112
113 int
114 puffs_cred_iskernel(const struct puffs_cred *pcr)
115 {
116
117 return INTCRED(pcr) && pcr->pcr_internal == PUFFCRED_CRED_NOCRED;
118 }
119
120 int
121 puffs_cred_isfs(const struct puffs_cred *pcr)
122 {
123
124 return INTCRED(pcr) && pcr->pcr_internal == PUFFCRED_CRED_FSCRED;
125 }
126
127 int
128 puffs_cred_isjuggernaut(const struct puffs_cred *pcr)
129 {
130
131 return puffs_cred_isuid(pcr, 0) || puffs_cred_iskernel(pcr)
132 || puffs_cred_isfs(pcr);
133 }
134
135 /*
136 * Gerneic routine for checking file access rights. Modeled after
137 * vaccess() in the kernel.
138 */
139 int
140 puffs_access(enum vtype type, mode_t file_mode, uid_t uid, gid_t gid,
141 mode_t acc_mode, const struct puffs_cred *pcr)
142 {
143 mode_t mask;
144
145 /* megapower */
146 if (puffs_cred_iskernel(pcr) || puffs_cred_isfs(pcr))
147 return 0;
148
149 /* superuser, allow all except exec if *ALL* exec bits are unset */
150 if (puffs_cred_isuid(pcr, 0)) {
151 if ((acc_mode & PUFFS_VEXEC) && type != VDIR &&
152 (file_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0)
153 return EACCES;
154 return 0;
155 }
156
157 mask = 0;
158 /* owner */
159 if (puffs_cred_isuid(pcr, uid)) {
160 if (acc_mode & PUFFS_VEXEC)
161 mask |= S_IXUSR;
162 if (acc_mode & PUFFS_VREAD)
163 mask |= S_IRUSR;
164 if (acc_mode & PUFFS_VWRITE)
165 mask |= S_IWUSR;
166 /* group */
167 } else if (puffs_cred_hasgroup(pcr, gid)) {
168 if (acc_mode & PUFFS_VEXEC)
169 mask |= S_IXGRP;
170 if (acc_mode & PUFFS_VREAD)
171 mask |= S_IRGRP;
172 if (acc_mode & PUFFS_VWRITE)
173 mask |= S_IWGRP;
174 /* other */
175 } else {
176 if (acc_mode & PUFFS_VEXEC)
177 mask |= S_IXOTH;
178 if (acc_mode & PUFFS_VREAD)
179 mask |= S_IROTH;
180 if (acc_mode & PUFFS_VWRITE)
181 mask |= S_IWOTH;
182 }
183
184 if ((file_mode & mask) == mask)
185 return 0;
186 else
187 return EACCES;
188 }
189