Alexander Pyhalov
2014-12-13 7b0dcec86c5455046c26524cf1a36c2e9df55fd9
commit | author | age
5b3229 1 This patch provides Python ucred support.  It may be contributed upstream at
AP 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 +}
7b0dce 413 --- Python-3.4.2/setup.py.~3~    2014-09-22 14:12:32.357526710 -0700
AP 414 +++ Python-3.4.2/setup.py    2014-09-22 14:12:32.421969305 -0700
415 @@ -1485,6 +1485,13 @@
5b3229 416          # Stefan Krah's _decimal module
AP 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)