summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2011-07-30 12:57:24 +0200
committerStephen Gallagher <sgallagh@redhat.com>2011-08-01 09:23:16 -0400
commit1e710acc5ce225c7e6aa33bc0dfe8af65f49d182 (patch)
tree2d7214eb37f91580f397d69ab105a73f063fc1fb
parentd2d90b7195f58bd20628b1c62d1e1b01bfbb7a2b (diff)
downloadsssd-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.c99
-rwxr-xr-xsrc/tests/pyhbac-test.py30
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 ]