summaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/solaris2/kopensolaris-gnu/ucred.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv/solaris2/kopensolaris-gnu/ucred.c')
-rw-r--r--sysdeps/unix/sysv/solaris2/kopensolaris-gnu/ucred.c328
1 files changed, 328 insertions, 0 deletions
diff --git a/sysdeps/unix/sysv/solaris2/kopensolaris-gnu/ucred.c b/sysdeps/unix/sysv/solaris2/kopensolaris-gnu/ucred.c
new file mode 100644
index 0000000000..5da3485d5e
--- /dev/null
+++ b/sysdeps/unix/sysv/solaris2/kopensolaris-gnu/ucred.c
@@ -0,0 +1,328 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by David Bartley <dtbartle@csclub.uwaterloo.ca>, 2008.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <inline-syscall.h>
+#include <unistd.h>
+#include <ucredP.h>
+#include <auditP.h>
+#include <priv.h>
+#include <procfs.h>
+#include <errno.h>
+#include <assert.h>
+
+DECLARE_INLINE_SYSCALL (int, getpeerucred, int fd, ucred_t *ucred);
+DECLARE_INLINE_SYSCALL (int, ucred_get, pid_t pid, ucred_t *ucred);
+
+/* Docs: http://docs.sun.com/app/docs/doc/816-5168/ucred-get-3c?a=view
+ http://docs.sun.com/app/docs/doc/816-5168/getpeerucred-3c?l=ru&a=view */
+
+
+ucred_t *_ucred_alloc (void)
+{
+ size_t uc_size = ucred_size ();
+ ucred_t *uc = malloc (uc_size);
+ if (uc)
+ uc->uc_size = uc_size;
+ return uc;
+}
+
+
+ucred_t *ucred_get (pid_t pid)
+{
+ ucred_t *uc = _ucred_alloc ();
+ if (!uc)
+ return NULL;
+
+ int res = INLINE_SYSCALL (ucred_get, 2, pid, uc);
+ if (res != 0)
+ return NULL;
+
+ return uc;
+}
+
+
+void ucred_free (ucred_t *uc)
+{
+ free(uc);
+}
+
+
+uid_t ucred_geteuid (const ucred_t *uc)
+{
+ if (uc->uc_credoff == 0)
+ {
+ __set_errno (EINVAL);
+ return (uid_t)-1;
+ }
+
+ return (uid_t)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_euid;
+}
+
+
+uid_t ucred_getruid (const ucred_t *uc)
+{
+ if (uc->uc_credoff == 0)
+ {
+ __set_errno (EINVAL);
+ return (uid_t)-1;
+ }
+
+ return (uid_t)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_ruid;
+}
+
+
+uid_t ucred_getsuid (const ucred_t *uc)
+{
+ if (uc->uc_credoff == 0)
+ {
+ __set_errno (EINVAL);
+ return (uid_t)-1;
+ }
+
+ return (uid_t)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_suid;
+}
+
+
+gid_t ucred_getegid (const ucred_t *uc)
+{
+ if (uc->uc_credoff == 0)
+ {
+ __set_errno (EINVAL);
+ return (gid_t)-1;
+ }
+
+ return (gid_t)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_egid;
+}
+
+
+gid_t ucred_getrgid (const ucred_t *uc)
+{
+ if (uc->uc_credoff == 0)
+ {
+ __set_errno (EINVAL);
+ return (gid_t)-1;
+ }
+
+ return (gid_t)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_rgid;
+}
+
+
+gid_t ucred_getsgid (const ucred_t *uc)
+{
+ if (uc->uc_credoff == 0)
+ {
+ __set_errno(EINVAL); \
+ return (gid_t)-1; \
+ }
+
+ return (gid_t)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_sgid;
+}
+
+
+int ucred_getgroups (const ucred_t *uc, const gid_t **groups)
+{
+ if (uc->uc_credoff == 0 || groups == NULL)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ /* The docs say that *groups should always be free'd, so we make sure
+ it's NULL if there are no groups. */
+ prcred_t *cred = (prcred_t *)((char *)uc + uc->uc_credoff);
+ if (cred->pr_ngroups > 0)
+ *groups = cred->pr_groups;
+ else
+ *groups = NULL;
+
+ return cred->pr_ngroups;
+}
+
+
+const priv_set_t *ucred_getprivset (const ucred_t *uc, const char *set)
+{
+ /* Get prpriv_t. */
+ if (uc->uc_privoff == 0)
+ {
+ __set_errno (EINVAL);
+ return NULL;
+ }
+ prpriv_t * pr = (prpriv_t *)((char *)uc + uc->uc_privoff);
+
+ /* Get priv set number. */
+ int setnum = priv_getsetbyname (set);
+ if (setnum == -1)
+ return NULL;
+
+ return (priv_set_t *)&pr->pr_sets[setnum * pr->pr_setsize];
+}
+
+
+pid_t ucred_getpid (const ucred_t *uc)
+{
+ if(uc->uc_pid == (pid_t)-1)
+ __set_errno (EINVAL);
+
+ return uc->uc_pid;
+}
+
+
+projid_t ucred_getprojid (const ucred_t *uc)
+{
+ if(uc->uc_projid == (projid_t)-1)
+ __set_errno (EINVAL);
+
+ return uc->uc_projid;
+}
+
+
+zoneid_t ucred_getzoneid (const ucred_t *uc)
+{
+ if(uc->uc_zoneid == (zoneid_t)-1)
+ __set_errno (EINVAL);
+
+ return uc->uc_zoneid;
+}
+
+
+unsigned int ucred_getpflags (const ucred_t *uc, unsigned int flags)
+{
+ /* Get prpriv_t. */
+ if (uc->uc_privoff == 0)
+ {
+ __set_errno (EINVAL);
+ return (unsigned int)-1;
+ }
+ prpriv_t *pr = (prpriv_t *)((char *)uc + uc->uc_privoff);
+
+ /* Iterate over all priv_info_t's. Note that the first priv_info_t follows
+ the list of priv sets. */
+ priv_info_t * pi = (priv_info_t *)&pr->pr_sets[pr->pr_nsets * pr->pr_setsize];
+ uint32_t left = pr->pr_infosize;
+ while (left)
+ {
+ if (pi->priv_info_type == PRIV_INFO_FLAGS)
+ return ((priv_info_uint_t *)pi)->val & flags;
+
+ left -= pi->priv_info_size;
+ pi = (priv_info_t *)((char *)pi + pi->priv_info_size);
+ }
+
+ /* We didn't find PRIV_INFO_FLAGS. */
+ __set_errno (EINVAL);
+ return (unsigned int)-1;
+}
+
+
+m_label_t *ucred_getlabel (const ucred_t *uc)
+{
+ extern int is_system_labeled (void);
+
+ if (!is_system_labeled () || uc->uc_labeloff == 0)
+ {
+ __set_errno (EINVAL);
+ return NULL;
+ }
+
+ return (m_label_t *)((char *)uc + uc->uc_labeloff);
+}
+
+
+au_id_t ucred_getauid (const ucred_t *uc)
+{
+ if (uc->uc_audoff == 0)
+ return AU_NOAUDITID;
+ const auditinfo64_addr_t *info = (auditinfo64_addr_t *)
+ ((char *)uc + uc->uc_audoff);
+
+ return info->ai_auid;
+}
+
+
+au_asid_t ucred_getasid (const ucred_t *uc)
+{
+ if (uc->uc_audoff == 0)
+ return (au_asid_t)-1;
+ const auditinfo64_addr_t *info = (auditinfo64_addr_t *)
+ ((char *)uc + uc->uc_audoff);
+
+ return info->ai_asid;
+}
+
+
+const au_tid64_addr_t * ucred_getatid (const ucred_t *uc)
+{
+ if (uc->uc_audoff == 0)
+ {
+ __set_errno (EINVAL);
+ return NULL;
+ }
+ const auditinfo64_addr_t *info = (auditinfo64_addr_t *)
+ ((char *)uc + uc->uc_audoff);
+
+ return &info->ai_termid;
+}
+
+
+const au_mask_t * ucred_getamask (const ucred_t *uc)
+{
+ if (uc->uc_audoff == 0)
+ {
+ __set_errno (EINVAL);
+ return NULL;
+ }
+ const auditinfo64_addr_t *info = (auditinfo64_addr_t *)
+ ((char *)uc + uc->uc_audoff);
+
+ return &info->ai_mask;
+}
+
+
+size_t ucred_size (void)
+{
+ const priv_impl_info_t *info = getprivimplinfo ();
+
+ return sizeof (ucred_t) + sizeof (prcred_t) + sizeof (prpriv_t) +
+ ((int)sysconf (_SC_NGROUPS_MAX) - 1) * sizeof (gid_t) +
+ sizeof (priv_chunk_t) * (info->priv_setsize * info->priv_nsets - 1) +
+ info->priv_infosize + sizeof (auditinfo64_addr_t) + BSLABEL_T_SIZE;
+}
+
+
+int getpeerucred (int fd, ucred_t **ucred)
+{
+ ucred_t *uc = *ucred;
+
+ /* alloc ucred if needed */
+ if (*ucred == NULL)
+ {
+ uc = _ucred_alloc ();
+ if (!uc)
+ return -1;
+ *ucred = uc;
+ }
+
+ int res = INLINE_SYSCALL (getpeerucred, 2, fd, uc);
+ if (res == -1 && *ucred == NULL)
+ free (uc);
+ else if (res == 0 && *ucred == NULL)
+ *ucred = uc;
+
+ return res;
+}