1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27
28#pragma weak _ucred_free = ucred_free
29#pragma weak _ucred_get = ucred_get
30#pragma weak _ucred_getegid = ucred_getegid
31#pragma weak _ucred_geteuid = ucred_geteuid
32#pragma weak _ucred_getgroups = ucred_getgroups
33#pragma weak _ucred_getpflags = ucred_getpflags
34#pragma weak _ucred_getpid = ucred_getpid
35#pragma weak _ucred_getzoneid = ucred_getzoneid
36#pragma weak _ucred_getprojid = ucred_getprojid
37#pragma weak _ucred_getprivset = ucred_getprivset
38#pragma weak _ucred_getrgid = ucred_getrgid
39#pragma weak _ucred_getruid = ucred_getruid
40#pragma weak _ucred_getsgid = ucred_getsgid
41#pragma weak _ucred_getsuid = ucred_getsuid
42#pragma weak _ucred_getauid = ucred_getauid
43#pragma weak _ucred_getasid = ucred_getasid
44#pragma weak _ucred_getatid = ucred_getatid
45#pragma weak _ucred_getlabel = ucred_getlabel
46#pragma weak _ucred_getamask = ucred_getamask
47#pragma weak _ucred_size = ucred_size
48
49#include "lint.h"
50
51#define	_STRUCTURED_PROC	1
52
53#include "priv_private.h"
54#include <errno.h>
55#include <priv.h>
56#include <stdarg.h>
57#include <stdlib.h>
58#include <stdio.h>
59#include <unistd.h>
60#include <ucred.h>
61#include <limits.h>
62#include <fcntl.h>
63#include <door.h>
64#include <alloca.h>
65#include <sys/ucred.h>
66#include <sys/procfs.h>
67#include <sys/sysmacros.h>
68#include <sys/zone.h>
69#include <tsol/label.h>
70
71ucred_t *
72_ucred_alloc(void)
73{
74	ucred_t *r;
75	size_t sz = ucred_size();
76
77	r = malloc(sz);
78
79	if (r != NULL)
80		r->uc_size = (uint32_t)sz;
81
82	return (r);
83}
84
85void
86ucred_free(ucred_t *uc)
87{
88	free(uc);
89}
90
91
92ucred_t *
93ucred_get(pid_t pid)
94{
95	ucred_t *uc;
96
97	uc = _ucred_alloc();
98
99	if (uc == NULL)
100		return (NULL);
101
102	if (syscall(SYS_ucredsys, UCREDSYS_UCREDGET, pid, uc) != 0) {
103		ucred_free(uc);
104		return (NULL);
105	}
106
107	return (uc);
108}
109
110uid_t
111ucred_geteuid(const ucred_t *uc)
112{
113	/* LINTED: alignment */
114	const prcred_t *cr = UCCRED(uc);
115
116	if (cr == NULL) {
117		errno = EINVAL;
118		return ((uid_t)-1);
119	}
120
121	return (cr->pr_euid);
122}
123
124uid_t
125ucred_getruid(const ucred_t *uc)
126{
127	/* LINTED: alignment */
128	const prcred_t *cr = UCCRED(uc);
129
130	if (cr == NULL) {
131		errno = EINVAL;
132		return ((uid_t)-1);
133	}
134
135	return (cr->pr_ruid);
136}
137
138uid_t
139ucred_getsuid(const ucred_t *uc)
140{
141	/* LINTED: alignment */
142	const prcred_t *cr = UCCRED(uc);
143
144	if (cr == NULL) {
145		errno = EINVAL;
146		return ((uid_t)-1);
147	}
148
149	return (cr->pr_suid);
150}
151
152gid_t
153ucred_getegid(const ucred_t *uc)
154{
155	/* LINTED: alignment */
156	const prcred_t *cr = UCCRED(uc);
157
158	if (cr == NULL) {
159		errno = EINVAL;
160		return ((gid_t)-1);
161	}
162
163	return (cr->pr_egid);
164}
165
166gid_t
167ucred_getrgid(const ucred_t *uc)
168{
169	/* LINTED: alignment */
170	const prcred_t *cr = UCCRED(uc);
171
172	if (cr == NULL) {
173		errno = EINVAL;
174		return ((gid_t)-1);
175	}
176
177	return (cr->pr_rgid);
178}
179
180gid_t
181ucred_getsgid(const ucred_t *uc)
182{
183	/* LINTED: alignment */
184	const prcred_t *cr = UCCRED(uc);
185
186	if (cr == NULL) {
187		errno = EINVAL;
188		return ((gid_t)-1);
189	}
190
191	return (cr->pr_sgid);
192}
193
194int
195ucred_getgroups(const ucred_t *uc, const gid_t **grps)
196{
197	/* LINTED: alignment */
198	const prcred_t *cr = UCCRED(uc);
199
200	if (cr == NULL) {
201		errno = EINVAL;
202		return (-1);
203	}
204
205	if (cr->pr_ngroups > 0)
206		*grps = &cr->pr_groups[0];
207	else
208		*grps = NULL;
209
210	return (cr->pr_ngroups);
211}
212
213const priv_set_t *
214ucred_getprivset(const ucred_t *uc, priv_ptype_t set)
215{
216	/* LINTED: alignment */
217	const prpriv_t *pr = UCPRIV(uc);
218	int pset = priv_getsetbyname(set);
219	priv_data_t *d;
220
221	if (pr == NULL || pset == -1) {
222		errno = EINVAL;
223		return (NULL);
224	}
225
226	LOADPRIVDATA(d);
227
228	return ((const priv_set_t *)
229	    &pr->pr_sets[d->pd_pinfo->priv_setsize * pset]);
230}
231
232pid_t
233ucred_getpid(const ucred_t *uc)
234{
235
236	if (uc->uc_pid == -1)
237		errno = EINVAL;
238
239	return (uc->uc_pid);
240}
241
242projid_t
243ucred_getprojid(const ucred_t *uc)
244{
245
246	if (uc->uc_projid == -1)
247		errno = EINVAL;
248
249	return (uc->uc_projid);
250}
251
252zoneid_t
253ucred_getzoneid(const ucred_t *uc)
254{
255
256	if (uc->uc_zoneid < MIN_ZONEID || uc->uc_zoneid > MAX_ZONEID) {
257		errno = EINVAL;
258		return (-1);
259	}
260
261	return (uc->uc_zoneid);
262}
263
264bslabel_t *
265ucred_getlabel(const ucred_t *uc)
266{
267	/* LINTED: alignment */
268	bslabel_t *slabel = UCLABEL(uc);
269
270	if (!is_system_labeled() || slabel == NULL) {
271		errno = EINVAL;
272		return (NULL);
273	}
274
275	return (slabel);
276}
277
278/*
279 * For now, assume single bit flags.
280 */
281uint_t
282ucred_getpflags(const ucred_t *uc, uint_t flag)
283{
284	/* LINTED: alignment */
285	prpriv_t *pr = UCPRIV(uc);
286	char *x, *end;
287
288	if (pr == NULL) {
289		errno = EINVAL;
290		return ((uint_t)-1);
291	}
292
293	end = (char *)pr + PRIV_PRPRIV_SIZE(pr);
294	x = end - pr->pr_infosize;
295
296	while (x < end) {
297		/* LINTED: alignment */
298		priv_info_t *pi = (priv_info_t *)x;
299		priv_info_uint_t *pii;
300
301		switch (pi->priv_info_type) {
302		case PRIV_INFO_FLAGS:
303			/* LINTED: alignment */
304			pii = (priv_info_uint_t *)x;
305			return ((pii->val & flag) ? 1 : 0);
306		}
307		/* Forward progress */
308		if (pi->priv_info_size < sizeof (priv_info_t))
309			break;
310		x += pi->priv_info_size;
311	}
312
313	errno = EINVAL;
314	return ((uint_t)-1);
315}
316
317au_id_t
318ucred_getauid(const ucred_t *uc)
319{
320	/* LINTED: alignment */
321	const auditinfo64_addr_t *ainfo = UCAUD(uc);
322
323	if (ainfo == NULL)
324		return (AU_NOAUDITID);
325
326	return (ainfo->ai_auid);
327}
328
329au_asid_t
330ucred_getasid(const ucred_t *uc)
331{
332	/* LINTED: alignment */
333	const auditinfo64_addr_t *ainfo = UCAUD(uc);
334
335	if (ainfo == NULL)
336		return ((au_asid_t)-1);
337
338	return (ainfo->ai_asid);
339}
340
341const au_tid64_addr_t *
342ucred_getatid(const ucred_t *uc)
343{
344	/* LINTED: alignment */
345	const auditinfo64_addr_t *ainfo = UCAUD(uc);
346
347	if (ainfo == NULL) {
348		errno = EINVAL;
349		return (NULL);
350	}
351
352	return (&ainfo->ai_termid);
353}
354
355const au_mask_t *
356ucred_getamask(const ucred_t *uc)
357{
358	/* LINTED: alignment */
359	const auditinfo64_addr_t *ainfo = UCAUD(uc);
360
361	if (ainfo == NULL) {
362		errno = EINVAL;
363		return (NULL);
364	}
365
366	return (&ainfo->ai_mask);
367}
368
369size_t
370ucred_size(void)
371{
372	priv_data_t *d;
373
374	LOADPRIVDATA(d);
375
376	return (d->pd_ucredsize);
377}
378