1 /* Copyright (C) 2008 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by David Bartley <dtbartle@csclub.uwaterloo.ca>, 2008.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 #include <inline-syscall.h>
29 DECLARE_INLINE_SYSCALL (int, getpeerucred, int fd, ucred_t *ucred);
30 DECLARE_INLINE_SYSCALL (int, ucred_get, pid_t pid, ucred_t *ucred);
32 /* Docs: http://docs.sun.com/app/docs/doc/816-5168/ucred-get-3c?a=view
33 http://docs.sun.com/app/docs/doc/816-5168/getpeerucred-3c?l=ru&a=view */
36 ucred_t *_ucred_alloc (void)
38 size_t uc_size = ucred_size ();
39 ucred_t *uc = malloc (uc_size);
41 uc->uc_size = uc_size;
46 ucred_t *ucred_get (pid_t pid)
48 ucred_t *uc = _ucred_alloc ();
52 int res = INLINE_SYSCALL (ucred_get, 2, pid, uc);
60 void ucred_free (ucred_t *uc)
66 uid_t ucred_geteuid (const ucred_t *uc)
68 if (uc->uc_credoff == 0)
74 return (uid_t)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_euid;
78 uid_t ucred_getruid (const ucred_t *uc)
80 if (uc->uc_credoff == 0)
86 return (uid_t)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_ruid;
90 uid_t ucred_getsuid (const ucred_t *uc)
92 if (uc->uc_credoff == 0)
98 return (uid_t)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_suid;
102 gid_t ucred_getegid (const ucred_t *uc)
104 if (uc->uc_credoff == 0)
106 __set_errno (EINVAL);
110 return (gid_t)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_egid;
114 gid_t ucred_getrgid (const ucred_t *uc)
116 if (uc->uc_credoff == 0)
118 __set_errno (EINVAL);
122 return (gid_t)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_rgid;
126 gid_t ucred_getsgid (const ucred_t *uc)
128 if (uc->uc_credoff == 0)
130 __set_errno(EINVAL); \
134 return (gid_t)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_sgid;
138 int ucred_getgroups (const ucred_t *uc, const gid_t **groups)
140 if (uc->uc_credoff == 0 || groups == NULL)
142 __set_errno (EINVAL);
146 /* The docs say that *groups should always be free'd, so we make sure
147 it's NULL if there are no groups. */
148 prcred_t *cred = (prcred_t *)((char *)uc + uc->uc_credoff);
149 if (cred->pr_ngroups > 0)
150 *groups = cred->pr_groups;
154 return cred->pr_ngroups;
158 const priv_set_t *ucred_getprivset (const ucred_t *uc, const char *set)
161 if (uc->uc_privoff == 0)
163 __set_errno (EINVAL);
166 prpriv_t * pr = (prpriv_t *)((char *)uc + uc->uc_privoff);
168 /* Get priv set number. */
169 int setnum = priv_getsetbyname (set);
173 return (priv_set_t *)&pr->pr_sets[setnum * pr->pr_setsize];
177 pid_t ucred_getpid (const ucred_t *uc)
179 if(uc->uc_pid == (pid_t)-1)
180 __set_errno (EINVAL);
186 projid_t ucred_getprojid (const ucred_t *uc)
188 if(uc->uc_projid == (projid_t)-1)
189 __set_errno (EINVAL);
191 return uc->uc_projid;
195 zoneid_t ucred_getzoneid (const ucred_t *uc)
197 if(uc->uc_zoneid == (zoneid_t)-1)
198 __set_errno (EINVAL);
200 return uc->uc_zoneid;
204 unsigned int ucred_getpflags (const ucred_t *uc, unsigned int flags)
207 if (uc->uc_privoff == 0)
209 __set_errno (EINVAL);
210 return (unsigned int)-1;
212 prpriv_t *pr = (prpriv_t *)((char *)uc + uc->uc_privoff);
214 /* Iterate over all priv_info_t's. Note that the first priv_info_t follows
215 the list of priv sets. */
216 priv_info_t * pi = (priv_info_t *)&pr->pr_sets[pr->pr_nsets * pr->pr_setsize];
217 uint32_t left = pr->pr_infosize;
220 if (pi->priv_info_type == PRIV_INFO_FLAGS)
221 return ((priv_info_uint_t *)pi)->val & flags;
223 left -= pi->priv_info_size;
224 pi = (priv_info_t *)((char *)pi + pi->priv_info_size);
227 /* We didn't find PRIV_INFO_FLAGS. */
228 __set_errno (EINVAL);
229 return (unsigned int)-1;
233 m_label_t *ucred_getlabel (const ucred_t *uc)
235 extern int is_system_labeled (void);
237 if (!is_system_labeled () || uc->uc_labeloff == 0)
239 __set_errno (EINVAL);
243 return (m_label_t *)((char *)uc + uc->uc_labeloff);
247 au_id_t ucred_getauid (const ucred_t *uc)
249 if (uc->uc_audoff == 0)
251 const auditinfo64_addr_t *info = (auditinfo64_addr_t *)
252 ((char *)uc + uc->uc_audoff);
254 return info->ai_auid;
258 au_asid_t ucred_getasid (const ucred_t *uc)
260 if (uc->uc_audoff == 0)
261 return (au_asid_t)-1;
262 const auditinfo64_addr_t *info = (auditinfo64_addr_t *)
263 ((char *)uc + uc->uc_audoff);
265 return info->ai_asid;
269 const au_tid64_addr_t * ucred_getatid (const ucred_t *uc)
271 if (uc->uc_audoff == 0)
273 __set_errno (EINVAL);
276 const auditinfo64_addr_t *info = (auditinfo64_addr_t *)
277 ((char *)uc + uc->uc_audoff);
279 return &info->ai_termid;
283 const au_mask_t * ucred_getamask (const ucred_t *uc)
285 if (uc->uc_audoff == 0)
287 __set_errno (EINVAL);
290 const auditinfo64_addr_t *info = (auditinfo64_addr_t *)
291 ((char *)uc + uc->uc_audoff);
293 return &info->ai_mask;
297 size_t ucred_size (void)
299 const priv_impl_info_t *info = getprivimplinfo ();
301 return sizeof (ucred_t) + sizeof (prcred_t) + sizeof (prpriv_t) +
302 ((int)sysconf (_SC_NGROUPS_MAX) - 1) * sizeof (gid_t) +
303 sizeof (priv_chunk_t) * (info->priv_setsize * info->priv_nsets - 1) +
304 info->priv_infosize + sizeof (auditinfo64_addr_t) + BSLABEL_T_SIZE;
308 int getpeerucred (int fd, ucred_t **ucred)
310 ucred_t *uc = *ucred;
312 /* alloc ucred if needed */
315 uc = _ucred_alloc ();
321 int res = INLINE_SYSCALL (getpeerucred, 2, fd, uc);
322 if (res == -1 && *ucred == NULL)
324 else if (res == 0 && *ucred == NULL)