components/python/python27/patches/06-ucred.patch
author John Beck <John.Beck@Oracle.COM>
Mon, 06 Oct 2014 13:15:36 -0700
branchs11u2-sru
changeset 3379 e99da14b537a
parent 458 2edc011b559e
child 3565 2d729d36ded7
permissions -rw-r--r--
PSARC 2014/183 Python 2.7.6 18251953 update Python 2.7 line to version 2.7.6 19004605 update Python 2.7 line to version 2.7.7 19308541 update Python 2.7 line to version 2.7.8 19284990 python 2.7.7 segfaults while under memory stress 17431625 64-bit python should use long rather than int for os.sysconf() return value 19164544 Python 2.7 test_tcl fails 19030238 Python 2.7 test_sysconfig fails - no module named _osx_support 19030198 Python 2.7 tests fail - import name error 19032456 more Python 2.7 tests failing with import errors 19022543 Python 2.7 test_lib2to3 fails

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.

--- /dev/null
+++ Python-2.6.4/Modules/ucred.c
@@ -0,0 +1,390 @@
+/*
+ * 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 }
+};
+
+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);
+	self->ob_type->tp_free(self);
+}
+
+static PyTypeObject pyucred_type = {
+	PyObject_HEAD_INIT(NULL)
+	0,                         /*ob_size*/
+	"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_compare*/
+	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 */
+};
+
+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
+initucred(void)
+{
+	PyObject *m;
+
+	m = Py_InitModule3("ucred", pyucred_module_methods,
+	    pyucred_module_doc);
+
+	pyucred_type.tp_new = PyType_GenericNew;
+	if (PyType_Ready(&pyucred_type) < 0)
+		return;
+
+	Py_INCREF(&pyucred_type);
+
+	PyModule_AddObject(m, "ucred", (PyObject *)&pyucred_type);
+}
--- Python-2.7.8/setup.py.~2~	2014-07-17 20:41:55.688200021 -0700
+++ Python-2.7.8/setup.py	2014-07-17 20:41:55.733063564 -0700
@@ -1542,6 +1542,13 @@
         else:
             missing.append('dl')
 
+        # 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/python2.7
+
+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, e:
+    print e
+try:
+    uc.has_priv("Defective", "proc_fork")
+except OSError, e:
+    print e
+try:
+    uc.has_priv("Defective", "proc_bork")
+except OSError, e:
+    print e
+
+del uc
+uc = ucred.ucred()
+try:
+    uc.getpid()
+except OSError, e:
+    print e