Branch data Line data Source code
1 : : /*
2 : : Authors:
3 : : Jakub Hrozek <jhrozek@redhat.com>
4 : :
5 : : Copyright (C) 2011 Red Hat
6 : :
7 : : This program is free software; you can redistribute it and/or modify
8 : : it under the terms of the GNU General Public License as published by
9 : : the Free Software Foundation; either version 3 of the License, or
10 : : (at your option) any later version.
11 : :
12 : : This program is distributed in the hope that it will be useful,
13 : : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : : GNU General Public License for more details.
16 : :
17 : : You should have received a copy of the GNU General Public License
18 : : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : : */
20 : :
21 : : #include <Python.h>
22 : : #include <structmember.h>
23 : :
24 : : #include "util/util.h"
25 : : #include "util/sss_python.h"
26 : : #include "providers/ipa/ipa_hbac.h"
27 : :
28 : : #define PYTHON_MODULE_NAME "pyhbac"
29 : :
30 : : #ifndef PYHBAC_ENCODING
31 : : #define PYHBAC_ENCODING "UTF-8"
32 : : #endif
33 : :
34 : : #define PYHBAC_ENCODING_ERRORS "strict"
35 : :
36 : : #define CHECK_ATTRIBUTE_DELETE(attr, attrname) do { \
37 : : if (attr == NULL) { \
38 : : PyErr_Format(PyExc_TypeError, \
39 : : "Cannot delete the %s attribute", \
40 : : attrname); \
41 : : return -1; \
42 : : } \
43 : : } while(0)
44 : :
45 : : static PyObject *PyExc_HbacError;
46 : :
47 : : /* ==================== Utility functions ========================*/
48 : : static char *
49 : 87 : py_strdup(const char *string)
50 : : {
51 : : char *copy;
52 : :
53 [ + - ]: 87 : copy = PyMem_New(char, strlen(string)+1);
54 [ - + ]: 87 : if (copy == NULL) {
55 : 0 : PyErr_NoMemory();
56 : 0 : return NULL;
57 : : }
58 : :
59 : 87 : return strcpy(copy, string);
60 : : }
61 : :
62 : : static char *
63 : 2 : py_strcat_realloc(char *first, const char *second)
64 : : {
65 : : char *new_first;
66 : 2 : new_first = PyMem_Realloc(first, strlen(first) + strlen(second) + 1);
67 [ - + ]: 2 : if (new_first == NULL) {
68 : 0 : PyErr_NoMemory();
69 : 0 : return NULL;
70 : : }
71 : :
72 : 2 : return strcat(new_first, second);
73 : : }
74 : :
75 : : static PyObject *
76 : 64 : get_utf8_string(PyObject *obj, const char *attrname)
77 : : {
78 [ + - ]: 64 : const char *a = attrname ? attrname : "attribute";
79 : 64 : PyObject *obj_utf8 = NULL;
80 : :
81 [ + - ]: 64 : if (PyString_Check(obj)) {
82 : 64 : obj_utf8 = obj;
83 : 64 : Py_INCREF(obj_utf8); /* Make sure we can DECREF later */
84 [ # # ]: 0 : } else if (PyUnicode_Check(obj)) {
85 [ # # ]: 0 : if ((obj_utf8 = PyUnicode_AsUTF8String(obj)) == NULL) {
86 : : return NULL;
87 : : }
88 : : } else {
89 : 0 : PyErr_Format(PyExc_TypeError, "%s must be a string", a);
90 : 0 : return NULL;
91 : : }
92 : :
93 : 64 : return obj_utf8;
94 : : }
95 : :
96 : : static void
97 : 91 : free_string_list(const char **list)
98 : : {
99 : : int i;
100 : :
101 [ + - ]: 182 : if (!list) return;
102 : :
103 [ + + ]: 123 : for (i=0; list[i]; i++) {
104 : 32 : PyMem_Free(discard_const_p(char, list[i]));
105 : : }
106 : 91 : PyMem_Free(list);
107 : : }
108 : :
109 : : static const char **
110 : 91 : sequence_as_string_list(PyObject *seq, const char *paramname)
111 : : {
112 [ + - ]: 91 : const char *p = paramname ? paramname : "attribute values";
113 : : const char **ret;
114 : : PyObject *utf_item;
115 : : int i;
116 : : Py_ssize_t len;
117 : : PyObject *item;
118 : :
119 [ - + ]: 91 : if (!PySequence_Check(seq)) {
120 : 0 : PyErr_Format(PyExc_TypeError,
121 : : "The object must be a sequence\n");
122 : 0 : return NULL;
123 : : }
124 : :
125 : 91 : len = PySequence_Size(seq);
126 [ + - ]: 91 : if (len == -1) return NULL;
127 : :
128 [ + - ]: 91 : ret = PyMem_New(const char *, (len+1));
129 [ + - ]: 91 : if (!ret) {
130 : 0 : PyErr_NoMemory();
131 : 0 : return NULL;
132 : : }
133 : :
134 [ + + ]: 123 : for (i = 0; i < len; i++) {
135 : 32 : item = PySequence_GetItem(seq, i);
136 [ + - ]: 32 : if (item == NULL) {
137 : : break;
138 : : }
139 : :
140 : 32 : utf_item = get_utf8_string(item, p);
141 [ + - ]: 32 : if (utf_item == NULL) {
142 : : return NULL;
143 : : }
144 : :
145 : 32 : ret[i] = py_strdup(PyString_AsString(utf_item));
146 [ - + ]: 32 : Py_DECREF(utf_item);
147 [ + - ]: 32 : if (!ret[i]) {
148 : : return NULL;
149 : : }
150 : : }
151 : :
152 : 91 : ret[i] = NULL;
153 : 91 : return ret;
154 : : }
155 : :
156 : : static bool
157 : 41 : verify_sequence(PyObject *seq, const char *attrname)
158 : : {
159 [ + - ]: 41 : const char *a = attrname ? attrname : "attribute";
160 : :
161 [ + + ]: 41 : if (!PySequence_Check(seq)) {
162 : 4 : PyErr_Format(PyExc_TypeError, "%s must be a sequence", a);
163 : 41 : return false;
164 : : }
165 : :
166 : : return true;
167 : : }
168 : :
169 : : static int
170 : 53 : pyobject_to_category(PyObject *o)
171 : : {
172 : : int c;
173 : :
174 : 53 : c = PyInt_AsLong(o);
175 [ + + ][ - + ]: 53 : if (c == -1 && PyErr_Occurred()) {
176 : 0 : PyErr_Format(PyExc_TypeError,
177 : : "Invalid type for category element - must be an int\n");
178 : 0 : return -1;
179 : : }
180 : :
181 [ + + ]: 53 : switch (c) {
182 : : case HBAC_CATEGORY_NULL:
183 : : case HBAC_CATEGORY_ALL:
184 : : return c;
185 : : }
186 : :
187 : 1 : PyErr_Format(PyExc_ValueError, "Invalid value %d for category\n", c);
188 : 53 : return -1;
189 : : }
190 : :
191 : : static uint32_t
192 : 48 : native_category(PyObject *pycat)
193 : : {
194 : : PyObject *iterator;
195 : : PyObject *item;
196 : : uint32_t cat;
197 : : int ret;
198 : :
199 : 48 : iterator = PyObject_GetIter(pycat);
200 [ + - ]: 48 : if (iterator == NULL) {
201 : 0 : PyErr_Format(PyExc_RuntimeError, "Cannot iterate category\n");
202 : 0 : return -1;
203 : : }
204 : :
205 : : cat = 0;
206 [ + + ]: 98 : while ((item = PyIter_Next(iterator))) {
207 : 51 : ret = pyobject_to_category(item);
208 [ - + ]: 51 : Py_DECREF(item);
209 [ + + ]: 51 : if (ret == -1) {
210 [ + - ]: 1 : Py_DECREF(iterator);
211 : : return -1;
212 : : }
213 : :
214 : 50 : cat |= ret;
215 : : }
216 : :
217 [ + - ]: 47 : Py_DECREF(iterator);
218 : 48 : return cat;
219 : : }
220 : :
221 : : static char *
222 : 30 : str_concat_sequence(PyObject *seq, const char *delim)
223 : : {
224 : : Py_ssize_t size;
225 : : Py_ssize_t i;
226 : : PyObject *item;
227 : 30 : char *s = NULL;
228 : : char *part;
229 : :
230 : 30 : size = PySequence_Size(seq);
231 : :
232 [ + + ]: 30 : if (size == 0) {
233 : 23 : s = py_strdup("");
234 [ + - ]: 23 : if (s == NULL) {
235 : : return NULL;
236 : : }
237 : 23 : return s;
238 : : }
239 : :
240 [ + + ]: 15 : for (i=0; i < size; i++) {
241 : 8 : item = PySequence_GetItem(seq, i);
242 [ + - ]: 8 : if (item == NULL) goto fail;
243 : :
244 : 8 : part = PyString_AsString(item);
245 [ - + ]: 8 : if (part == NULL) {
246 [ # # ]: 0 : Py_DECREF(item);
247 : : goto fail;
248 : : }
249 : :
250 [ + + ]: 8 : if (s) {
251 : 1 : s = py_strcat_realloc(s, delim);
252 [ + - ]: 1 : if (s == NULL) goto fail;
253 : 1 : s = py_strcat_realloc(s, part);
254 [ + - ]: 1 : if (s == NULL) goto fail;
255 : : } else {
256 : 7 : s = py_strdup(part);
257 [ + - ]: 7 : if (s == NULL) goto fail;
258 : : }
259 [ - + ]: 8 : Py_DECREF(item);
260 : : }
261 : :
262 : : return s;
263 : : fail:
264 : 0 : PyMem_Free(s);
265 : 30 : return NULL;
266 : : }
267 : :
268 : : /* ================= HBAC Exception handling =====================*/
269 : : static void
270 : 0 : set_hbac_exception(PyObject *exc, struct hbac_info *error)
271 : : {
272 [ # # ]: 0 : PyErr_SetObject(exc,
273 : : Py_BuildValue(sss_py_const_p(char, "(i,s)"),
274 : 0 : error->code,
275 : 0 : error->rule_name ? \
276 : : error->rule_name : "no rule"));
277 : 0 : }
278 : :
279 : : /* ==================== HBAC Rule Element ========================*/
280 : : typedef struct {
281 : : PyObject_HEAD
282 : :
283 : : PyObject *category;
284 : : PyObject *names;
285 : : PyObject *groups;
286 : : } HbacRuleElement;
287 : :
288 : : static PyObject *
289 : 53 : HbacRuleElement_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
290 : : {
291 : : HbacRuleElement *self;
292 : :
293 : 53 : self = (HbacRuleElement *) type->tp_alloc(type, 0);
294 [ - + ]: 53 : if (self == NULL) {
295 : 0 : PyErr_NoMemory();
296 : 0 : return NULL;
297 : : }
298 : :
299 : 53 : self->category = sss_python_set_new();
300 : 53 : self->names = PyList_New(0);
301 : 53 : self->groups = PyList_New(0);
302 [ + - ][ + - ]: 53 : if (!self->names || !self->groups || !self->category) {
[ - + ]
303 [ # # ]: 0 : Py_DECREF(self);
304 : 0 : PyErr_NoMemory();
305 : 53 : return NULL;
306 : : }
307 : :
308 : : return (PyObject *) self;
309 : : }
310 : :
311 : : static int
312 : 46 : HbacRuleElement_clear(HbacRuleElement *self)
313 : : {
314 [ + - ][ + + ]: 46 : Py_CLEAR(self->names);
315 [ + - ][ + + ]: 46 : Py_CLEAR(self->groups);
316 [ + - ][ + + ]: 46 : Py_CLEAR(self->category);
317 : 46 : return 0;
318 : : }
319 : :
320 : : static void
321 : 46 : HbacRuleElement_dealloc(HbacRuleElement *self)
322 : : {
323 : 46 : HbacRuleElement_clear(self);
324 : 46 : self->ob_type->tp_free((PyObject*) self);
325 : 46 : }
326 : :
327 : : static int
328 : 14 : HbacRuleElement_traverse(HbacRuleElement *self, visitproc visit, void *arg)
329 : : {
330 [ + - ][ + - ]: 14 : Py_VISIT(self->groups);
331 [ + - ][ + - ]: 14 : Py_VISIT(self->names);
332 [ + - ][ - + ]: 14 : Py_VISIT(self->category);
333 : : return 0;
334 : : }
335 : :
336 : : static int
337 : : hbac_rule_element_set_names(HbacRuleElement *self, PyObject *names,
338 : : void *closure);
339 : : static int
340 : : hbac_rule_element_set_groups(HbacRuleElement *self, PyObject *groups,
341 : : void *closure);
342 : : static int
343 : : hbac_rule_element_set_category(HbacRuleElement *self, PyObject *category,
344 : : void *closure);
345 : :
346 : : static int
347 : 53 : HbacRuleElement_init(HbacRuleElement *self, PyObject *args, PyObject *kwargs)
348 : : {
349 : 53 : const char * const kwlist[] = { "names", "groups", "category", NULL };
350 : 53 : PyObject *names = NULL;
351 : 53 : PyObject *groups = NULL;
352 : 53 : PyObject *category = NULL;
353 : 53 : PyObject *tmp = NULL;
354 : :
355 [ + - ]: 53 : if (!PyArg_ParseTupleAndKeywords(args, kwargs,
356 : : sss_py_const_p(char, "|OOO"),
357 : : discard_const_p(char *, kwlist),
358 : : &names, &groups, &category)) {
359 : : return -1;
360 : : }
361 : :
362 [ + + ]: 53 : if (names) {
363 [ + + ]: 6 : if (hbac_rule_element_set_names(self, names, NULL) != 0) {
364 : : return -1;
365 : : }
366 : : }
367 : :
368 [ + + ]: 51 : if (groups) {
369 [ + - ]: 4 : if (hbac_rule_element_set_groups(self, groups, NULL) != 0) {
370 : : return -1;
371 : : }
372 : : }
373 : :
374 [ - + ]: 51 : if (category) {
375 [ # # ]: 0 : if (hbac_rule_element_set_category(self, category, NULL) != 0) {
376 : : return -1;
377 : : }
378 : : } else {
379 : 51 : tmp = PyInt_FromLong(HBAC_CATEGORY_NULL);
380 [ + - ]: 51 : if (!tmp) {
381 : : return -1;
382 : : }
383 : :
384 [ - + ]: 51 : if (sss_python_set_add(self->category, tmp) != 0) {
385 [ # # ]: 53 : Py_DECREF(tmp);
386 : : return -1;
387 : : }
388 : : }
389 : :
390 : : return 0;
391 : : }
392 : :
393 : : static int
394 : 25 : hbac_rule_element_set_names(HbacRuleElement *self,
395 : : PyObject *names,
396 : : void *closure)
397 : : {
398 [ - + ]: 25 : CHECK_ATTRIBUTE_DELETE(names, "names");
399 : :
400 [ + + ]: 25 : if (!verify_sequence(names, "names")) {
401 : : return -1;
402 : : }
403 : :
404 [ + - ][ + - ]: 25 : SAFE_SET(self->names, names);
405 : : return 0;
406 : : }
407 : :
408 : : static PyObject *
409 : 10 : hbac_rule_element_get_names(HbacRuleElement *self, void *closure)
410 : : {
411 : 10 : Py_INCREF(self->names);
412 : 10 : return self->names;
413 : : }
414 : :
415 : : static int
416 : 8 : hbac_rule_element_set_groups(HbacRuleElement *self,
417 : : PyObject *groups,
418 : : void *closure)
419 : : {
420 [ - + ]: 8 : CHECK_ATTRIBUTE_DELETE(groups, "groups");
421 : :
422 [ + - ]: 8 : if (!verify_sequence(groups, "groups")) {
423 : : return -1;
424 : : }
425 : :
426 [ + - ][ + - ]: 8 : SAFE_SET(self->groups, groups);
427 : : return 0;
428 : : }
429 : :
430 : : static PyObject *
431 : 12 : hbac_rule_element_get_groups(HbacRuleElement *self, void *closure)
432 : : {
433 : 12 : Py_INCREF(self->groups);
434 : 12 : return self->groups;
435 : : }
436 : :
437 : : static int
438 : 5 : hbac_rule_element_set_category(HbacRuleElement *self,
439 : : PyObject *category,
440 : : void *closure)
441 : : {
442 : : PyObject *iterator;
443 : : PyObject *item;
444 : : int ret;
445 : :
446 [ - + ]: 5 : CHECK_ATTRIBUTE_DELETE(category, "category");
447 : :
448 [ + + ]: 5 : if (!sss_python_set_check(category)) {
449 : 3 : PyErr_Format(PyExc_TypeError, "The category must be a set type\n");
450 : 3 : return -1;
451 : : }
452 : :
453 : : /* Check the values, too */
454 : 2 : iterator = PyObject_GetIter(category);
455 [ - + ]: 2 : if (iterator == NULL) {
456 : 0 : PyErr_Format(PyExc_RuntimeError, "Cannot iterate a set?\n");
457 : 0 : return -1;
458 : : }
459 : :
460 [ + + ]: 4 : while ((item = PyIter_Next(iterator))) {
461 : 2 : ret = pyobject_to_category(item);
462 [ - + ]: 2 : Py_DECREF(item);
463 [ - + ]: 2 : if (ret == -1) {
464 [ # # ]: 2 : Py_DECREF(iterator);
465 : : return -1;
466 : : }
467 : : }
468 : :
469 [ + - ][ + - ]: 2 : SAFE_SET(self->category, category);
470 [ + - ]: 5 : Py_DECREF(iterator);
471 : : return 0;
472 : : }
473 : :
474 : : static PyObject *
475 : 10 : hbac_rule_element_get_category(HbacRuleElement *self, void *closure)
476 : : {
477 : 10 : Py_INCREF(self->category);
478 : 10 : return self->category;
479 : : }
480 : :
481 : : static PyObject *
482 : 10 : HbacRuleElement_repr(HbacRuleElement *self)
483 : : {
484 : 10 : char *strnames = NULL;
485 : 10 : char *strgroups = NULL;
486 : : uint32_t category;
487 : : PyObject *o, *format, *args;
488 : :
489 : 10 : format = sss_python_unicode_from_string("<category %lu names [%s] groups [%s]>");
490 [ + - ]: 10 : if (format == NULL) {
491 : : return NULL;
492 : : }
493 : :
494 : 10 : strnames = str_concat_sequence(self->names,
495 : : discard_const_p(char, ","));
496 : 10 : strgroups = str_concat_sequence(self->groups,
497 : : discard_const_p(char, ","));
498 : 10 : category = native_category(self->category);
499 [ + - ][ - + ]: 10 : if (strnames == NULL || strgroups == NULL || category == -1) {
500 : 0 : PyMem_Free(strnames);
501 : 0 : PyMem_Free(strgroups);
502 [ # # ]: 0 : Py_DECREF(format);
503 : : return NULL;
504 : : }
505 : :
506 : 10 : args = Py_BuildValue(sss_py_const_p(char, "Kss"),
507 : : (unsigned long long ) category,
508 : : strnames, strgroups);
509 [ - + ]: 10 : if (args == NULL) {
510 : 0 : PyMem_Free(strnames);
511 : 0 : PyMem_Free(strgroups);
512 [ # # ]: 0 : Py_DECREF(format);
513 : : return NULL;
514 : : }
515 : :
516 : 10 : o = PyUnicode_Format(format, args);
517 : 10 : PyMem_Free(strnames);
518 : 10 : PyMem_Free(strgroups);
519 [ + - ]: 10 : Py_DECREF(format);
520 [ + - ]: 10 : Py_DECREF(args);
521 : 10 : return o;
522 : : }
523 : :
524 : : PyDoc_STRVAR(HbacRuleElement_names__doc__,
525 : : "(sequence of strings) A list of object names this element applies to");
526 : : PyDoc_STRVAR(HbacRuleElement_groups__doc__,
527 : : "(sequence of strings) A list of group names this element applies to");
528 : : PyDoc_STRVAR(HbacRuleElement_category__doc__,
529 : : "(set) A set of categories this rule falls into");
530 : :
531 : : static PyGetSetDef py_hbac_rule_element_getset[] = {
532 : : { discard_const_p(char, "names"),
533 : : (getter) hbac_rule_element_get_names,
534 : : (setter) hbac_rule_element_set_names,
535 : : HbacRuleElement_names__doc__,
536 : : NULL },
537 : :
538 : : { discard_const_p(char, "groups"),
539 : : (getter) hbac_rule_element_get_groups,
540 : : (setter) hbac_rule_element_set_groups,
541 : : HbacRuleElement_groups__doc__,
542 : : NULL },
543 : :
544 : : { discard_const_p(char, "category"),
545 : : (getter) hbac_rule_element_get_category,
546 : : (setter) hbac_rule_element_set_category,
547 : : HbacRuleElement_category__doc__,
548 : : NULL },
549 : :
550 : : { NULL, 0, 0, 0, NULL } /* Sentinel */
551 : : };
552 : :
553 : : PyDoc_STRVAR(HbacRuleElement__doc__,
554 : : "IPA HBAC Rule Element\n\n"
555 : : "HbacRuleElement() -> new empty rule element\n"
556 : : "HbacRuleElement([names], [groups], [category]) -> optionally, provide\n"
557 : : "names and/or groups and/or category\n");
558 : :
559 : : static PyTypeObject pyhbac_hbacrule_element_type = {
560 : : PyObject_HEAD_INIT(NULL)
561 : : .tp_name = sss_py_const_p(char, "pyhbac.HbacRuleElement"),
562 : : .tp_basicsize = sizeof(HbacRuleElement),
563 : : .tp_new = HbacRuleElement_new,
564 : : .tp_dealloc = (destructor) HbacRuleElement_dealloc,
565 : : .tp_traverse = (traverseproc) HbacRuleElement_traverse,
566 : : .tp_clear = (inquiry) HbacRuleElement_clear,
567 : : .tp_init = (initproc) HbacRuleElement_init,
568 : : .tp_repr = (reprfunc) HbacRuleElement_repr,
569 : : .tp_getset = py_hbac_rule_element_getset,
570 : : .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
571 : : .tp_doc = HbacRuleElement__doc__
572 : : };
573 : :
574 : : static void
575 : 43 : free_hbac_rule_element(struct hbac_rule_element *el)
576 : : {
577 [ + + ]: 81 : if (!el) return;
578 : :
579 : 38 : free_string_list(el->names);
580 : 38 : free_string_list(el->groups);
581 : 38 : PyMem_Free(el);
582 : : }
583 : :
584 : : struct hbac_rule_element *
585 : 40 : HbacRuleElement_to_native(HbacRuleElement *pyel)
586 : : {
587 : 40 : struct hbac_rule_element *el = NULL;
588 : :
589 : : /* check the type, None would wreak havoc here because for some reason
590 : : * it would pass the sequence check */
591 [ + + ]: 40 : if (!PyObject_IsInstance((PyObject *) pyel,
592 : : (PyObject *) &pyhbac_hbacrule_element_type)) {
593 : 2 : PyErr_Format(PyExc_TypeError,
594 : : "The element must be of type HbacRuleElement\n");
595 : 2 : goto fail;
596 : : }
597 : :
598 : 38 : el = PyMem_Malloc(sizeof(struct hbac_rule_element));
599 [ - + ]: 38 : if (!el) {
600 : 0 : PyErr_NoMemory();
601 : 0 : goto fail;
602 : : }
603 : :
604 : 38 : el->category = native_category(pyel->category);
605 : 38 : el->names = sequence_as_string_list(pyel->names, "names");
606 : 38 : el->groups = sequence_as_string_list(pyel->groups, "groups");
607 [ + - ][ + - ]: 38 : if (!el->names || !el->groups || el->category == -1) {
[ + + ]
608 : : goto fail;
609 : : }
610 : :
611 : : return el;
612 : :
613 : : fail:
614 : 3 : free_hbac_rule_element(el);
615 : 40 : return NULL;
616 : : }
617 : :
618 : : /* ==================== HBAC Rule ========================*/
619 : : typedef struct {
620 : : PyObject_HEAD
621 : :
622 : : PyObject *name;
623 : : bool enabled;
624 : :
625 : : HbacRuleElement *users;
626 : : HbacRuleElement *services;
627 : : HbacRuleElement *targethosts;
628 : : HbacRuleElement *srchosts;
629 : : } HbacRuleObject;
630 : :
631 : : static void
632 : : free_hbac_rule(struct hbac_rule *rule);
633 : : static struct hbac_rule *
634 : : HbacRule_to_native(HbacRuleObject *pyrule);
635 : :
636 : : static PyObject *
637 : 10 : HbacRule_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
638 : : {
639 : : HbacRuleObject *self;
640 : :
641 : 10 : self = (HbacRuleObject *) type->tp_alloc(type, 0);
642 [ - + ]: 10 : if (self == NULL) {
643 : 0 : PyErr_NoMemory();
644 : 0 : return NULL;
645 : : }
646 : :
647 : 10 : self->name = sss_python_unicode_from_string("");
648 [ - + ]: 10 : if (self->name == NULL) {
649 [ # # ]: 0 : Py_DECREF(self);
650 : 0 : PyErr_NoMemory();
651 : 0 : return NULL;
652 : : }
653 : :
654 : 10 : self->enabled = false;
655 : :
656 : 10 : self->services = (HbacRuleElement *) HbacRuleElement_new(
657 : : &pyhbac_hbacrule_element_type,
658 : : NULL, NULL);
659 : 10 : self->users = (HbacRuleElement *) HbacRuleElement_new(
660 : : &pyhbac_hbacrule_element_type,
661 : : NULL, NULL);
662 : 10 : self->targethosts = (HbacRuleElement *) HbacRuleElement_new(
663 : : &pyhbac_hbacrule_element_type,
664 : : NULL, NULL);
665 : 10 : self->srchosts = (HbacRuleElement *) HbacRuleElement_new(
666 : : &pyhbac_hbacrule_element_type,
667 : : NULL, NULL);
668 [ + - ][ + - ]: 10 : if (self->services == NULL || self->users == NULL ||
[ + - ]
669 [ - + ]: 10 : self->targethosts == NULL || self->srchosts == NULL) {
670 [ # # ][ # # ]: 0 : Py_XDECREF(self->services);
671 [ # # ][ # # ]: 0 : Py_XDECREF(self->users);
672 [ # # ][ # # ]: 0 : Py_XDECREF(self->targethosts);
673 [ # # ][ # # ]: 0 : Py_XDECREF(self->srchosts);
674 [ # # ]: 0 : Py_DECREF(self->name);
675 [ # # ]: 0 : Py_DECREF(self);
676 : 0 : PyErr_NoMemory();
677 : 10 : return NULL;
678 : : }
679 : :
680 : : return (PyObject *) self;
681 : : }
682 : :
683 : : static int
684 : 8 : HbacRule_clear(HbacRuleObject *self)
685 : : {
686 [ + - ][ - + ]: 8 : Py_CLEAR(self->name);
687 [ + - ][ + - ]: 8 : Py_CLEAR(self->services);
688 [ + - ][ + + ]: 8 : Py_CLEAR(self->users);
689 [ + - ][ + - ]: 8 : Py_CLEAR(self->targethosts);
690 [ + - ][ + - ]: 8 : Py_CLEAR(self->srchosts);
691 : 8 : return 0;
692 : : }
693 : :
694 : : static void
695 : 8 : HbacRule_dealloc(HbacRuleObject *self)
696 : : {
697 : 8 : HbacRule_clear(self);
698 : 8 : self->ob_type->tp_free((PyObject*) self);
699 : 8 : }
700 : :
701 : : static int
702 : 4 : HbacRule_traverse(HbacRuleObject *self, visitproc visit, void *arg)
703 : : {
704 [ + - ][ + - ]: 4 : Py_VISIT((PyObject *) self->name);
705 [ + - ][ + - ]: 4 : Py_VISIT((PyObject *) self->services);
706 [ + - ][ + - ]: 4 : Py_VISIT((PyObject *) self->users);
707 [ + - ][ + - ]: 4 : Py_VISIT((PyObject *) self->targethosts);
708 [ + - ][ - + ]: 4 : Py_VISIT((PyObject *) self->srchosts);
709 : : return 0;
710 : : }
711 : :
712 : : static int
713 : : hbac_rule_set_enabled(HbacRuleObject *self, PyObject *enabled, void *closure);
714 : : static int
715 : : hbac_rule_set_name(HbacRuleObject *self, PyObject *name, void *closure);
716 : :
717 : : static int
718 : 10 : HbacRule_init(HbacRuleObject *self, PyObject *args, PyObject *kwargs)
719 : : {
720 : 10 : const char * const kwlist[] = { "name", "enabled", NULL };
721 : 10 : PyObject *name = NULL;
722 : 10 : PyObject *empty_tuple = NULL;
723 : 10 : PyObject *enabled=NULL;
724 : :
725 [ + - ]: 10 : if (!PyArg_ParseTupleAndKeywords(args, kwargs,
726 : : sss_py_const_p(char, "O|O"),
727 : : discard_const_p(char *, kwlist),
728 : : &name, &enabled)) {
729 : : return -1;
730 : : }
731 : :
732 [ + + ]: 10 : if (enabled) {
733 [ + - ]: 2 : if (hbac_rule_set_enabled(self, enabled, NULL) == -1) {
734 : : return -1;
735 : : }
736 : : }
737 : :
738 [ + - ]: 10 : if (hbac_rule_set_name(self, name, NULL) == -1) {
739 : : return -1;
740 : : }
741 : :
742 : 10 : empty_tuple = PyTuple_New(0);
743 [ + - ]: 10 : if (!empty_tuple) {
744 : : return -1;
745 : : }
746 : :
747 [ + - + - ]: 20 : if (HbacRuleElement_init(self->users, empty_tuple, NULL) == -1 ||
748 [ + - ]: 20 : HbacRuleElement_init(self->services, empty_tuple, NULL) == -1 ||
749 [ - + ]: 20 : HbacRuleElement_init(self->targethosts, empty_tuple, NULL) == -1 ||
750 : 10 : HbacRuleElement_init(self->srchosts, empty_tuple, NULL) == -1) {
751 [ # # ]: 0 : Py_DECREF(empty_tuple);
752 : : return -1;
753 : : }
754 : :
755 [ - + ]: 10 : Py_DECREF(empty_tuple);
756 : : return 0;
757 : : }
758 : :
759 : : static int
760 : 16 : hbac_rule_set_enabled(HbacRuleObject *self, PyObject *enabled, void *closure)
761 : : {
762 [ - + ]: 16 : CHECK_ATTRIBUTE_DELETE(enabled, "enabled");
763 : :
764 [ + + ]: 16 : if (PyString_Check(enabled) || PyUnicode_Check(enabled)) {
765 : : PyObject *utf8_str;
766 : : char *str;
767 : :
768 : 7 : utf8_str = get_utf8_string(enabled, "enabled");
769 [ + - ]: 7 : if (!utf8_str) return -1;
770 : 7 : str = PyString_AsString(utf8_str);
771 [ - + ]: 7 : if (!str) {
772 [ # # ]: 0 : Py_DECREF(utf8_str);
773 : : return -1;
774 : : }
775 : :
776 [ + + ]: 7 : if (strcasecmp(str, "true") == 0) {
777 : 3 : self->enabled = true;
778 [ + + ]: 4 : } else if (strcasecmp(str, "false") == 0) {
779 : 3 : self->enabled = false;
780 : : } else {
781 : 1 : PyErr_Format(PyExc_ValueError,
782 : : "enabled only accepts 'true' of 'false' "
783 : : "string literals");
784 [ - + ]: 1 : Py_DECREF(utf8_str);
785 : : return -1;
786 : : }
787 : :
788 [ - + ]: 6 : Py_DECREF(utf8_str);
789 : : return 0;
790 [ + + ]: 9 : } else if (PyBool_Check(enabled)) {
791 : 4 : self->enabled = (enabled == Py_True);
792 : 4 : return 0;
793 [ + + ]: 5 : } else if (PyInt_Check(enabled)) {
794 [ + + + ]: 3 : switch(PyInt_AsLong(enabled)) {
795 : : case 0:
796 : 1 : self->enabled = false;
797 : 1 : break;
798 : : case 1:
799 : 1 : self->enabled = true;
800 : 1 : break;
801 : : default:
802 : 1 : PyErr_Format(PyExc_ValueError,
803 : : "enabled only accepts '0' of '1' "
804 : : "integer constants");
805 : 1 : return -1;
806 : : }
807 : : return 0;
808 : : }
809 : :
810 : 2 : PyErr_Format(PyExc_TypeError, "enabled must be a boolean, an integer "
811 : : "1 or 0 or a string constant true/false");
812 : 16 : return -1;
813 : :
814 : : }
815 : :
816 : : static PyObject *
817 : 10 : hbac_rule_get_enabled(HbacRuleObject *self, void *closure)
818 : : {
819 [ + + ]: 10 : if (self->enabled) {
820 : 5 : Py_RETURN_TRUE;
821 : : }
822 : :
823 : 10 : Py_RETURN_FALSE;
824 : : }
825 : :
826 : : static int
827 : 11 : hbac_rule_set_name(HbacRuleObject *self, PyObject *name, void *closure)
828 : : {
829 [ - + ]: 11 : CHECK_ATTRIBUTE_DELETE(name, "name");
830 : :
831 [ - + ]: 11 : if (!PyString_Check(name) && !PyUnicode_Check(name)) {
832 : 0 : PyErr_Format(PyExc_TypeError, "name must be a string or Unicode");
833 : 0 : return -1;
834 : : }
835 : :
836 [ + - ][ - + ]: 11 : SAFE_SET(self->name, name);
837 : : return 0;
838 : : }
839 : :
840 : : static PyObject *
841 : 2 : hbac_rule_get_name(HbacRuleObject *self, void *closure)
842 : : {
843 [ - + ]: 2 : if (PyUnicode_Check(self->name)) {
844 : 0 : Py_INCREF(self->name);
845 : 0 : return self->name;
846 [ + - ]: 2 : } else if (PyString_Check(self->name)) {
847 : 2 : return PyUnicode_FromEncodedObject(self->name,
848 : : PYHBAC_ENCODING, PYHBAC_ENCODING_ERRORS);
849 : : }
850 : :
851 : : /* setter does typechecking but let us be paranoid */
852 : 0 : PyErr_Format(PyExc_TypeError, "name must be a string or Unicode");
853 : 2 : return NULL;
854 : : }
855 : :
856 : : static PyObject *
857 : 2 : HbacRule_repr(HbacRuleObject *self)
858 : : {
859 : : PyObject *users_repr;
860 : : PyObject *services_repr;
861 : : PyObject *targethosts_repr;
862 : : PyObject *srchosts_repr;
863 : : PyObject *o, *format, *args;
864 : :
865 : 2 : format = sss_python_unicode_from_string("<name %s enabled %d "
866 : : "users %s services %s "
867 : : "targethosts %s srchosts %s>");
868 [ + - ]: 2 : if (format == NULL) {
869 : : return NULL;
870 : : }
871 : :
872 : 2 : users_repr = HbacRuleElement_repr(self->users);
873 : 2 : services_repr = HbacRuleElement_repr(self->services);
874 : 2 : targethosts_repr = HbacRuleElement_repr(self->targethosts);
875 : 2 : srchosts_repr = HbacRuleElement_repr(self->srchosts);
876 [ + - ]: 2 : if (users_repr == NULL || services_repr == NULL ||
877 [ - + ]: 2 : targethosts_repr == NULL || srchosts_repr == NULL) {
878 [ # # ][ # # ]: 0 : Py_XDECREF(users_repr);
879 [ # # ][ # # ]: 0 : Py_XDECREF(services_repr);
880 [ # # ][ # # ]: 0 : Py_XDECREF(targethosts_repr);
881 [ # # ][ # # ]: 0 : Py_XDECREF(srchosts_repr);
882 [ # # ]: 0 : Py_DECREF(format);
883 : : return NULL;
884 : : }
885 : :
886 : 2 : args = Py_BuildValue(sss_py_const_p(char, "OiOOOO"),
887 : 2 : self->name, self->enabled,
888 : : users_repr, services_repr,
889 : : targethosts_repr, srchosts_repr);
890 [ - + ]: 2 : if (args == NULL) {
891 [ # # ]: 0 : Py_DECREF(users_repr);
892 [ # # ]: 0 : Py_DECREF(services_repr);
893 [ # # ]: 0 : Py_DECREF(targethosts_repr);
894 [ # # ]: 0 : Py_DECREF(srchosts_repr);
895 [ # # ]: 0 : Py_DECREF(format);
896 : : return NULL;
897 : : }
898 : :
899 : 2 : o = PyUnicode_Format(format, args);
900 [ - + ]: 2 : Py_DECREF(users_repr);
901 [ - + ]: 2 : Py_DECREF(services_repr);
902 [ - + ]: 2 : Py_DECREF(targethosts_repr);
903 [ - + ]: 2 : Py_DECREF(srchosts_repr);
904 [ + - ]: 2 : Py_DECREF(format);
905 [ + - ]: 2 : Py_DECREF(args);
906 : 2 : return o;
907 : : }
908 : :
909 : : static PyObject *
910 : 3 : py_hbac_rule_validate(HbacRuleObject *self, PyObject *args)
911 : : {
912 : : struct hbac_rule *rule;
913 : : bool is_valid;
914 : : uint32_t missing;
915 : : uint32_t attr;
916 : 3 : PyObject *ret = NULL;
917 : 3 : PyObject *py_is_valid = NULL;
918 : 3 : PyObject *py_missing = NULL;
919 : 3 : PyObject *py_attr = NULL;
920 : :
921 : 3 : rule = HbacRule_to_native(self);
922 [ - + ]: 3 : if (!rule) {
923 : : /* Make sure there is at least a generic exception */
924 [ # # ]: 0 : if (!PyErr_Occurred()) {
925 : 0 : PyErr_Format(PyExc_IOError,
926 : : "Could not convert HbacRule to native type\n");
927 : : }
928 : : goto fail;
929 : : }
930 : :
931 : 3 : is_valid = hbac_rule_is_complete(rule, &missing);
932 : 3 : free_hbac_rule(rule);
933 : :
934 : 3 : ret = PyTuple_New(2);
935 [ - + ]: 3 : if (!ret) {
936 : 0 : PyErr_NoMemory();
937 : : goto fail;
938 : : }
939 : :
940 : 3 : py_is_valid = PyBool_FromLong(is_valid);
941 : 3 : py_missing = sss_python_set_new();
942 [ + - ]: 3 : if (!py_missing || !py_is_valid) {
943 : 0 : PyErr_NoMemory();
944 : : goto fail;
945 : : }
946 : :
947 [ + + ]: 15 : for (attr = HBAC_RULE_ELEMENT_USERS;
948 : : attr <= HBAC_RULE_ELEMENT_SOURCEHOSTS;
949 : 12 : attr <<= 1) {
950 [ + + ]: 12 : if (!(missing & attr)) continue;
951 : :
952 : 6 : py_attr = PyInt_FromLong(attr);
953 [ - + ]: 6 : if (!py_attr) {
954 : 0 : PyErr_NoMemory();
955 : : goto fail;
956 : : }
957 : :
958 [ - + ]: 6 : if (sss_python_set_add(py_missing, py_attr) != 0) {
959 : : /* If the set-add succeeded, it would steal the reference */
960 [ # # ]: 0 : Py_DECREF(py_attr);
961 : : goto fail;
962 : : }
963 : : }
964 : :
965 : 3 : PyTuple_SET_ITEM(ret, 0, py_is_valid);
966 : 3 : PyTuple_SET_ITEM(ret, 1, py_missing);
967 : : return ret;
968 : :
969 : : fail:
970 [ # # ][ # # ]: 0 : Py_XDECREF(ret);
971 [ # # ][ # # ]: 0 : Py_XDECREF(py_missing);
972 [ # # ][ # # ]: 3 : Py_XDECREF(py_is_valid);
973 : : return NULL;
974 : : }
975 : :
976 : : PyDoc_STRVAR(py_hbac_rule_validate__doc__,
977 : : "validate() -> (valid, missing)\n\n"
978 : : "Validate an HBAC rule\n"
979 : : "Returns a tuple of (bool, set). The boolean value describes whether\n"
980 : : "the rule is valid. If it is False, then the set lists all the missing "
981 : : "rule elements as HBAC_RULE_ELEMENT_* constants\n");
982 : :
983 : : static PyMethodDef py_hbac_rule_methods[] = {
984 : : { sss_py_const_p(char, "validate"),
985 : : (PyCFunction) py_hbac_rule_validate,
986 : : METH_VARARGS, py_hbac_rule_validate__doc__,
987 : : },
988 : : { NULL, NULL, 0, NULL } /* Sentinel */
989 : : };
990 : :
991 : : PyDoc_STRVAR(HbacRuleObject_users__doc__,
992 : : "(HbacRuleElement) Users and user groups for which this rule applies");
993 : : PyDoc_STRVAR(HbacRuleObject_services__doc__,
994 : : "(HbacRuleElement) Services and service groups for which this rule applies");
995 : : PyDoc_STRVAR(HbacRuleObject_targethosts__doc__,
996 : : "(HbacRuleElement) Target hosts for which this rule applies");
997 : : PyDoc_STRVAR(HbacRuleObject_srchosts__doc__,
998 : : "(HbacRuleElement) Source hosts for which this rule applies");
999 : :
1000 : : static PyMemberDef py_hbac_rule_members[] = {
1001 : : { discard_const_p(char, "users"), T_OBJECT_EX,
1002 : : offsetof(HbacRuleObject, users), 0,
1003 : : HbacRuleObject_users__doc__ },
1004 : :
1005 : : { discard_const_p(char, "services"), T_OBJECT_EX,
1006 : : offsetof(HbacRuleObject, services), 0,
1007 : : HbacRuleObject_services__doc__ },
1008 : :
1009 : : { discard_const_p(char, "targethosts"), T_OBJECT_EX,
1010 : : offsetof(HbacRuleObject, targethosts), 0,
1011 : : HbacRuleObject_targethosts__doc__},
1012 : :
1013 : : { discard_const_p(char, "srchosts"), T_OBJECT_EX,
1014 : : offsetof(HbacRuleObject, srchosts), 0,
1015 : : HbacRuleObject_srchosts__doc__},
1016 : :
1017 : : { NULL, 0, 0, 0, NULL } /* Sentinel */
1018 : : };
1019 : :
1020 : : PyDoc_STRVAR(HbacRuleObject_enabled__doc__,
1021 : : "(bool) Is the rule enabled");
1022 : : PyDoc_STRVAR(HbacRuleObject_name__doc__,
1023 : : "(string) The name of the rule");
1024 : :
1025 : : static PyGetSetDef py_hbac_rule_getset[] = {
1026 : : { discard_const_p(char, "enabled"),
1027 : : (getter) hbac_rule_get_enabled,
1028 : : (setter) hbac_rule_set_enabled,
1029 : : HbacRuleObject_enabled__doc__,
1030 : : NULL },
1031 : :
1032 : : { discard_const_p(char, "name"),
1033 : : (getter) hbac_rule_get_name,
1034 : : (setter) hbac_rule_set_name,
1035 : : HbacRuleObject_name__doc__,
1036 : : NULL },
1037 : :
1038 : : {NULL, 0, 0, 0, NULL} /* Sentinel */
1039 : : };
1040 : :
1041 : : PyDoc_STRVAR(HbacRuleObject__doc__,
1042 : : "IPA HBAC Rule\n\n"
1043 : : "HbacRule(name, [enabled]) -> instantiate an empty rule, optionally\n"
1044 : : "specify whether it is enabled. Rules are created disabled by default and\n"
1045 : : "contain empty HbacRuleElement instances in services, users, targethosts\n"
1046 : : "and srchosts attributes.\n");
1047 : :
1048 : : static PyTypeObject pyhbac_hbacrule_type = {
1049 : : PyObject_HEAD_INIT(NULL)
1050 : : .tp_name = sss_py_const_p(char, "pyhbac.HbacRule"),
1051 : : .tp_basicsize = sizeof(HbacRuleObject),
1052 : : .tp_new = HbacRule_new,
1053 : : .tp_dealloc = (destructor) HbacRule_dealloc,
1054 : : .tp_traverse = (traverseproc) HbacRule_traverse,
1055 : : .tp_clear = (inquiry) HbacRule_clear,
1056 : : .tp_init = (initproc) HbacRule_init,
1057 : : .tp_repr = (reprfunc) HbacRule_repr,
1058 : : .tp_members = py_hbac_rule_members,
1059 : : .tp_methods = py_hbac_rule_methods,
1060 : : .tp_getset = py_hbac_rule_getset,
1061 : : .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
1062 : : .tp_doc = HbacRuleObject__doc__
1063 : : };
1064 : :
1065 : : static void
1066 : 10 : free_hbac_rule(struct hbac_rule *rule)
1067 : : {
1068 [ + - ]: 20 : if (!rule) return;
1069 : :
1070 : 10 : free_hbac_rule_element(rule->services);
1071 : 10 : free_hbac_rule_element(rule->users);
1072 : 10 : free_hbac_rule_element(rule->targethosts);
1073 : 10 : free_hbac_rule_element(rule->srchosts);
1074 : :
1075 : 10 : PyMem_Free(discard_const_p(char, rule->name));
1076 : 10 : PyMem_Free(rule);
1077 : : }
1078 : :
1079 : : static struct hbac_rule *
1080 : 10 : HbacRule_to_native(HbacRuleObject *pyrule)
1081 : : {
1082 : 10 : struct hbac_rule *rule = NULL;
1083 : : PyObject *utf_name;
1084 : :
1085 : 10 : rule = PyMem_Malloc(sizeof(struct hbac_rule));
1086 [ - + ]: 10 : if (!rule) {
1087 : 0 : PyErr_NoMemory();
1088 : 0 : goto fail;
1089 : : }
1090 : :
1091 [ - + ]: 10 : if (!PyObject_IsInstance((PyObject *) pyrule,
1092 : : (PyObject *) &pyhbac_hbacrule_type)) {
1093 : 0 : PyErr_Format(PyExc_TypeError,
1094 : : "The rule must be of type HbacRule\n");
1095 : 0 : goto fail;
1096 : : }
1097 : :
1098 : 10 : utf_name = get_utf8_string(pyrule->name, "name");
1099 [ + - ]: 10 : if (utf_name == NULL) {
1100 : : return NULL;
1101 : : }
1102 : :
1103 : 10 : rule->name = py_strdup(PyString_AsString(utf_name));
1104 [ - + ]: 10 : Py_DECREF(utf_name);
1105 [ + - ]: 10 : if (rule->name == NULL) {
1106 : : goto fail;
1107 : : }
1108 : :
1109 : 10 : rule->services = HbacRuleElement_to_native(pyrule->services);
1110 : 10 : rule->users = HbacRuleElement_to_native(pyrule->users);
1111 : 10 : rule->targethosts = HbacRuleElement_to_native(pyrule->targethosts);
1112 : 10 : rule->srchosts = HbacRuleElement_to_native(pyrule->srchosts);
1113 [ + - ][ + + ]: 10 : if (!rule->services || !rule->users ||
[ + - ]
1114 [ + - ]: 7 : !rule->targethosts || !rule->srchosts) {
1115 : : goto fail;
1116 : : }
1117 : :
1118 : 7 : rule->enabled = pyrule->enabled;
1119 : 7 : return rule;
1120 : :
1121 : : fail:
1122 : 3 : free_hbac_rule(rule);
1123 : 10 : return NULL;
1124 : : }
1125 : :
1126 : : /* ==================== HBAC Request Element ========================*/
1127 : : typedef struct {
1128 : : PyObject_HEAD
1129 : :
1130 : : PyObject *name;
1131 : : PyObject *groups;
1132 : : } HbacRequestElement;
1133 : :
1134 : : static PyObject *
1135 : 38 : HbacRequestElement_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1136 : : {
1137 : : HbacRequestElement *self;
1138 : :
1139 : 38 : self = (HbacRequestElement *) type->tp_alloc(type, 0);
1140 [ - + ]: 38 : if (self == NULL) {
1141 : 0 : PyErr_NoMemory();
1142 : 0 : return NULL;
1143 : : }
1144 : :
1145 : 38 : self->name = sss_python_unicode_from_string("");
1146 [ - + ]: 38 : if (self->name == NULL) {
1147 : 0 : PyErr_NoMemory();
1148 [ # # ]: 0 : Py_DECREF(self);
1149 : : return NULL;
1150 : : }
1151 : :
1152 : 38 : self->groups = PyList_New(0);
1153 [ - + ]: 38 : if (self->groups == NULL) {
1154 [ # # ]: 0 : Py_DECREF(self->name);
1155 [ # # ]: 0 : Py_DECREF(self);
1156 : 0 : PyErr_NoMemory();
1157 : 38 : return NULL;
1158 : : }
1159 : :
1160 : : return (PyObject *) self;
1161 : : }
1162 : :
1163 : : static int
1164 : 38 : HbacRequestElement_clear(HbacRequestElement *self)
1165 : : {
1166 [ + - ][ - + ]: 38 : Py_CLEAR(self->name);
1167 [ + - ][ + + ]: 38 : Py_CLEAR(self->groups);
1168 : 38 : return 0;
1169 : : }
1170 : :
1171 : : static void
1172 : 38 : HbacRequestElement_dealloc(HbacRequestElement *self)
1173 : : {
1174 : 38 : HbacRequestElement_clear(self);
1175 : 38 : self->ob_type->tp_free((PyObject*) self);
1176 : 38 : }
1177 : :
1178 : : static int
1179 : 0 : HbacRequestElement_traverse(HbacRequestElement *self,
1180 : : visitproc visit, void *arg)
1181 : : {
1182 [ # # ][ # # ]: 0 : Py_VISIT(self->name);
1183 [ # # ][ # # ]: 0 : Py_VISIT(self->groups);
1184 : : return 0;
1185 : : }
1186 : :
1187 : : static int
1188 : : hbac_request_element_set_groups(HbacRequestElement *self,
1189 : : PyObject *groups,
1190 : : void *closure);
1191 : : static int
1192 : : hbac_request_element_set_name(HbacRequestElement *self,
1193 : : PyObject *name,
1194 : : void *closure);
1195 : :
1196 : : static int
1197 : 38 : HbacRequestElement_init(HbacRequestElement *self,
1198 : : PyObject *args,
1199 : : PyObject *kwargs)
1200 : : {
1201 : 38 : const char * const kwlist[] = { "name", "groups", NULL };
1202 : 38 : PyObject *name = NULL;
1203 : 38 : PyObject *groups = NULL;
1204 : :
1205 [ + - ]: 38 : if (!PyArg_ParseTupleAndKeywords(args, kwargs,
1206 : : sss_py_const_p(char, "|OO"),
1207 : : discard_const_p(char *, kwlist),
1208 : : &name, &groups)) {
1209 : : return -1;
1210 : : }
1211 : :
1212 [ + + ]: 38 : if (name) {
1213 [ + - ]: 2 : if (hbac_request_element_set_name(self, name, NULL) != 0) {
1214 : : return -1;
1215 : : }
1216 : : }
1217 : :
1218 [ + + ]: 38 : if (groups) {
1219 [ + + ]: 38 : if (hbac_request_element_set_groups(self, groups, NULL) != 0) {
1220 : : return -1;
1221 : : }
1222 : : }
1223 : :
1224 : : return 0;
1225 : : }
1226 : :
1227 : : static int
1228 : 18 : hbac_request_element_set_name(HbacRequestElement *self,
1229 : : PyObject *name,
1230 : : void *closure)
1231 : : {
1232 [ - + ]: 18 : CHECK_ATTRIBUTE_DELETE(name, "name");
1233 : :
1234 [ - + ]: 18 : if (!PyString_Check(name) && !PyUnicode_Check(name)) {
1235 : 0 : PyErr_Format(PyExc_TypeError, "name must be a string or Unicode");
1236 : 0 : return -1;
1237 : : }
1238 : :
1239 [ + - ][ - + ]: 18 : SAFE_SET(self->name, name);
1240 : : return 0;
1241 : : }
1242 : :
1243 : : static PyObject *
1244 : 8 : hbac_request_element_get_name(HbacRequestElement *self, void *closure)
1245 : : {
1246 [ + + ]: 8 : if (PyUnicode_Check(self->name)) {
1247 : 3 : Py_INCREF(self->name);
1248 : 3 : return self->name;
1249 [ + - ]: 5 : } else if (PyString_Check(self->name)) {
1250 : 5 : return PyUnicode_FromEncodedObject(self->name,
1251 : : PYHBAC_ENCODING, PYHBAC_ENCODING_ERRORS);
1252 : : }
1253 : :
1254 : : /* setter does typechecking but let us be paranoid */
1255 : 0 : PyErr_Format(PyExc_TypeError, "name must be a string or Unicode");
1256 : 8 : return NULL;
1257 : : }
1258 : :
1259 : : static int
1260 : 8 : hbac_request_element_set_groups(HbacRequestElement *self,
1261 : : PyObject *groups,
1262 : : void *closure)
1263 : : {
1264 [ - + ]: 8 : CHECK_ATTRIBUTE_DELETE(groups, "groups");
1265 : :
1266 [ + + ]: 8 : if (!verify_sequence(groups, "groups")) {
1267 : : return -1;
1268 : : }
1269 : :
1270 [ + - ][ + - ]: 8 : SAFE_SET(self->groups, groups);
1271 : : return 0;
1272 : : }
1273 : :
1274 : : static PyObject *
1275 : 10 : hbac_request_element_get_groups(HbacRequestElement *self, void *closure)
1276 : : {
1277 : 10 : Py_INCREF(self->groups);
1278 : 10 : return self->groups;
1279 : : }
1280 : :
1281 : : static PyObject *
1282 : 10 : HbacRequestElement_repr(HbacRequestElement *self)
1283 : : {
1284 : : char *strgroups;
1285 : : PyObject *o, *format, *args;
1286 : :
1287 : 10 : format = sss_python_unicode_from_string("<name %s groups [%s]>");
1288 [ + - ]: 10 : if (format == NULL) {
1289 : : return NULL;
1290 : : }
1291 : :
1292 : 10 : strgroups = str_concat_sequence(self->groups, discard_const_p(char, ","));
1293 [ - + ]: 10 : if (strgroups == NULL) {
1294 [ # # ]: 0 : Py_DECREF(format);
1295 : : return NULL;
1296 : : }
1297 : :
1298 : 10 : args = Py_BuildValue(sss_py_const_p(char, "Os"), self->name, strgroups);
1299 [ - + ]: 10 : if (args == NULL) {
1300 : 0 : PyMem_Free(strgroups);
1301 [ # # ]: 0 : Py_DECREF(format);
1302 : : return NULL;
1303 : : }
1304 : :
1305 : 10 : o = PyUnicode_Format(format, args);
1306 : 10 : PyMem_Free(strgroups);
1307 [ + - ]: 10 : Py_DECREF(format);
1308 [ + - ]: 10 : Py_DECREF(args);
1309 : 10 : return o;
1310 : : }
1311 : :
1312 : : PyDoc_STRVAR(HbacRequestElement_name__doc__,
1313 : : "(string) An object name this element applies to");
1314 : : PyDoc_STRVAR(HbacRequestElement_groups__doc__,
1315 : : "(list of strings) A list of group names this element applies to");
1316 : :
1317 : : static PyGetSetDef py_hbac_request_element_getset[] = {
1318 : : { discard_const_p(char, "name"),
1319 : : (getter) hbac_request_element_get_name,
1320 : : (setter) hbac_request_element_set_name,
1321 : : HbacRequestElement_name__doc__,
1322 : : NULL },
1323 : :
1324 : : { discard_const_p(char, "groups"),
1325 : : (getter) hbac_request_element_get_groups,
1326 : : (setter) hbac_request_element_set_groups,
1327 : : HbacRequestElement_groups__doc__,
1328 : : NULL },
1329 : :
1330 : : { NULL, 0, 0, 0, NULL } /* Sentinel */
1331 : : };
1332 : :
1333 : : PyDoc_STRVAR(HbacRequestElement__doc__,
1334 : : "IPA HBAC Request Element\n\n"
1335 : : "HbacRequestElement() -> new empty request element\n"
1336 : : "HbacRequestElement([name], [groups]) -> optionally, provide name and/or "
1337 : : "groups\n");
1338 : :
1339 : : static PyTypeObject pyhbac_hbacrequest_element_type = {
1340 : : PyObject_HEAD_INIT(NULL)
1341 : : .tp_name = sss_py_const_p(char, "pyhbac.HbacRequestElement"),
1342 : : .tp_basicsize = sizeof(HbacRequestElement),
1343 : : .tp_new = HbacRequestElement_new,
1344 : : .tp_dealloc = (destructor) HbacRequestElement_dealloc,
1345 : : .tp_traverse = (traverseproc) HbacRequestElement_traverse,
1346 : : .tp_clear = (inquiry) HbacRequestElement_clear,
1347 : : .tp_init = (initproc) HbacRequestElement_init,
1348 : : .tp_repr = (reprfunc) HbacRequestElement_repr,
1349 : : .tp_getset = py_hbac_request_element_getset,
1350 : : .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
1351 : : .tp_doc = HbacRequestElement__doc__
1352 : : };
1353 : :
1354 : : static void
1355 : 17 : free_hbac_request_element(struct hbac_request_element *el)
1356 : : {
1357 [ + + ]: 32 : if (!el) return;
1358 : :
1359 : 15 : PyMem_Free(discard_const_p(char, el->name));
1360 : 15 : free_string_list(el->groups);
1361 : 15 : PyMem_Free(el);
1362 : : }
1363 : :
1364 : : static struct hbac_request_element *
1365 : 16 : HbacRequestElement_to_native(HbacRequestElement *pyel)
1366 : : {
1367 : 16 : struct hbac_request_element *el = NULL;
1368 : : PyObject *utf_name;
1369 : :
1370 [ + + ]: 16 : if (!PyObject_IsInstance((PyObject *) pyel,
1371 : : (PyObject *) &pyhbac_hbacrequest_element_type)) {
1372 : 1 : PyErr_Format(PyExc_TypeError,
1373 : : "The element must be of type HbacRequestElement\n");
1374 : 1 : goto fail;
1375 : : }
1376 : :
1377 : 15 : el = PyMem_Malloc(sizeof(struct hbac_request_element));
1378 [ - + ]: 15 : if (!el) {
1379 : 0 : PyErr_NoMemory();
1380 : 0 : goto fail;
1381 : : }
1382 : :
1383 : 15 : utf_name = get_utf8_string(pyel->name, "name");
1384 [ + - ]: 15 : if (utf_name == NULL) {
1385 : : return NULL;
1386 : : }
1387 : :
1388 : 15 : el->name = py_strdup(PyString_AsString(utf_name));
1389 [ - + ]: 15 : Py_DECREF(utf_name);
1390 [ + - ]: 15 : if (!el->name) {
1391 : : goto fail;
1392 : : }
1393 : :
1394 : 15 : el->groups = sequence_as_string_list(pyel->groups, "groups");
1395 [ - + ]: 15 : if (!el->groups) {
1396 : : goto fail;
1397 : : }
1398 : :
1399 : : return el;
1400 : :
1401 : : fail:
1402 : 1 : free_hbac_request_element(el);
1403 : 16 : return NULL;
1404 : : }
1405 : :
1406 : : /* ==================== HBAC Request ========================*/
1407 : : typedef struct {
1408 : : PyObject_HEAD
1409 : :
1410 : : HbacRequestElement *service;
1411 : : HbacRequestElement *user;
1412 : : HbacRequestElement *targethost;
1413 : : HbacRequestElement *srchost;
1414 : :
1415 : : PyObject *rule_name;
1416 : : } HbacRequest;
1417 : :
1418 : : static PyObject *
1419 : 7 : HbacRequest_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1420 : : {
1421 : : HbacRequest *self;
1422 : :
1423 : 7 : self = (HbacRequest *) type->tp_alloc(type, 0);
1424 [ - + ]: 7 : if (self == NULL) {
1425 : 0 : PyErr_NoMemory();
1426 : 0 : return NULL;
1427 : : }
1428 : :
1429 : 7 : self->service = (HbacRequestElement *) HbacRequestElement_new(
1430 : : &pyhbac_hbacrequest_element_type,
1431 : : NULL, NULL);
1432 : 7 : self->user = (HbacRequestElement *) HbacRequestElement_new(
1433 : : &pyhbac_hbacrequest_element_type,
1434 : : NULL, NULL);
1435 : 7 : self->targethost = (HbacRequestElement *) HbacRequestElement_new(
1436 : : &pyhbac_hbacrequest_element_type,
1437 : : NULL, NULL);
1438 : 7 : self->srchost = (HbacRequestElement *) HbacRequestElement_new(
1439 : : &pyhbac_hbacrequest_element_type,
1440 : : NULL, NULL);
1441 [ + - ][ + - ]: 7 : if (self->service == NULL || self->user == NULL ||
[ + - ]
1442 [ - + ]: 7 : self->targethost == NULL || self->srchost == NULL) {
1443 [ # # ][ # # ]: 0 : Py_XDECREF(self->service);
1444 [ # # ][ # # ]: 0 : Py_XDECREF(self->user);
1445 [ # # ][ # # ]: 0 : Py_XDECREF(self->targethost);
1446 [ # # ][ # # ]: 0 : Py_XDECREF(self->srchost);
1447 [ # # ]: 0 : Py_DECREF(self);
1448 : 0 : PyErr_NoMemory();
1449 : 7 : return NULL;
1450 : : }
1451 : :
1452 : : return (PyObject *) self;
1453 : : }
1454 : :
1455 : : static int
1456 : 7 : HbacRequest_clear(HbacRequest *self)
1457 : : {
1458 [ + - ][ + - ]: 7 : Py_CLEAR(self->service);
1459 [ + - ][ + + ]: 7 : Py_CLEAR(self->user);
1460 [ + - ][ + - ]: 7 : Py_CLEAR(self->targethost);
1461 [ + - ][ + - ]: 7 : Py_CLEAR(self->srchost);
1462 [ + + ][ + - ]: 7 : Py_CLEAR(self->rule_name);
1463 : 7 : return 0;
1464 : : }
1465 : :
1466 : : static void
1467 : 7 : HbacRequest_dealloc(HbacRequest *self)
1468 : : {
1469 : 7 : HbacRequest_clear(self);
1470 : 7 : self->ob_type->tp_free((PyObject*) self);
1471 : 7 : }
1472 : :
1473 : : static int
1474 : 0 : HbacRequest_traverse(HbacRequest *self, visitproc visit, void *arg)
1475 : : {
1476 [ # # ][ # # ]: 0 : Py_VISIT((PyObject *) self->service);
1477 [ # # ][ # # ]: 0 : Py_VISIT((PyObject *) self->user);
1478 [ # # ][ # # ]: 0 : Py_VISIT((PyObject *) self->targethost);
1479 [ # # ][ # # ]: 0 : Py_VISIT((PyObject *) self->srchost);
1480 : : return 0;
1481 : : }
1482 : :
1483 : : static int
1484 : 7 : HbacRequest_init(HbacRequest *self, PyObject *args, PyObject *kwargs)
1485 : : {
1486 : 7 : PyObject *empty_tuple = NULL;
1487 : :
1488 : 7 : empty_tuple = PyTuple_New(0);
1489 [ - + ]: 7 : if (!empty_tuple) {
1490 : 0 : PyErr_NoMemory();
1491 : 0 : return -1;
1492 : : }
1493 : :
1494 : 7 : self->rule_name = NULL;
1495 : :
1496 [ + - + - ]: 14 : if (HbacRequestElement_init(self->user, empty_tuple, NULL) == -1 ||
1497 [ + - ]: 14 : HbacRequestElement_init(self->service, empty_tuple, NULL) == -1 ||
1498 [ - + ]: 14 : HbacRequestElement_init(self->targethost, empty_tuple, NULL) == -1 ||
1499 : 7 : HbacRequestElement_init(self->srchost, empty_tuple, NULL) == -1) {
1500 [ # # ]: 0 : Py_DECREF(empty_tuple);
1501 : : return -1;
1502 : : }
1503 : :
1504 [ - + ]: 7 : Py_DECREF(empty_tuple);
1505 : : return 0;
1506 : : }
1507 : :
1508 : : PyDoc_STRVAR(py_hbac_evaluate__doc__,
1509 : : "evaluate(rules) -> int\n\n"
1510 : : "Evaluate a set of HBAC rules.\n"
1511 : : "rules is a sequence of HbacRule objects. The returned value describes\n"
1512 : : "the result of evaluation and will have one of HBAC_EVAL_* values.\n"
1513 : : "Use hbac_result_string() to get textual representation of the result\n"
1514 : : "On error, HbacError exception is raised.\n"
1515 : : "If HBAC_EVAL_ALLOW is returned, the class attribute rule_name would\n"
1516 : : "contain the name of the rule that matched. Otherwise, the attribute\n"
1517 : : "contains None\n");
1518 : :
1519 : : static struct hbac_eval_req *
1520 : : HbacRequest_to_native(HbacRequest *pyreq);
1521 : :
1522 : : static void
1523 : 7 : free_hbac_rule_list(struct hbac_rule **rules)
1524 : : {
1525 : : int i;
1526 : :
1527 [ + - ]: 14 : if (!rules) return;
1528 : :
1529 [ + + ]: 11 : for(i=0; rules[i]; i++) {
1530 : 4 : free_hbac_rule(rules[i]);
1531 : : }
1532 : 7 : PyMem_Free(rules);
1533 : : }
1534 : :
1535 : : static void
1536 : : free_hbac_eval_req(struct hbac_eval_req *req);
1537 : :
1538 : : static PyObject *
1539 : 7 : py_hbac_evaluate(HbacRequest *self, PyObject *args)
1540 : : {
1541 : 7 : PyObject *py_rules_list = NULL;
1542 : 7 : PyObject *py_rule = NULL;
1543 : : Py_ssize_t num_rules;
1544 : 7 : struct hbac_rule **rules = NULL;
1545 : 7 : struct hbac_eval_req *hbac_req = NULL;
1546 : : enum hbac_eval_result eres;
1547 : 7 : struct hbac_info *info = NULL;
1548 : 7 : PyObject *ret = NULL;
1549 : : long i;
1550 : :
1551 [ + - ]: 7 : if (!PyArg_ParseTuple(args, sss_py_const_p(char, "O"), &py_rules_list)) {
1552 : : goto fail;
1553 : : }
1554 : :
1555 [ - + ]: 7 : if (!PySequence_Check(py_rules_list)) {
1556 : 0 : PyErr_Format(PyExc_TypeError,
1557 : : "The parameter rules must be a sequence\n");
1558 : : goto fail;
1559 : : }
1560 : :
1561 : 7 : num_rules = PySequence_Size(py_rules_list);
1562 [ + - ]: 7 : rules = PyMem_New(struct hbac_rule *, num_rules+1);
1563 [ + - ]: 7 : if (!rules) {
1564 : 0 : PyErr_NoMemory();
1565 : : goto fail;
1566 : : }
1567 : :
1568 [ + + ]: 11 : for (i=0; i < num_rules; i++) {
1569 : 7 : py_rule = PySequence_GetItem(py_rules_list, i);
1570 : :
1571 [ - + ]: 7 : if (!PyObject_IsInstance(py_rule,
1572 : : (PyObject *) &pyhbac_hbacrule_type)) {
1573 : 0 : PyErr_Format(PyExc_TypeError,
1574 : : "A rule must be of type HbacRule\n");
1575 : : goto fail;
1576 : : }
1577 : :
1578 : 7 : rules[i] = HbacRule_to_native((HbacRuleObject *) py_rule);
1579 [ + + ]: 7 : if (!rules[i]) {
1580 : : /* Make sure there is at least a generic exception */
1581 [ - + ]: 3 : if (!PyErr_Occurred()) {
1582 : 0 : PyErr_Format(PyExc_IOError,
1583 : : "Could not convert HbacRule to native type\n");
1584 : : }
1585 : : goto fail;
1586 : : }
1587 : : }
1588 : 4 : rules[num_rules] = NULL;
1589 : :
1590 : 4 : hbac_req = HbacRequest_to_native(self);
1591 [ + + ]: 4 : if (!hbac_req) {
1592 [ - + ]: 1 : if (!PyErr_Occurred()) {
1593 : 0 : PyErr_Format(PyExc_IOError,
1594 : : "Could not convert HbacRequest to native type\n");
1595 : : }
1596 : : goto fail;
1597 : : }
1598 : :
1599 [ + + ][ + - ]: 3 : Py_XDECREF(self->rule_name);
1600 : 3 : self->rule_name = NULL;
1601 : :
1602 : 3 : eres = hbac_evaluate(rules, hbac_req, &info);
1603 [ + + - - : 3 : switch (eres) {
- ]
1604 : : case HBAC_EVAL_ALLOW:
1605 : 2 : self->rule_name = sss_python_unicode_from_string(info->rule_name);
1606 [ - + ]: 2 : if (!self->rule_name) {
1607 : 0 : PyErr_NoMemory();
1608 : : goto fail;
1609 : : }
1610 : : /* FALLTHROUGH */
1611 : : case HBAC_EVAL_DENY:
1612 : 3 : ret = PyInt_FromLong(eres);
1613 : : break;
1614 : : case HBAC_EVAL_ERROR:
1615 : 0 : set_hbac_exception(PyExc_HbacError, info);
1616 : : goto fail;
1617 : : case HBAC_EVAL_OOM:
1618 : 0 : PyErr_NoMemory();
1619 : : goto fail;
1620 : : }
1621 : :
1622 : 3 : free_hbac_eval_req(hbac_req);
1623 : 3 : free_hbac_rule_list(rules);
1624 : 3 : hbac_free_info(info);
1625 : : return ret;
1626 : :
1627 : : fail:
1628 : 4 : hbac_free_info(info);
1629 : 4 : free_hbac_eval_req(hbac_req);
1630 : 7 : free_hbac_rule_list(rules);
1631 : : return NULL;
1632 : : }
1633 : :
1634 : : static PyObject *
1635 : 3 : hbac_request_element_get_rule_name(HbacRequest *self, void *closure)
1636 : : {
1637 [ + + ]: 3 : if (self->rule_name == NULL) {
1638 : 2 : Py_INCREF(Py_None);
1639 : 2 : return Py_None;
1640 [ + - ]: 1 : } else if (PyUnicode_Check(self->rule_name)) {
1641 : 1 : Py_INCREF(self->rule_name);
1642 : 1 : return self->rule_name;
1643 : : }
1644 : :
1645 : 0 : PyErr_Format(PyExc_TypeError, "rule_name is not Unicode");
1646 : 3 : return NULL;
1647 : : }
1648 : :
1649 : : static PyObject *
1650 : 2 : HbacRequest_repr(HbacRequest *self)
1651 : : {
1652 : : PyObject *user_repr;
1653 : : PyObject *service_repr;
1654 : : PyObject *targethost_repr;
1655 : : PyObject *srchost_repr;
1656 : : PyObject *o, *format, *args;
1657 : :
1658 : 2 : format = sss_python_unicode_from_string("<user %s service %s "
1659 : : "targethost %s srchost %s>");
1660 [ + - ]: 2 : if (format == NULL) {
1661 : : return NULL;
1662 : : }
1663 : :
1664 : 2 : user_repr = HbacRequestElement_repr(self->user);
1665 : 2 : service_repr = HbacRequestElement_repr(self->service);
1666 : 2 : targethost_repr = HbacRequestElement_repr(self->targethost);
1667 : 2 : srchost_repr = HbacRequestElement_repr(self->srchost);
1668 [ + - ]: 2 : if (user_repr == NULL || service_repr == NULL ||
1669 [ - + ]: 2 : targethost_repr == NULL || srchost_repr == NULL) {
1670 [ # # ][ # # ]: 0 : Py_XDECREF(user_repr);
1671 [ # # ][ # # ]: 0 : Py_XDECREF(service_repr);
1672 [ # # ][ # # ]: 0 : Py_XDECREF(targethost_repr);
1673 [ # # ][ # # ]: 0 : Py_XDECREF(srchost_repr);
1674 [ # # ]: 0 : Py_DECREF(format);
1675 : : return NULL;
1676 : : }
1677 : :
1678 : 2 : args = Py_BuildValue(sss_py_const_p(char, "OOOO"),
1679 : : user_repr, service_repr,
1680 : : targethost_repr, srchost_repr);
1681 [ - + ]: 2 : if (args == NULL) {
1682 [ # # ]: 0 : Py_DECREF(user_repr);
1683 [ # # ]: 0 : Py_DECREF(service_repr);
1684 [ # # ]: 0 : Py_DECREF(targethost_repr);
1685 [ # # ]: 0 : Py_DECREF(srchost_repr);
1686 [ # # ]: 0 : Py_DECREF(format);
1687 : : return NULL;
1688 : : }
1689 : :
1690 : 2 : o = PyUnicode_Format(format, args);
1691 [ - + ]: 2 : Py_DECREF(user_repr);
1692 [ - + ]: 2 : Py_DECREF(service_repr);
1693 [ - + ]: 2 : Py_DECREF(targethost_repr);
1694 [ - + ]: 2 : Py_DECREF(srchost_repr);
1695 [ + - ]: 2 : Py_DECREF(format);
1696 [ + - ]: 2 : Py_DECREF(args);
1697 : 2 : return o;
1698 : : }
1699 : :
1700 : : static PyMethodDef py_hbac_request_methods[] = {
1701 : : { sss_py_const_p(char, "evaluate"),
1702 : : (PyCFunction) py_hbac_evaluate,
1703 : : METH_VARARGS, py_hbac_evaluate__doc__
1704 : : },
1705 : : { NULL, NULL, 0, NULL } /* Sentinel */
1706 : : };
1707 : :
1708 : : PyDoc_STRVAR(HbacRequest_service__doc__,
1709 : : "(HbacRequestElement) This is a list of service DNs to check, it must\n"
1710 : : "consist of the actual service requested, as well as all parent groups\n"
1711 : : "containing that service");
1712 : : PyDoc_STRVAR(HbacRequest_user__doc__,
1713 : : "(HbacRequestElement) This is a list of user DNs to check, it must consist\n"
1714 : : "of the actual user requested, as well as all parent groups containing\n"
1715 : : "that user.");
1716 : : PyDoc_STRVAR(HbacRequest_targethost__doc__,
1717 : : "(HbacRequestElement) This is a list of target hosts to check, it must\n"
1718 : : "consist of the actual target host requested, as well as all parent groups\n"
1719 : : "containing that target host.");
1720 : : PyDoc_STRVAR(HbacRequest_srchost__doc__,
1721 : : "(HbacRequestElement) This is a list of source hosts to check, it must\n"
1722 : : "consist of the actual source host requested, as well as all parent groups\n"
1723 : : "containing that source host.");
1724 : :
1725 : : static PyMemberDef py_hbac_request_members[] = {
1726 : : { discard_const_p(char, "service"), T_OBJECT_EX,
1727 : : offsetof(HbacRequest, service), 0,
1728 : : HbacRequest_service__doc__ },
1729 : :
1730 : : { discard_const_p(char, "user"), T_OBJECT_EX,
1731 : : offsetof(HbacRequest, user), 0,
1732 : : HbacRequest_user__doc__ },
1733 : :
1734 : : { discard_const_p(char, "targethost"), T_OBJECT_EX,
1735 : : offsetof(HbacRequest, targethost), 0,
1736 : : HbacRequest_targethost__doc__ },
1737 : :
1738 : : { discard_const_p(char, "srchost"), T_OBJECT_EX,
1739 : : offsetof(HbacRequest, srchost), 0,
1740 : : HbacRequest_srchost__doc__ },
1741 : :
1742 : : { NULL, 0, 0, 0, NULL } /* Sentinel */
1743 : : };
1744 : :
1745 : : PyDoc_STRVAR(HbacRequest_rule_name__doc__,
1746 : : "(string) If result of evaluation was to allow access, this member contains\n"
1747 : : "the name of the rule that allowed it. Otherwise, this attribute contains \n"
1748 : : "None. This attribute is read-only.\n");
1749 : :
1750 : : static PyGetSetDef py_hbac_request_getset[] = {
1751 : : { discard_const_p(char, "rule_name"),
1752 : : (getter) hbac_request_element_get_rule_name,
1753 : : NULL, /* read only */
1754 : : HbacRequest_rule_name__doc__,
1755 : : NULL },
1756 : :
1757 : : { NULL, 0, 0, 0, NULL } /* Sentinel */
1758 : : };
1759 : :
1760 : : PyDoc_STRVAR(HbacRequest__doc__,
1761 : : "IPA HBAC Request\n\n"
1762 : : "HbacRequest() -> new empty HBAC request");
1763 : :
1764 : : static PyTypeObject pyhbac_hbacrequest_type = {
1765 : : PyObject_HEAD_INIT(NULL)
1766 : : .tp_name = sss_py_const_p(char, "pyhbac.HbacRequest"),
1767 : : .tp_basicsize = sizeof(HbacRequest),
1768 : : .tp_new = HbacRequest_new,
1769 : : .tp_dealloc = (destructor) HbacRequest_dealloc,
1770 : : .tp_traverse = (traverseproc) HbacRequest_traverse,
1771 : : .tp_clear = (inquiry) HbacRequest_clear,
1772 : : .tp_init = (initproc) HbacRequest_init,
1773 : : .tp_repr = (reprfunc) HbacRequest_repr,
1774 : : .tp_methods = py_hbac_request_methods,
1775 : : .tp_members = py_hbac_request_members,
1776 : : .tp_getset = py_hbac_request_getset,
1777 : : .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
1778 : : .tp_doc = HbacRequest__doc__
1779 : : };
1780 : :
1781 : : static void
1782 : 8 : free_hbac_eval_req(struct hbac_eval_req *req)
1783 : : {
1784 [ + + ]: 12 : if (!req) return;
1785 : :
1786 : 4 : free_hbac_request_element(req->service);
1787 : 4 : free_hbac_request_element(req->user);
1788 : 4 : free_hbac_request_element(req->targethost);
1789 : 4 : free_hbac_request_element(req->srchost);
1790 : :
1791 : 4 : PyMem_Free(req);
1792 : : }
1793 : :
1794 : : static struct hbac_eval_req *
1795 : 4 : HbacRequest_to_native(HbacRequest *pyreq)
1796 : : {
1797 : 4 : struct hbac_eval_req *req = NULL;
1798 : :
1799 : 4 : req = PyMem_Malloc(sizeof(struct hbac_eval_req));
1800 [ - + ]: 4 : if (!req) {
1801 : 0 : PyErr_NoMemory();
1802 : 0 : goto fail;
1803 : : }
1804 : :
1805 [ - + ]: 4 : if (!PyObject_IsInstance((PyObject *) pyreq,
1806 : : (PyObject *) &pyhbac_hbacrequest_type)) {
1807 : 0 : PyErr_Format(PyExc_TypeError,
1808 : : "The request must be of type HbacRequest\n");
1809 : 0 : goto fail;
1810 : : }
1811 : :
1812 : 4 : req->service = HbacRequestElement_to_native(pyreq->service);
1813 : 4 : req->user = HbacRequestElement_to_native(pyreq->user);
1814 : 4 : req->targethost = HbacRequestElement_to_native(pyreq->targethost);
1815 : 4 : req->srchost = HbacRequestElement_to_native(pyreq->srchost);
1816 [ + - ][ + + ]: 4 : if (!req->service || !req->user ||
[ + - ]
1817 [ - + ]: 3 : !req->targethost || !req->srchost) {
1818 : : goto fail;
1819 : : }
1820 : : return req;
1821 : :
1822 : : fail:
1823 : 1 : free_hbac_eval_req(req);
1824 : 4 : return NULL;
1825 : : }
1826 : :
1827 : : /* =================== the pyhbac module initialization =====================*/
1828 : : PyDoc_STRVAR(py_hbac_result_string__doc__,
1829 : : "hbac_result_string(code) -> string\n"
1830 : : "Returns a string representation of the HBAC result code");
1831 : :
1832 : : static PyObject *
1833 : 3 : py_hbac_result_string(PyObject *module, PyObject *args)
1834 : : {
1835 : : enum hbac_eval_result result;
1836 : : const char *str;
1837 : :
1838 [ + - ]: 3 : if (!PyArg_ParseTuple(args, sss_py_const_p(char, "i"), &result)) {
1839 : : return NULL;
1840 : : }
1841 : :
1842 : 3 : str = hbac_result_string(result);
1843 [ - + ]: 3 : if (str == NULL) {
1844 : : /* None needs to be referenced, too */
1845 : 0 : Py_INCREF(Py_None);
1846 : : return Py_None;
1847 : : }
1848 : :
1849 : 3 : return sss_python_unicode_from_string(str);
1850 : : }
1851 : :
1852 : : PyDoc_STRVAR(py_hbac_error_string__doc__,
1853 : : "hbac_error_string(code) -> string\n"
1854 : : "Returns a string representation of the HBAC error code");
1855 : :
1856 : : static PyObject *
1857 : 5 : py_hbac_error_string(PyObject *module, PyObject *args)
1858 : : {
1859 : : enum hbac_error_code code;
1860 : : const char *str;
1861 : :
1862 [ + - ]: 5 : if (!PyArg_ParseTuple(args, sss_py_const_p(char, "i"), &code)) {
1863 : : return NULL;
1864 : : }
1865 : :
1866 : 5 : str = hbac_error_string(code);
1867 [ - + ]: 5 : if (str == NULL) {
1868 : : /* None needs to be referenced, too */
1869 : 0 : Py_INCREF(Py_None);
1870 : : return Py_None;
1871 : : }
1872 : :
1873 : 5 : return sss_python_unicode_from_string(str);
1874 : : }
1875 : :
1876 : : static PyMethodDef pyhbac_module_methods[] = {
1877 : : { sss_py_const_p(char, "hbac_result_string"),
1878 : : (PyCFunction) py_hbac_result_string,
1879 : : METH_VARARGS,
1880 : : py_hbac_result_string__doc__,
1881 : : },
1882 : :
1883 : : { sss_py_const_p(char, "hbac_error_string"),
1884 : : (PyCFunction) py_hbac_error_string,
1885 : : METH_VARARGS,
1886 : : py_hbac_error_string__doc__,
1887 : : },
1888 : :
1889 : : {NULL, NULL, 0, NULL} /* Sentinel */
1890 : : };
1891 : :
1892 : : PyDoc_STRVAR(HbacError__doc__,
1893 : : "An HBAC processing exception\n\n"
1894 : : "This exception is raised when there is an internal error during the\n"
1895 : : "HBAC processing, such as an Out-Of-Memory situation or unparseable\n"
1896 : : "rule. HbacError.args argument is a tuple that contains error code and\n"
1897 : : "the name of the rule that was being processed. Use hbac_error_string()\n"
1898 : : "to get the text representation of the HBAC error");
1899 : :
1900 : : PyMODINIT_FUNC
1901 : 1 : initpyhbac(void)
1902 : : {
1903 : : PyObject *m;
1904 : : int ret;
1905 : :
1906 : 1 : m = Py_InitModule(sss_py_const_p(char, PYTHON_MODULE_NAME), pyhbac_module_methods);
1907 [ + - ]: 1 : if (m == NULL) return;
1908 : :
1909 : : /* The HBAC module exception */
1910 : 1 : PyExc_HbacError = sss_exception_with_doc(
1911 : : discard_const_p(char, "hbac.HbacError"),
1912 : : HbacError__doc__,
1913 : : PyExc_EnvironmentError, NULL);
1914 : 1 : Py_INCREF(PyExc_HbacError);
1915 : 1 : ret = PyModule_AddObject(m, sss_py_const_p(char, "HbacError"), PyExc_HbacError);
1916 [ + - ]: 1 : if (ret == -1) return;
1917 : :
1918 : : /* HBAC rule categories */
1919 : 1 : ret = PyModule_AddIntMacro(m, HBAC_CATEGORY_NULL);
1920 [ + - ]: 1 : if (ret == -1) return;
1921 : 1 : ret = PyModule_AddIntMacro(m, HBAC_CATEGORY_ALL);
1922 [ + - ]: 1 : if (ret == -1) return;
1923 : :
1924 : : /* HBAC rule elements */
1925 : 1 : ret = PyModule_AddIntMacro(m, HBAC_RULE_ELEMENT_USERS);
1926 [ + - ]: 1 : if (ret == -1) return;
1927 : 1 : ret = PyModule_AddIntMacro(m, HBAC_RULE_ELEMENT_SERVICES);
1928 [ + - ]: 1 : if (ret == -1) return;
1929 : 1 : ret = PyModule_AddIntMacro(m, HBAC_RULE_ELEMENT_TARGETHOSTS);
1930 [ + - ]: 1 : if (ret == -1) return;
1931 : 1 : ret = PyModule_AddIntMacro(m, HBAC_RULE_ELEMENT_SOURCEHOSTS);
1932 [ + - ]: 1 : if (ret == -1) return;
1933 : :
1934 : : /* enum hbac_eval_result */
1935 : 1 : ret = PyModule_AddIntMacro(m, HBAC_EVAL_ALLOW);
1936 [ + - ]: 1 : if (ret == -1) return;
1937 : 1 : ret = PyModule_AddIntMacro(m, HBAC_EVAL_DENY);
1938 [ + - ]: 1 : if (ret == -1) return;
1939 : 1 : ret = PyModule_AddIntMacro(m, HBAC_EVAL_ERROR);
1940 [ + - ]: 1 : if (ret == -1) return;
1941 : :
1942 : : /* enum hbac_error_code */
1943 : 1 : ret = PyModule_AddIntMacro(m, HBAC_ERROR_UNKNOWN);
1944 [ + - ]: 1 : if (ret == -1) return;
1945 : 1 : ret = PyModule_AddIntMacro(m, HBAC_SUCCESS);
1946 [ + - ]: 1 : if (ret == -1) return;
1947 : 1 : ret = PyModule_AddIntMacro(m, HBAC_ERROR_NOT_IMPLEMENTED);
1948 [ + - ]: 1 : if (ret == -1) return;
1949 : 1 : ret = PyModule_AddIntMacro(m, HBAC_ERROR_OUT_OF_MEMORY);
1950 [ + - ]: 1 : if (ret == -1) return;
1951 : 1 : ret = PyModule_AddIntMacro(m, HBAC_ERROR_UNPARSEABLE_RULE);
1952 [ + - ]: 1 : if (ret == -1) return;
1953 : :
1954 [ + - ]: 1 : TYPE_READY(m, pyhbac_hbacrule_type, "HbacRule");
1955 [ + - ]: 1 : TYPE_READY(m, pyhbac_hbacrule_element_type, "HbacRuleElement");
1956 [ + - ]: 1 : TYPE_READY(m, pyhbac_hbacrequest_element_type, "HbacRequestElement");
1957 [ + - ]: 1 : TYPE_READY(m, pyhbac_hbacrequest_type, "HbacRequest");
1958 : 0 : }
|