components/python/python34/patches/07-ucred.patch
branchs11-update
changeset 3778 35735ffdda43
child 1953 5c1face45dc8
equal deleted inserted replaced
3777:68aef260e079 3778:35735ffdda43
       
     1 This patch provides Python ucred support.  It may be contributed upstream at
       
     2 some point, but the suitability (or lack thereof) has not yet been determined.
       
     3 
       
     4 diff --git Python-2.6.4/Modules/ucred.c Python-2.6.4/Modules/ucred.c
       
     5 new file mode 100644
       
     6 --- /dev/null
       
     7 +++ Python-2.6.4/Modules/ucred.c
       
     8 @@ -0,0 +1,404 @@
       
     9 +/*
       
    10 + * Permission is hereby granted, free of charge, to any person obtaining a copy
       
    11 + * of this software and associated documentation files (the "Software"), to
       
    12 + * deal in the Software without restriction, including without limitation the
       
    13 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
       
    14 + * sell copies of the Software, and to permit persons to whom the Software is
       
    15 + * furnished to do so, subject to the following conditions:
       
    16 + *
       
    17 + * The above copyright notice and this permission notice shall be included in
       
    18 + * all copies or substantial portions of the Software.
       
    19 + *
       
    20 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
    21 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       
    22 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
       
    23 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       
    24 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
       
    25 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
       
    26 + * DEALINGS IN THE SOFTWARE.
       
    27 + *
       
    28 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
       
    29 + */
       
    30 +
       
    31 +#include <Python.h>
       
    32 +
       
    33 +#include <stdio.h>
       
    34 +#include <priv.h>
       
    35 +#include <ucred.h>
       
    36 +#include <ctype.h>
       
    37 +#include <tsol/label.h>
       
    38 +
       
    39 +typedef struct {
       
    40 +	PyObject_HEAD
       
    41 +	ucred_t *ucred;
       
    42 +} pyucred_t;
       
    43 +
       
    44 +#define pyucred_getlongid(name, type)				\
       
    45 +	static PyObject *					\
       
    46 +	pyucred_get##name(pyucred_t *uc)			\
       
    47 +	{ 							\
       
    48 +		type val;					\
       
    49 +								\
       
    50 +		if (uc->ucred == NULL) {			\
       
    51 +			errno = EINVAL;				\
       
    52 +			PyErr_SetFromErrno(PyExc_OSError);	\
       
    53 +			return (NULL);				\
       
    54 +		}						\
       
    55 +								\
       
    56 +		if ((val = ucred_get##name(uc->ucred)) == -1) {	\
       
    57 +			PyErr_SetFromErrno(PyExc_OSError);	\
       
    58 +			return (NULL);				\
       
    59 +		}						\
       
    60 +								\
       
    61 +		return (Py_BuildValue("l", (long)val));		\
       
    62 +	}
       
    63 +
       
    64 +pyucred_getlongid(euid, uid_t)
       
    65 +pyucred_getlongid(ruid, uid_t)
       
    66 +pyucred_getlongid(suid, uid_t)
       
    67 +pyucred_getlongid(egid, gid_t)
       
    68 +pyucred_getlongid(rgid, gid_t)
       
    69 +pyucred_getlongid(sgid, gid_t)
       
    70 +pyucred_getlongid(pid, pid_t)
       
    71 +pyucred_getlongid(projid, projid_t)
       
    72 +pyucred_getlongid(zoneid, zoneid_t)
       
    73 +
       
    74 +static PyObject *
       
    75 +pyucred_getgroups(pyucred_t *uc)
       
    76 +{
       
    77 +	const gid_t *groups;
       
    78 +	PyObject *list;
       
    79 +	int len;
       
    80 +	int i;
       
    81 +
       
    82 +	if (uc->ucred == NULL) {
       
    83 +		errno = EINVAL;
       
    84 +		PyErr_SetFromErrno(PyExc_OSError);
       
    85 +		return (NULL);
       
    86 +	}
       
    87 +
       
    88 +	if ((len = ucred_getgroups(uc->ucred, &groups)) == -1) {
       
    89 +		PyErr_SetFromErrno(PyExc_OSError);
       
    90 +		return (NULL);
       
    91 +	}
       
    92 +
       
    93 +	if ((list = PyList_New(len)) == NULL)
       
    94 +		return (NULL);
       
    95 +
       
    96 +	for (i = 0; i < len; i++) {
       
    97 +		PyObject *gid = Py_BuildValue("l", (long)groups[i]);
       
    98 +		if (PyList_SetItem(list, i, gid) == -1)
       
    99 +			return (NULL);
       
   100 +	}
       
   101 +
       
   102 +	return (list);
       
   103 +}
       
   104 +
       
   105 +static PyObject *
       
   106 +pyucred_getlabel(pyucred_t *uc)
       
   107 +{
       
   108 +	m_label_t *label;
       
   109 +	PyObject *ret;
       
   110 +	char *str;
       
   111 +
       
   112 +	if (uc->ucred == NULL) {
       
   113 +		errno = EINVAL;
       
   114 +		PyErr_SetFromErrno(PyExc_OSError);
       
   115 +		return (NULL);
       
   116 +	}
       
   117 +
       
   118 +	label = ucred_getlabel(uc->ucred);
       
   119 +	if (label == NULL)
       
   120 +		return (Py_BuildValue("s", ""));
       
   121 +
       
   122 +	if (label_to_str(label, &str, M_LABEL, DEF_NAMES) == -1) {
       
   123 +		PyErr_SetFromErrno(PyExc_OSError);
       
   124 +		return (NULL);
       
   125 +	}
       
   126 +
       
   127 +	ret = Py_BuildValue("s", str);
       
   128 +	free(str);
       
   129 +	return (ret);
       
   130 +}
       
   131 +
       
   132 +static PyObject *
       
   133 +pyucred_getpflags(pyucred_t *uc, PyObject *args, PyObject *kwargs)
       
   134 +{
       
   135 +	static char *kwlist[] = { "flags", NULL };
       
   136 +	uint_t flags;
       
   137 +
       
   138 +	if (uc->ucred == NULL) {
       
   139 +		errno = EINVAL;
       
   140 +		PyErr_SetFromErrno(PyExc_OSError);
       
   141 +		return (NULL);
       
   142 +	}
       
   143 +
       
   144 +	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist,
       
   145 +	    &flags))
       
   146 +		return (NULL);
       
   147 +
       
   148 +	if ((flags = ucred_getpflags(uc->ucred, flags)) == (uint_t)-1) {
       
   149 +		PyErr_SetFromErrno(PyExc_OSError);
       
   150 +		return (NULL);
       
   151 +	}
       
   152 +
       
   153 +	return (Py_BuildValue("i", flags));
       
   154 +}
       
   155 +
       
   156 +static PyObject *
       
   157 +pyucred_has_priv(pyucred_t *uc, PyObject *args, PyObject *kwargs)
       
   158 +{
       
   159 +	static char *kwlist[] = { "set", "priv", NULL };
       
   160 +	const priv_set_t *privs;
       
   161 +	const char *set;
       
   162 +	const char *priv;
       
   163 +
       
   164 +	if (uc->ucred == NULL) {
       
   165 +		errno = EINVAL;
       
   166 +		PyErr_SetFromErrno(PyExc_OSError);
       
   167 +		return (NULL);
       
   168 +	}
       
   169 +
       
   170 +	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss", kwlist,
       
   171 +	    &set, &priv))
       
   172 +		return (NULL);
       
   173 +
       
   174 +	if ((privs = ucred_getprivset(uc->ucred, set)) == NULL) {
       
   175 +		PyErr_SetFromErrno(PyExc_OSError);
       
   176 +		return (NULL);
       
   177 +	}
       
   178 +
       
   179 +	if (priv_ismember(privs, priv)) {
       
   180 +		Py_INCREF(Py_True);
       
   181 +		return Py_True;
       
   182 +	}
       
   183 +
       
   184 +	Py_INCREF(Py_False);
       
   185 +	return Py_False;
       
   186 +}
       
   187 +
       
   188 +PyDoc_STRVAR(pyucred_getlabel_doc,
       
   189 +    "getlabel() -> string\n"
       
   190 +    "\n"
       
   191 +    "Return the Trusted Extensions label string, or an "
       
   192 +    "empty string if not available. The label string is "
       
   193 +    "converted using the default name and M_LABEL (human-readable). "
       
   194 +    "Raises OSError. See label_to_str(3TSOL).");
       
   195 +PyDoc_STRVAR(pyucred_getpflags_doc,
       
   196 +    "getpflags(flags) -> int\n"
       
   197 +    "\n"
       
   198 +    "Return the values of the specified privilege flags.");
       
   199 +PyDoc_STRVAR(pyucred_has_priv_doc,
       
   200 +    "has_priv(set, priv) -> bool\n"
       
   201 +    "\n"
       
   202 +    "Return true if the given privilege is set in the "
       
   203 +    "specified set. Raises OSError if the set or privilege is "
       
   204 +    "invalid, or a problem occurs.\n"
       
   205 +    "\n"
       
   206 +    "Currently, the following privilege sets are defined, as "
       
   207 +    "described in privileges(5):\n"
       
   208 +    "\n"
       
   209 +    "Effective\n"
       
   210 +    "Permitted\n"
       
   211 +    "Inheritable\n"
       
   212 +    "Limit\n");
       
   213 +
       
   214 +static PyMethodDef pyucred_methods[] = {
       
   215 +	{ "geteuid", (PyCFunction)pyucred_geteuid, METH_NOARGS,
       
   216 +	    "Return the effective user ID." },
       
   217 +	{ "getruid", (PyCFunction)pyucred_getruid, METH_NOARGS,
       
   218 +	    "Return the real user ID." },
       
   219 +	{ "getsuid", (PyCFunction)pyucred_getsuid, METH_NOARGS,
       
   220 +	    "Return the saved user ID." },
       
   221 +	{ "getegid", (PyCFunction)pyucred_getegid, METH_NOARGS,
       
   222 +	    "Return the effective group ID." },
       
   223 +	{ "getrgid", (PyCFunction)pyucred_getrgid, METH_NOARGS,
       
   224 +	    "Return the real group ID." },
       
   225 +	{ "getsgid", (PyCFunction)pyucred_getsgid, METH_NOARGS,
       
   226 +	    "Return the saved group ID." },
       
   227 +	{ "getpid", (PyCFunction)pyucred_getpid, METH_NOARGS,
       
   228 +	    "Return the effective user ID." },
       
   229 +	{ "getprojid", (PyCFunction)pyucred_getprojid, METH_NOARGS,
       
   230 +	    "Return the project ID." },
       
   231 +	{ "getzoneid", (PyCFunction)pyucred_getzoneid, METH_NOARGS,
       
   232 +	    "Return the zone ID." },
       
   233 +	{ "getgroups", (PyCFunction)pyucred_getgroups, METH_NOARGS,
       
   234 +	    "Return a list of group IDs." },
       
   235 +	{ "getlabel", (PyCFunction)pyucred_getlabel, METH_NOARGS,
       
   236 +	    pyucred_getlabel_doc },
       
   237 +	{ "getpflags", (PyCFunction)pyucred_getpflags,
       
   238 +	    METH_VARARGS|METH_KEYWORDS, pyucred_getpflags_doc },
       
   239 +	{ "has_priv", (PyCFunction)pyucred_has_priv,
       
   240 +	    METH_VARARGS|METH_KEYWORDS, pyucred_has_priv_doc },
       
   241 +	{ NULL, NULL }
       
   242 +};
       
   243 +
       
   244 +static int
       
   245 +pyucred_init(PyObject *self, PyObject *args, PyObject *kwargs)
       
   246 +{
       
   247 +	pyucred_t *uc = (pyucred_t *)self;
       
   248 +	uc->ucred = NULL;
       
   249 +	return (0);
       
   250 +}
       
   251 +
       
   252 +static void
       
   253 +pyucred_dealloc(PyObject *self)
       
   254 +{
       
   255 +	pyucred_t *uc = (pyucred_t *)self;
       
   256 +	if (uc->ucred != NULL)
       
   257 +		ucred_free(uc->ucred);
       
   258 +	Py_TYPE(self)->tp_free(self);
       
   259 +}
       
   260 +
       
   261 +static PyTypeObject pyucred_type = {
       
   262 +	PyVarObject_HEAD_INIT(NULL, 0)
       
   263 +	"ucred.ucred",             /*tp_name*/
       
   264 +	sizeof (pyucred_t),        /*tp_basicsize*/
       
   265 +	0,                         /*tp_itemsize*/
       
   266 +	pyucred_dealloc,           /*tp_dealloc*/
       
   267 +	0,                         /*tp_print*/
       
   268 +	0,                         /*tp_getattr*/
       
   269 +	0,                         /*tp_setattr*/
       
   270 +	0,                         /*tp_reserved*/
       
   271 +	0,                         /*tp_repr*/
       
   272 +	0,                         /*tp_as_number*/
       
   273 +	0,                         /*tp_as_sequence*/
       
   274 +	0,                         /*tp_as_mapping*/
       
   275 +	0,                         /*tp_hash */
       
   276 +	0,                         /*tp_call*/
       
   277 +	0,                         /*tp_str*/
       
   278 +	0,                         /*tp_getattro*/
       
   279 +	0,                         /*tp_setattro*/
       
   280 +	0,                         /*tp_as_buffer*/
       
   281 +	Py_TPFLAGS_DEFAULT,        /*tp_flags*/
       
   282 +	"user credentials",        /*tp_doc */
       
   283 +	0,		           /* tp_traverse */
       
   284 +	0,		           /* tp_clear */
       
   285 +	0,		           /* tp_richcompare */
       
   286 +	0,		           /* tp_weaklistoffset */
       
   287 +	0,		           /* tp_iter */
       
   288 +	0,		           /* tp_iternext */
       
   289 +	pyucred_methods,           /* tp_methods */
       
   290 +	0,                         /* tp_members */
       
   291 +	0,                         /* tp_getset */
       
   292 +	0,                         /* tp_base */
       
   293 +	0,                         /* tp_dict */
       
   294 +	0,                         /* tp_descr_get */
       
   295 +	0,                         /* tp_descr_set */
       
   296 +	0,                         /* tp_dictoffset */
       
   297 +	(initproc)pyucred_init,    /* tp_init */
       
   298 +	0,                         /* tp_alloc */
       
   299 +	0,                         /* tp_new */
       
   300 +	0,                         /* tp_free */
       
   301 +	0,                         /* tp_is_gc */
       
   302 +};
       
   303 +
       
   304 +static PyObject *
       
   305 +pyucred_new(const ucred_t *uc)
       
   306 +{
       
   307 +	pyucred_t *self;
       
   308 +
       
   309 +	self = (pyucred_t *)PyObject_CallObject((PyObject *)&pyucred_type, NULL);
       
   310 +
       
   311 +	if (self == NULL)
       
   312 +		return (NULL);
       
   313 +
       
   314 +	self->ucred = (ucred_t *)uc;
       
   315 +
       
   316 +	return ((PyObject *)self);
       
   317 +}
       
   318 +
       
   319 +static PyObject *
       
   320 +pyucred_get(PyObject *o, PyObject *args, PyObject *kwargs)
       
   321 +{
       
   322 +	static char *kwlist[] = { "pid", NULL };
       
   323 +	ucred_t *ucred = NULL;
       
   324 +	int pid;
       
   325 +
       
   326 +	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist,
       
   327 +	    &pid))
       
   328 +		return (NULL);
       
   329 +
       
   330 +	ucred = ucred_get(pid);
       
   331 +
       
   332 +	if (ucred == NULL) {
       
   333 +		PyErr_SetFromErrno(PyExc_OSError);
       
   334 +		return (NULL);
       
   335 +	}
       
   336 +
       
   337 +	return (pyucred_new(ucred));
       
   338 +}
       
   339 +
       
   340 +static PyObject *
       
   341 +pyucred_getpeer(PyObject *o, PyObject *args, PyObject *kwargs)
       
   342 +{
       
   343 +	static char *kwlist[] = { "fd", NULL };
       
   344 +	ucred_t *ucred = NULL;
       
   345 +	int fd;
       
   346 +
       
   347 +	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist,
       
   348 +	    &fd))
       
   349 +		return (NULL);
       
   350 +
       
   351 +	if (getpeerucred(fd, &ucred) == -1) {
       
   352 +		PyErr_SetFromErrno(PyExc_OSError);
       
   353 +		return (NULL);
       
   354 +	}
       
   355 +
       
   356 +	return (pyucred_new(ucred));
       
   357 +}
       
   358 +
       
   359 +PyDoc_STRVAR(pyucred_get_doc,
       
   360 +    "get(pid) -> ucred\n"
       
   361 +    "\n"
       
   362 +    "Return the credentials of the specified process ID. "
       
   363 +    "Raises OSError. See ucred_get(3C).");
       
   364 +PyDoc_STRVAR(pyucred_getpeer_doc,
       
   365 +    "getpeer(fd) -> ucred\n"
       
   366 +    "\n"
       
   367 +    "Return the credentials of the peer endpoint of a "
       
   368 +    "connection-oriented socket (SOCK_STREAM) or STREAM fd "
       
   369 +    "at the time the endpoint was created or the connection "
       
   370 +    "was established. Raises OSError. See getpeerucred(3C).");
       
   371 +
       
   372 +static struct PyMethodDef pyucred_module_methods[] = {
       
   373 +	{ "get", (PyCFunction) pyucred_get,
       
   374 +	  METH_VARARGS|METH_KEYWORDS, pyucred_get_doc },
       
   375 +	{ "getpeer", (PyCFunction) pyucred_getpeer,
       
   376 +	  METH_VARARGS|METH_KEYWORDS, pyucred_getpeer_doc },
       
   377 +	{ NULL, NULL, 0, NULL }
       
   378 +};
       
   379 +
       
   380 +PyDoc_STRVAR(pyucred_module_doc,
       
   381 +    "This module provides an interface to the user credential access "
       
   382 +    "methods, obtainable either by process ID or file descriptor.");
       
   383 +
       
   384 +PyMODINIT_FUNC
       
   385 +PyInit_ucred (void)
       
   386 +{
       
   387 +	PyObject *m;
       
   388 +
       
   389 +	static struct PyModuleDef moduledef = {
       
   390 +	    PyModuleDef_HEAD_INIT,
       
   391 +	    "ucred",
       
   392 +	    pyucred_module_doc,
       
   393 +	    -1,
       
   394 +	    pyucred_module_methods,
       
   395 +	    NULL,
       
   396 +	    NULL,
       
   397 +	    NULL,
       
   398 +	    NULL,
       
   399 +	};
       
   400 +
       
   401 +	m = PyModule_Create(&moduledef);
       
   402 +
       
   403 +	pyucred_type.tp_new = PyType_GenericNew;
       
   404 +	if (PyType_Ready(&pyucred_type) < 0)
       
   405 +		return NULL;
       
   406 +
       
   407 +	Py_INCREF(&pyucred_type);
       
   408 +
       
   409 +	PyModule_AddObject(m, "ucred", (PyObject *)&pyucred_type);
       
   410 +
       
   411 +	return m;
       
   412 +}
       
   413 --- Python-3.4.0/setup.py.~3~	2014-03-19 10:44:16.508585670 -0700
       
   414 +++ Python-3.4.0/setup.py	2014-03-19 10:44:16.596735089 -0700
       
   415 @@ -1467,6 +1467,13 @@
       
   416          # Stefan Krah's _decimal module
       
   417          exts.append(self._decimal_ext())
       
   418  
       
   419 +        # ucred module (Solaris)
       
   420 +        ucred_inc = find_file('ucred.h', [], inc_dirs)
       
   421 +        tsol_inc = find_file('tsol/label.h', [], inc_dirs)
       
   422 +        if ucred_inc is not None and tsol_inc is not None:
       
   423 +            exts.append( Extension('ucred', ['ucred.c'],
       
   424 +                                   libraries = ['tsol']) )
       
   425 +
       
   426          # Thomas Heller's _ctypes module
       
   427          self.detect_ctypes(inc_dirs, lib_dirs)
       
   428  
       
   429 --- /dev/null	2011-02-12 03:14:16.000000000 -0600
       
   430 +++ Python-2.6.4/Lib/test/ucredtest.py	2011-01-20 13:52:42.945657919 -0600
       
   431 @@ -0,0 +1,45 @@
       
   432 +#!/usr/bin/python3.4
       
   433 +
       
   434 +import ucred
       
   435 +import os
       
   436 +
       
   437 +uc = ucred.get(os.getpid())
       
   438 +
       
   439 +print("pid = %d" % uc.getpid())
       
   440 +print("euid = %d" % uc.geteuid())
       
   441 +print("ruid = %d" % uc.getruid())
       
   442 +print("suid = %d" % uc.getsuid())
       
   443 +print("egid = %d" % uc.getegid())
       
   444 +print("rgid = %d" % uc.getrgid())
       
   445 +print("sgid = %d" % uc.getsgid())
       
   446 +print("zoneid = %d" % uc.getzoneid())
       
   447 +print("projid = %d" % uc.getprojid())
       
   448 +print("groups = %s" % uc.getgroups())
       
   449 +print("label = %s" % uc.getlabel())
       
   450 +
       
   451 +print("getpflags(0x1) = %d" % uc.getpflags(0x1))
       
   452 +print("getpflags(0x2) = %d" % uc.getpflags(0x2))
       
   453 +print("has_priv(Effective, proc_fork) = %d" % uc.has_priv("Effective", "proc_fork"))
       
   454 +print("has_priv(Permitted, proc_fork) = %d" % uc.has_priv("Permitted", "proc_fork"))
       
   455 +print("has_priv(Inheritable, proc_fork) = %d" % uc.has_priv("Inheritable", "proc_fork"))
       
   456 +print("has_priv(Limit, file_setid) = %d" % uc.has_priv("Limit", "file_setid"))
       
   457 +print("has_priv(Effective, file_setid) = %d" % uc.has_priv("Effective", "file_setid"))
       
   458 +try:
       
   459 +    uc.has_priv("Effective", "proc_bork")
       
   460 +except OSError as e:
       
   461 +    print(e)
       
   462 +try:
       
   463 +    uc.has_priv("Defective", "proc_fork")
       
   464 +except OSError as e:
       
   465 +    print(e)
       
   466 +try:
       
   467 +    uc.has_priv("Defective", "proc_bork")
       
   468 +except OSError as e:
       
   469 +    print(e)
       
   470 +
       
   471 +del uc
       
   472 +uc = ucred.ucred()
       
   473 +try:
       
   474 +    uc.getpid()
       
   475 +except OSError as e:
       
   476 +    print(e)