components/python/python34/patches/07-ucred.patch
author John Beck <John.Beck@Oracle.COM>
Thu, 19 Jun 2014 13:53:07 -0700
changeset 1953 5c1face45dc8
parent 1907 446472de62e9
child 2183 5d00686e81da
permissions -rw-r--r--
19004593 update Python to 3.4.1

This patch provides Python ucred support.  It may be contributed upstream at
some point, but the suitability (or lack thereof) has not yet been determined.

diff --git Python-2.6.4/Modules/ucred.c Python-2.6.4/Modules/ucred.c
new file mode 100644
--- /dev/null
+++ Python-2.6.4/Modules/ucred.c
@@ -0,0 +1,404 @@
+/*
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include <Python.h>
+
+#include <stdio.h>
+#include <priv.h>
+#include <ucred.h>
+#include <ctype.h>
+#include <tsol/label.h>
+
+typedef struct {
+	PyObject_HEAD
+	ucred_t *ucred;
+} pyucred_t;
+
+#define pyucred_getlongid(name, type)				\
+	static PyObject *					\
+	pyucred_get##name(pyucred_t *uc)			\
+	{ 							\
+		type val;					\
+								\
+		if (uc->ucred == NULL) {			\
+			errno = EINVAL;				\
+			PyErr_SetFromErrno(PyExc_OSError);	\
+			return (NULL);				\
+		}						\
+								\
+		if ((val = ucred_get##name(uc->ucred)) == -1) {	\
+			PyErr_SetFromErrno(PyExc_OSError);	\
+			return (NULL);				\
+		}						\
+								\
+		return (Py_BuildValue("l", (long)val));		\
+	}
+
+pyucred_getlongid(euid, uid_t)
+pyucred_getlongid(ruid, uid_t)
+pyucred_getlongid(suid, uid_t)
+pyucred_getlongid(egid, gid_t)
+pyucred_getlongid(rgid, gid_t)
+pyucred_getlongid(sgid, gid_t)
+pyucred_getlongid(pid, pid_t)
+pyucred_getlongid(projid, projid_t)
+pyucred_getlongid(zoneid, zoneid_t)
+
+static PyObject *
+pyucred_getgroups(pyucred_t *uc)
+{
+	const gid_t *groups;
+	PyObject *list;
+	int len;
+	int i;
+
+	if (uc->ucred == NULL) {
+		errno = EINVAL;
+		PyErr_SetFromErrno(PyExc_OSError);
+		return (NULL);
+	}
+
+	if ((len = ucred_getgroups(uc->ucred, &groups)) == -1) {
+		PyErr_SetFromErrno(PyExc_OSError);
+		return (NULL);
+	}
+
+	if ((list = PyList_New(len)) == NULL)
+		return (NULL);
+
+	for (i = 0; i < len; i++) {
+		PyObject *gid = Py_BuildValue("l", (long)groups[i]);
+		if (PyList_SetItem(list, i, gid) == -1)
+			return (NULL);
+	}
+
+	return (list);
+}
+
+static PyObject *
+pyucred_getlabel(pyucred_t *uc)
+{
+	m_label_t *label;
+	PyObject *ret;
+	char *str;
+
+	if (uc->ucred == NULL) {
+		errno = EINVAL;
+		PyErr_SetFromErrno(PyExc_OSError);
+		return (NULL);
+	}
+
+	label = ucred_getlabel(uc->ucred);
+	if (label == NULL)
+		return (Py_BuildValue("s", ""));
+
+	if (label_to_str(label, &str, M_LABEL, DEF_NAMES) == -1) {
+		PyErr_SetFromErrno(PyExc_OSError);
+		return (NULL);
+	}
+
+	ret = Py_BuildValue("s", str);
+	free(str);
+	return (ret);
+}
+
+static PyObject *
+pyucred_getpflags(pyucred_t *uc, PyObject *args, PyObject *kwargs)
+{
+	static char *kwlist[] = { "flags", NULL };
+	uint_t flags;
+
+	if (uc->ucred == NULL) {
+		errno = EINVAL;
+		PyErr_SetFromErrno(PyExc_OSError);
+		return (NULL);
+	}
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist,
+	    &flags))
+		return (NULL);
+
+	if ((flags = ucred_getpflags(uc->ucred, flags)) == (uint_t)-1) {
+		PyErr_SetFromErrno(PyExc_OSError);
+		return (NULL);
+	}
+
+	return (Py_BuildValue("i", flags));
+}
+
+static PyObject *
+pyucred_has_priv(pyucred_t *uc, PyObject *args, PyObject *kwargs)
+{
+	static char *kwlist[] = { "set", "priv", NULL };
+	const priv_set_t *privs;
+	const char *set;
+	const char *priv;
+
+	if (uc->ucred == NULL) {
+		errno = EINVAL;
+		PyErr_SetFromErrno(PyExc_OSError);
+		return (NULL);
+	}
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss", kwlist,
+	    &set, &priv))
+		return (NULL);
+
+	if ((privs = ucred_getprivset(uc->ucred, set)) == NULL) {
+		PyErr_SetFromErrno(PyExc_OSError);
+		return (NULL);
+	}
+
+	if (priv_ismember(privs, priv)) {
+		Py_INCREF(Py_True);
+		return Py_True;
+	}
+
+	Py_INCREF(Py_False);
+	return Py_False;
+}
+
+PyDoc_STRVAR(pyucred_getlabel_doc,
+    "getlabel() -> string\n"
+    "\n"
+    "Return the Trusted Extensions label string, or an "
+    "empty string if not available. The label string is "
+    "converted using the default name and M_LABEL (human-readable). "
+    "Raises OSError. See label_to_str(3TSOL).");
+PyDoc_STRVAR(pyucred_getpflags_doc,
+    "getpflags(flags) -> int\n"
+    "\n"
+    "Return the values of the specified privilege flags.");
+PyDoc_STRVAR(pyucred_has_priv_doc,
+    "has_priv(set, priv) -> bool\n"
+    "\n"
+    "Return true if the given privilege is set in the "
+    "specified set. Raises OSError if the set or privilege is "
+    "invalid, or a problem occurs.\n"
+    "\n"
+    "Currently, the following privilege sets are defined, as "
+    "described in privileges(5):\n"
+    "\n"
+    "Effective\n"
+    "Permitted\n"
+    "Inheritable\n"
+    "Limit\n");
+
+static PyMethodDef pyucred_methods[] = {
+	{ "geteuid", (PyCFunction)pyucred_geteuid, METH_NOARGS,
+	    "Return the effective user ID." },
+	{ "getruid", (PyCFunction)pyucred_getruid, METH_NOARGS,
+	    "Return the real user ID." },
+	{ "getsuid", (PyCFunction)pyucred_getsuid, METH_NOARGS,
+	    "Return the saved user ID." },
+	{ "getegid", (PyCFunction)pyucred_getegid, METH_NOARGS,
+	    "Return the effective group ID." },
+	{ "getrgid", (PyCFunction)pyucred_getrgid, METH_NOARGS,
+	    "Return the real group ID." },
+	{ "getsgid", (PyCFunction)pyucred_getsgid, METH_NOARGS,
+	    "Return the saved group ID." },
+	{ "getpid", (PyCFunction)pyucred_getpid, METH_NOARGS,
+	    "Return the effective user ID." },
+	{ "getprojid", (PyCFunction)pyucred_getprojid, METH_NOARGS,
+	    "Return the project ID." },
+	{ "getzoneid", (PyCFunction)pyucred_getzoneid, METH_NOARGS,
+	    "Return the zone ID." },
+	{ "getgroups", (PyCFunction)pyucred_getgroups, METH_NOARGS,
+	    "Return a list of group IDs." },
+	{ "getlabel", (PyCFunction)pyucred_getlabel, METH_NOARGS,
+	    pyucred_getlabel_doc },
+	{ "getpflags", (PyCFunction)pyucred_getpflags,
+	    METH_VARARGS|METH_KEYWORDS, pyucred_getpflags_doc },
+	{ "has_priv", (PyCFunction)pyucred_has_priv,
+	    METH_VARARGS|METH_KEYWORDS, pyucred_has_priv_doc },
+	{ NULL, NULL }
+};
+
+static int
+pyucred_init(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+	pyucred_t *uc = (pyucred_t *)self;
+	uc->ucred = NULL;
+	return (0);
+}
+
+static void
+pyucred_dealloc(PyObject *self)
+{
+	pyucred_t *uc = (pyucred_t *)self;
+	if (uc->ucred != NULL)
+		ucred_free(uc->ucred);
+	Py_TYPE(self)->tp_free(self);
+}
+
+static PyTypeObject pyucred_type = {
+	PyVarObject_HEAD_INIT(NULL, 0)
+	"ucred.ucred",             /*tp_name*/
+	sizeof (pyucred_t),        /*tp_basicsize*/
+	0,                         /*tp_itemsize*/
+	pyucred_dealloc,           /*tp_dealloc*/
+	0,                         /*tp_print*/
+	0,                         /*tp_getattr*/
+	0,                         /*tp_setattr*/
+	0,                         /*tp_reserved*/
+	0,                         /*tp_repr*/
+	0,                         /*tp_as_number*/
+	0,                         /*tp_as_sequence*/
+	0,                         /*tp_as_mapping*/
+	0,                         /*tp_hash */
+	0,                         /*tp_call*/
+	0,                         /*tp_str*/
+	0,                         /*tp_getattro*/
+	0,                         /*tp_setattro*/
+	0,                         /*tp_as_buffer*/
+	Py_TPFLAGS_DEFAULT,        /*tp_flags*/
+	"user credentials",        /*tp_doc */
+	0,		           /* tp_traverse */
+	0,		           /* tp_clear */
+	0,		           /* tp_richcompare */
+	0,		           /* tp_weaklistoffset */
+	0,		           /* tp_iter */
+	0,		           /* tp_iternext */
+	pyucred_methods,           /* tp_methods */
+	0,                         /* tp_members */
+	0,                         /* tp_getset */
+	0,                         /* tp_base */
+	0,                         /* tp_dict */
+	0,                         /* tp_descr_get */
+	0,                         /* tp_descr_set */
+	0,                         /* tp_dictoffset */
+	(initproc)pyucred_init,    /* tp_init */
+	0,                         /* tp_alloc */
+	0,                         /* tp_new */
+	0,                         /* tp_free */
+	0,                         /* tp_is_gc */
+};
+
+static PyObject *
+pyucred_new(const ucred_t *uc)
+{
+	pyucred_t *self;
+
+	self = (pyucred_t *)PyObject_CallObject((PyObject *)&pyucred_type, NULL);
+
+	if (self == NULL)
+		return (NULL);
+
+	self->ucred = (ucred_t *)uc;
+
+	return ((PyObject *)self);
+}
+
+static PyObject *
+pyucred_get(PyObject *o, PyObject *args, PyObject *kwargs)
+{
+	static char *kwlist[] = { "pid", NULL };
+	ucred_t *ucred = NULL;
+	int pid;
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist,
+	    &pid))
+		return (NULL);
+
+	ucred = ucred_get(pid);
+
+	if (ucred == NULL) {
+		PyErr_SetFromErrno(PyExc_OSError);
+		return (NULL);
+	}
+
+	return (pyucred_new(ucred));
+}
+
+static PyObject *
+pyucred_getpeer(PyObject *o, PyObject *args, PyObject *kwargs)
+{
+	static char *kwlist[] = { "fd", NULL };
+	ucred_t *ucred = NULL;
+	int fd;
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist,
+	    &fd))
+		return (NULL);
+
+	if (getpeerucred(fd, &ucred) == -1) {
+		PyErr_SetFromErrno(PyExc_OSError);
+		return (NULL);
+	}
+
+	return (pyucred_new(ucred));
+}
+
+PyDoc_STRVAR(pyucred_get_doc,
+    "get(pid) -> ucred\n"
+    "\n"
+    "Return the credentials of the specified process ID. "
+    "Raises OSError. See ucred_get(3C).");
+PyDoc_STRVAR(pyucred_getpeer_doc,
+    "getpeer(fd) -> ucred\n"
+    "\n"
+    "Return the credentials of the peer endpoint of a "
+    "connection-oriented socket (SOCK_STREAM) or STREAM fd "
+    "at the time the endpoint was created or the connection "
+    "was established. Raises OSError. See getpeerucred(3C).");
+
+static struct PyMethodDef pyucred_module_methods[] = {
+	{ "get", (PyCFunction) pyucred_get,
+	  METH_VARARGS|METH_KEYWORDS, pyucred_get_doc },
+	{ "getpeer", (PyCFunction) pyucred_getpeer,
+	  METH_VARARGS|METH_KEYWORDS, pyucred_getpeer_doc },
+	{ NULL, NULL, 0, NULL }
+};
+
+PyDoc_STRVAR(pyucred_module_doc,
+    "This module provides an interface to the user credential access "
+    "methods, obtainable either by process ID or file descriptor.");
+
+PyMODINIT_FUNC
+PyInit_ucred (void)
+{
+	PyObject *m;
+
+	static struct PyModuleDef moduledef = {
+	    PyModuleDef_HEAD_INIT,
+	    "ucred",
+	    pyucred_module_doc,
+	    -1,
+	    pyucred_module_methods,
+	    NULL,
+	    NULL,
+	    NULL,
+	    NULL,
+	};
+
+	m = PyModule_Create(&moduledef);
+
+	pyucred_type.tp_new = PyType_GenericNew;
+	if (PyType_Ready(&pyucred_type) < 0)
+		return NULL;
+
+	Py_INCREF(&pyucred_type);
+
+	PyModule_AddObject(m, "ucred", (PyObject *)&pyucred_type);
+
+	return m;
+}
--- Python-3.4.1/setup.py.~3~	2014-05-27 11:02:30.818966992 -0700
+++ Python-3.4.1/setup.py	2014-05-27 11:02:30.872276167 -0700
@@ -1477,6 +1477,13 @@
         # Stefan Krah's _decimal module
         exts.append(self._decimal_ext())
 
