976bce621466298d6079a6cd8054b78c0885d1ae
[kopensolaris-gnu/glibc.git] / sysdeps / unix / sysv / solaris2 / kopensolaris-gnu / ucred.c
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.
4
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.
9
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.
14
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
18    02111-1307 USA.  */
19
20 #include <inline-syscall.h>
21 #include <unistd.h>
22 #include <ucredP.h>
23 #include <auditP.h>
24 #include <privP.h>
25 #include <errno.h>
26 #include <assert.h>
27
28 DECLARE_INLINE_SYSCALL (int, getpeerucred, int fd, ucred_t *ucred);
29 DECLARE_INLINE_SYSCALL (int, ucred_get, pid_t pid, ucred_t *ucred);
30
31 /* Docs: http://docs.sun.com/app/docs/doc/816-5168/ucred-get-3c?a=view
32          http://docs.sun.com/app/docs/doc/816-5168/getpeerucred-3c?l=ru&a=view */
33
34
35 ucred_t *_ucred_alloc (void)
36 {
37   size_t uc_size = ucred_size ();
38   ucred_t *uc = malloc (uc_size);
39   if (uc)
40     uc->uc_size = uc_size;
41   return uc;
42 }
43
44
45 ucred_t *ucred_get (pid_t pid)
46 {
47   ucred_t *uc = _ucred_alloc ();
48   if (!uc)
49     return NULL;
50
51   int res = INLINE_SYSCALL (ucred_get, 2, pid, uc);
52   if (res != 0)
53     return NULL;
54
55   return uc;
56 }
57
58
59 void ucred_free (ucred_t *uc)
60 {
61   free(uc);
62 }
63
64
65 uid_t ucred_geteuid (const ucred_t *uc)
66 {
67   if (uc->uc_credoff == 0)
68     {
69       __set_errno (EINVAL);
70       return (uid_t)-1;
71     }
72
73   return (uid_t)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_euid;
74 }
75
76
77 uid_t ucred_getruid (const ucred_t *uc)
78 {
79   if (uc->uc_credoff == 0)
80     {
81       __set_errno (EINVAL);
82       return (uid_t)-1;
83     }
84
85   return (uid_t)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_ruid;
86 }
87
88
89 uid_t ucred_getsuid (const ucred_t *uc)
90 {
91   if (uc->uc_credoff == 0)
92     {
93       __set_errno (EINVAL);
94       return (uid_t)-1;
95     }
96
97   return (uid_t)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_suid;
98 }
99
100
101 gid_t ucred_getegid (const ucred_t *uc)
102 {
103   if (uc->uc_credoff == 0)
104     {
105       __set_errno (EINVAL);
106       return (gid_t)-1;
107     }
108
109   return (gid_t)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_egid;
110 }
111
112
113 gid_t ucred_getrgid (const ucred_t *uc)
114 {
115   if (uc->uc_credoff == 0)
116     {
117       __set_errno (EINVAL);
118       return (gid_t)-1;
119     }
120
121   return (gid_t)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_rgid;
122 }
123
124
125 gid_t ucred_getsgid (const ucred_t *uc)
126 {
127   if (uc->uc_credoff == 0)
128     {
129       __set_errno(EINVAL);                                                \
130       return (gid_t)-1;                                                    \
131     }
132
133   return (gid_t)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_sgid;
134 }
135
136
137 int ucred_getgroups (const ucred_t *uc, const gid_t **groups)
138 {
139   if (uc->uc_credoff == 0 || groups == NULL)
140     {
141       __set_errno (EINVAL);
142       return -1;
143     }
144
145   /* The docs say that *groups should always be free'd, so we make sure
146      it's NULL if there are no groups.  */
147   prcred_t *cred = (prcred_t *)((char *)uc + uc->uc_credoff);
148   if (cred->pr_ngroups > 0)
149     *groups = cred->pr_groups;
150   else
151     *groups = NULL;
152
153   return cred->pr_ngroups;
154 }
155
156
157 const priv_set_t *ucred_getprivset (const ucred_t *uc, const char *set)
158 {
159   /* Get prpriv_t.  */
160   if (uc->uc_privoff == 0)
161     {
162       __set_errno (EINVAL);
163       return NULL;
164     }
165   prpriv_t * pr = (prpriv_t *)((char *)uc + uc->uc_privoff);
166
167   /* Get priv set number.  */
168   int setnum = priv_getsetbyname (set);
169   if (setnum == -1)
170     return NULL;
171
172   return (priv_set_t *)&pr->pr_sets[setnum * pr->pr_setsize];
173 }
174
175
176 pid_t ucred_getpid (const ucred_t *uc)
177 {
178   if(uc->uc_pid == (pid_t)-1)
179     __set_errno (EINVAL);
180
181   return uc->uc_pid;
182 }
183
184
185 projid_t ucred_getprojid (const ucred_t *uc)
186 {
187   if(uc->uc_projid == (projid_t)-1)
188     __set_errno (EINVAL);
189
190   return uc->uc_projid;
191 }
192
193
194 zoneid_t ucred_getzoneid (const ucred_t *uc)
195 {
196   if(uc->uc_zoneid == (zoneid_t)-1)
197     __set_errno (EINVAL);
198
199   return uc->uc_zoneid;
200 }
201
202
203 unsigned int ucred_getpflags (const ucred_t *uc, unsigned int flags)
204 {
205   /* Get prpriv_t.  */
206   if (uc->uc_privoff == 0)
207     {
208       __set_errno (EINVAL);
209       return (unsigned int)-1;
210     }
211   prpriv_t *pr = (prpriv_t *)((char *)uc + uc->uc_privoff);
212
213   /* Iterate over all priv_info_t's. Note that the first priv_info_t follows
214      the list of priv sets.  */
215   priv_info_t * pi = (priv_info_t *)&pr->pr_sets[pr->pr_nsets * pr->pr_setsize];
216   uint32_t left = pr->pr_infosize;
217   while (left)
218     {
219       if (pi->priv_info_type == PRIV_INFO_FLAGS)
220         return ((priv_info_uint_t *)pi)->val & flags;
221
222       left -= pi->priv_info_size;
223       pi = (priv_info_t *)((char *)pi + pi->priv_info_size);
224     }
225
226   /* We didn't find PRIV_INFO_FLAGS.  */
227   __set_errno (EINVAL);
228   return (unsigned int)-1;
229 }
230
231
232 m_label_t *ucred_getlabel (const ucred_t *uc)
233 {
234   extern int is_system_labeled (void);
235
236   if (!is_system_labeled () || uc->uc_labeloff == 0)
237     {
238       __set_errno (EINVAL);
239       return NULL;
240     }
241
242   return (m_label_t *)((char *)uc + uc->uc_labeloff);
243 }
244
245
246 au_id_t ucred_getauid (const ucred_t *uc)
247 {
248   if (uc->uc_audoff == 0)
249     return AU_NOAUDITID;
250   const auditinfo64_addr_t *info = (auditinfo64_addr_t *)
251       ((char *)uc + uc->uc_audoff);
252
253   return info->ai_auid;
254 }
255
256
257 au_asid_t ucred_getasid (const ucred_t *uc)
258 {
259   if (uc->uc_audoff == 0)
260     return (au_asid_t)-1;
261   const auditinfo64_addr_t *info = (auditinfo64_addr_t *)
262       ((char *)uc + uc->uc_audoff);
263
264   return info->ai_asid;
265 }
266
267
268 const au_tid64_addr_t * ucred_getatid (const ucred_t *uc)
269 {
270   if (uc->uc_audoff == 0)
271     {
272       __set_errno (EINVAL);
273       return NULL;
274     }
275   const auditinfo64_addr_t *info = (auditinfo64_addr_t *)
276       ((char *)uc + uc->uc_audoff);
277
278   return &info->ai_termid;
279 }
280
281
282 const au_mask_t * ucred_getamask (const ucred_t *uc)
283 {
284   if (uc->uc_audoff == 0)
285     {
286       __set_errno (EINVAL);
287       return NULL;
288     }
289   const auditinfo64_addr_t *info = (auditinfo64_addr_t *)
290       ((char *)uc + uc->uc_audoff);
291
292   return &info->ai_mask;
293 }
294
295
296 size_t ucred_size (void)
297 {
298   const priv_impl_info_t *info = getprivimplinfo ();
299
300   return sizeof (ucred_t) + sizeof (prcred_t) + sizeof (prpriv_t) +
301     ((int)sysconf (_SC_NGROUPS_MAX) - 1) * sizeof (gid_t) +
302     sizeof (priv_chunk_t) * (info->priv_setsize * info->priv_nsets - 1) +
303     info->priv_infosize + sizeof (auditinfo64_addr_t) + BSLABEL_T_SIZE;
304 }
305
306
307 int getpeerucred (int fd, ucred_t **ucred)
308 {
309   ucred_t *uc = *ucred;
310
311   /* alloc ucred if needed */
312   if(*ucred == NULL)
313     {
314       ucred_t *uc = _ucred_alloc ();
315       if (!uc)
316         return -1;
317       *ucred = uc;
318     }
319
320   int res = INLINE_SYSCALL (getpeerucred, 2, fd, uc);
321   if (res == -1 && *ucred == NULL)
322       free (uc);
323   else if (res == 0 && *ucred == NULL)
324       *ucred = uc;
325
326   return res;
327 }