diff options
author | Jakub Hrozek <jhrozek@redhat.com> | 2011-07-30 12:57:24 +0200 |
---|---|---|
committer | Stephen Gallagher <sgallagh@redhat.com> | 2011-08-01 09:23:16 -0400 |
commit | 1e710acc5ce225c7e6aa33bc0dfe8af65f49d182 (patch) | |
tree | 2d7214eb37f91580f397d69ab105a73f063fc1fb | |
parent | d2d90b7195f58bd20628b1c62d1e1b01bfbb7a2b (diff) | |
download | sssd-1e710acc5ce225c7e6aa33bc0dfe8af65f49d182.tar.gz sssd-1e710acc5ce225c7e6aa33bc0dfe8af65f49d182.tar.xz sssd-1e710acc5ce225c7e6aa33bc0dfe8af65f49d182.zip |
HBAC rule validation Python bindings
https://fedorahosted.org/sssd/ticket/943
-rw-r--r-- | src/python/pyhbac.c | 99 | ||||
-rwxr-xr-x | src/tests/pyhbac-test.py | 30 |
2 files changed, 129 insertions, 0 deletions
diff --git a/src/python/pyhbac.c b/src/python/pyhbac.c index 38df27e50..230b9316a 100644 --- a/src/python/pyhbac.c +++ b/src/python/pyhbac.c @@ -382,6 +382,7 @@ HbacRuleElement_init(HbacRuleElement *self, PyObject *args, PyObject *kwargs) } if (sss_python_set_add(self->category, tmp) != 0) { + Py_DECREF(tmp); return -1; } } @@ -627,6 +628,11 @@ typedef struct { HbacRuleElement *srchosts; } HbacRuleObject; +static void +free_hbac_rule(struct hbac_rule *rule); +static struct hbac_rule * +HbacRule_to_native(HbacRuleObject *pyrule); + static PyObject * HbacRule_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { @@ -891,6 +897,88 @@ HbacRule_repr(HbacRuleObject *self) return o; } +static PyObject * +py_hbac_rule_validate(HbacRuleObject *self, PyObject *args) +{ + struct hbac_rule *rule; + bool is_valid; + uint32_t missing; + uint32_t attr; + PyObject *ret = NULL; + PyObject *py_is_valid = NULL; + PyObject *py_missing = NULL; + PyObject *py_attr = NULL; + + rule = HbacRule_to_native(self); + if (!rule) { + /* Make sure there is at least a generic exception */ + if (!PyErr_Occurred()) { + PyErr_Format(PyExc_IOError, + "Could not convert HbacRule to native type\n"); + } + goto fail; + } + + is_valid = hbac_rule_is_complete(rule, &missing); + free_hbac_rule(rule); + + ret = PyTuple_New(2); + if (!ret) { + PyErr_NoMemory(); + goto fail; + } + + py_is_valid = PyBool_FromLong(is_valid); + py_missing = sss_python_set_new(); + if (!py_missing || !py_is_valid) { + PyErr_NoMemory(); + goto fail; + } + + for (attr = HBAC_RULE_ELEMENT_USERS; + attr <= HBAC_RULE_ELEMENT_SOURCEHOSTS; + attr <<= 1) { + if (!(missing & attr)) continue; + + py_attr = PyInt_FromLong(attr); + if (!py_attr) { + PyErr_NoMemory(); + goto fail; + } + + if (sss_python_set_add(py_missing, py_attr) != 0) { + /* If the set-add succeeded, it would steal the reference */ + Py_DECREF(py_attr); + goto fail; + } + } + + PyTuple_SET_ITEM(ret, 0, py_is_valid); + PyTuple_SET_ITEM(ret, 1, py_missing); + return ret; + +fail: + Py_XDECREF(ret); + Py_XDECREF(py_missing); + Py_XDECREF(py_is_valid); + return NULL; +} + +PyDoc_STRVAR(py_hbac_rule_validate__doc__, +"validate() -> (valid, missing)\n\n" +"Validate an HBAC rule\n" +"Returns a tuple of (bool, set). The boolean value describes whether\n" +"the rule is valid. If it is False, then the set lists all the missing " +"rule elements as HBAC_RULE_ELEMENT_* constants\n"); + +static PyMethodDef py_hbac_rule_methods[] = { + { sss_py_const_p(char, "validate"), + (PyCFunction) py_hbac_rule_validate, + METH_VARARGS, py_hbac_rule_validate__doc__, + }, + { NULL, NULL, 0, NULL } /* Sentinel */ +}; + PyDoc_STRVAR(HbacRuleObject_users__doc__, "(HbacRuleElement) Users and user groups for which this rule applies"); PyDoc_STRVAR(HbacRuleObject_services__doc__, @@ -959,6 +1047,7 @@ static PyTypeObject pyhbac_hbacrule_type = { .tp_init = (initproc) HbacRule_init, .tp_repr = (reprfunc) HbacRule_repr, .tp_members = py_hbac_rule_members, + .tp_methods = py_hbac_rule_methods, .tp_getset = py_hbac_rule_getset, .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .tp_doc = HbacRuleObject__doc__ @@ -1822,6 +1911,16 @@ initpyhbac(void) ret = PyModule_AddIntMacro(m, HBAC_CATEGORY_ALL); if (ret == -1) return; + /* HBAC rule elements */ + ret = PyModule_AddIntMacro(m, HBAC_RULE_ELEMENT_USERS); + if (ret == -1) return; + ret = PyModule_AddIntMacro(m, HBAC_RULE_ELEMENT_SERVICES); + if (ret == -1) return; + ret = PyModule_AddIntMacro(m, HBAC_RULE_ELEMENT_TARGETHOSTS); + if (ret == -1) return; + ret = PyModule_AddIntMacro(m, HBAC_RULE_ELEMENT_SOURCEHOSTS); + if (ret == -1) return; + /* enum hbac_eval_result */ ret = PyModule_AddIntMacro(m, HBAC_EVAL_ALLOW); if (ret == -1) return; diff --git a/src/tests/pyhbac-test.py b/src/tests/pyhbac-test.py index b19fe5861..5579180b0 100755 --- a/src/tests/pyhbac-test.py +++ b/src/tests/pyhbac-test.py @@ -232,6 +232,30 @@ class PyHbacRuleTest(unittest.TestCase): "srchosts <category 0 names [%s] groups []>>" % (name, service, targethost, srchost)) + def testValidate(self): + r = pyhbac.HbacRule('valid_rule') + + valid, missing = r.validate() + self.assertEqual(valid, False) + self.assertItemsEqual(missing, ( pyhbac.HBAC_RULE_ELEMENT_USERS, + pyhbac.HBAC_RULE_ELEMENT_SERVICES, + pyhbac.HBAC_RULE_ELEMENT_TARGETHOSTS, + pyhbac.HBAC_RULE_ELEMENT_SOURCEHOSTS )) + + r.users.names = [ "someuser" ] + r.services.names = [ "ssh" ] + + valid, missing = r.validate() + self.assertEqual(valid, False) + self.assertItemsEqual(missing, ( pyhbac.HBAC_RULE_ELEMENT_TARGETHOSTS, + pyhbac.HBAC_RULE_ELEMENT_SOURCEHOSTS )) + + r.srchosts.names = [ "host1" ] + r.targethosts.names = [ "host2" ] + + valid, missing = r.validate() + self.assertEqual(valid, True) + class PyHbacRequestElementTest(unittest.TestCase): def testInstantiateEmpty(self): el = pyhbac.HbacRequestElement() @@ -428,6 +452,12 @@ class PyHbacModuleTest(unittest.TestCase): assert hasattr(pyhbac, "HBAC_CATEGORY_NULL") assert hasattr(pyhbac, "HBAC_CATEGORY_ALL") + def testHasRuleElementTypes(self): + assert hasattr(pyhbac, "HBAC_RULE_ELEMENT_USERS") + assert hasattr(pyhbac, "HBAC_RULE_ELEMENT_SERVICES") + assert hasattr(pyhbac, "HBAC_RULE_ELEMENT_TARGETHOSTS") + assert hasattr(pyhbac, "HBAC_RULE_ELEMENT_SOURCEHOSTS") + def testHbacResultString(self): results = [ pyhbac.HBAC_EVAL_ALLOW, pyhbac.HBAC_EVAL_DENY, pyhbac.HBAC_EVAL_ERROR ] |