+        # ucred module (Solaris)
+        ucred_inc = find_file('ucred.h', [], inc_dirs)
+        tsol_inc = find_file('tsol/label.h', [], inc_dirs)
+        if ucred_inc is not None and tsol_inc is not None:
+            exts.append( Extension('ucred', ['ucred.c'],
+                                   libraries = ['tsol']) )
+
         # Thomas Heller's _ctypes module
         self.detect_ctypes(inc_dirs, lib_dirs)
 
--- /dev/null	2011-02-12 03:14:16.000000000 -0600
+++ Python-2.6.4/Lib/test/ucredtest.py	2011-01-20 13:52:42.945657919 -0600
@@ -0,0 +1,45 @@
+#!/usr/bin/python3.4
+
+import ucred
+import os
+
+uc = ucred.get(os.getpid())
+
+print("pid = %d" % uc.getpid())
+print("euid = %d" % uc.geteuid())
+print("ruid = %d" % uc.getruid())
+print("suid = %d" % uc.getsuid())
+print("egid = %d" % uc.getegid())
+print("rgid = %d" % uc.getrgid())
+print("sgid = %d" % uc.getsgid())
+print("zoneid = %d" % uc.getzoneid())
+print("projid = %d" % uc.getprojid())
+print("groups = %s" % uc.getgroups())
+print("label = %s" % uc.getlabel())
+
+print("getpflags(0x1) = %d" % uc.getpflags(0x1))
+print("getpflags(0x2) = %d" % uc.getpflags(0x2))
+print("has_priv(Effective, proc_fork) = %d" % uc.has_priv("Effective", "proc_fork"))
+print("has_priv(Permitted, proc_fork) = %d" % uc.has_priv("Permitted", "proc_fork"))
+print("has_priv(Inheritable, proc_fork) = %d" % uc.has_priv("Inheritable", "proc_fork"))
+print("has_priv(Limit, file_setid) = %d" % uc.has_priv("Limit", "file_setid"))
+print("has_priv(Effective, file_setid) = %d" % uc.has_priv("Effective", "file_setid"))
+try:
+    uc.has_priv("Effective", "proc_bork")
+except OSError as e:
+    print(e)
+try:
+    uc.has_priv("Defective", "proc_fork")
+except OSError as e:
+    print(e)
+try:
+    uc.has_priv("Defective", "proc_bork")
+except OSError as e:
+    print(e)
+
+del uc
+uc = ucred.ucred()
+try:
+    uc.getpid()
+except OSError as e:
+    print(e)