LCOV - code coverage report
Current view: top level - python - pyhbac.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 622 823 75.6 %
Date: 2015-10-19 Functions: 61 64 95.3 %

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

Generated by: LCOV version 1.10