summaryrefslogtreecommitdiffstats
path: root/src/python
diff options
context:
space:
mode:
Diffstat (limited to 'src/python')
-rw-r--r--src/python/pyhbac.c2030
-rw-r--r--src/python/pysss.c358
-rw-r--r--src/python/pysss_murmur.c100
-rw-r--r--src/python/pysss_nss_idmap.c676
4 files changed, 3164 insertions, 0 deletions
diff --git a/src/python/pyhbac.c b/src/python/pyhbac.c
new file mode 100644
index 0000000..e12779d
--- /dev/null
+++ b/src/python/pyhbac.c
@@ -0,0 +1,2030 @@
+/*
+ Authors:
+ Jakub Hrozek <jhrozek@redhat.com>
+
+ Copyright (C) 2011 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "config.h"
+
+#include <Python.h>
+#include <structmember.h>
+
+#include "util/util.h"
+#include "util/sss_python.h"
+#include "lib/ipa_hbac/ipa_hbac.h"
+
+#define PYTHON_MODULE_NAME "pyhbac"
+
+#ifndef PYHBAC_ENCODING
+#define PYHBAC_ENCODING "UTF-8"
+#endif
+
+#define PYHBAC_ENCODING_ERRORS "strict"
+
+#define CHECK_ATTRIBUTE_DELETE(attr, attrname) do { \
+ if (attr == NULL) { \
+ PyErr_Format(PyExc_TypeError, \
+ "Cannot delete the %s attribute", \
+ attrname); \
+ return -1; \
+ } \
+} while(0)
+
+static PyObject *PyExc_HbacError;
+
+/* ==================== Utility functions ========================*/
+static char *
+py_strdup(const char *string)
+{
+ char *copy;
+
+ copy = PyMem_New(char, strlen(string)+1);
+ if (copy == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ return strcpy(copy, string);
+}
+
+static char *
+py_strcat_realloc(char *first, const char *second)
+{
+ char *new_first;
+ new_first = PyMem_Realloc(first, strlen(first) + strlen(second) + 1);
+ if (new_first == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ return strcat(new_first, second);
+}
+
+static PyObject *
+get_utf8_string(PyObject *obj, const char *attrname)
+{
+ const char *a = attrname ? attrname : "attribute";
+ PyObject *obj_utf8 = NULL;
+
+ if (PyBytes_Check(obj)) {
+ obj_utf8 = obj;
+ Py_INCREF(obj_utf8); /* Make sure we can DECREF later */
+ } else if (PyUnicode_Check(obj)) {
+ if ((obj_utf8 = PyUnicode_AsUTF8String(obj)) == NULL) {
+ return NULL;
+ }
+ } else {
+ PyErr_Format(PyExc_TypeError, "%s must be a string", a);
+ return NULL;
+ }
+
+ return obj_utf8;
+}
+
+static void
+free_string_list(const char **list)
+{
+ int i;
+
+ if (!list) return;
+
+ for (i=0; list[i]; i++) {
+ PyMem_Free(discard_const_p(char, list[i]));
+ }
+ PyMem_Free(list);
+}
+
+static const char **
+sequence_as_string_list(PyObject *seq, const char *paramname)
+{
+ const char *p = paramname ? paramname : "attribute values";
+ const char **ret;
+ PyObject *utf_item;
+ int i;
+ Py_ssize_t len;
+ PyObject *item;
+
+ if (!PySequence_Check(seq)) {
+ PyErr_Format(PyExc_TypeError,
+ "The object must be a sequence\n");
+ return NULL;
+ }
+
+ len = PySequence_Size(seq);
+ if (len == -1) return NULL;
+
+ ret = PyMem_New(const char *, (len+1));
+ if (!ret) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ for (i = 0; i < len; i++) {
+ item = PySequence_GetItem(seq, i);
+ if (item == NULL) {
+ break;
+ }
+
+ utf_item = get_utf8_string(item, p);
+ if (utf_item == NULL) {
+ Py_DECREF(item);
+ return NULL;
+ }
+
+ ret[i] = py_strdup(PyBytes_AsString(utf_item));
+ Py_DECREF(utf_item);
+ if (!ret[i]) {
+ Py_DECREF(item);
+ return NULL;
+ }
+ Py_DECREF(item);
+ }
+
+ ret[i] = NULL;
+ return ret;
+}
+
+static bool
+verify_sequence(PyObject *seq, const char *attrname)
+{
+ const char *a = attrname ? attrname : "attribute";
+
+ if (!PySequence_Check(seq)) {
+ PyErr_Format(PyExc_TypeError, "%s must be a sequence", a);
+ return false;
+ }
+
+ return true;
+}
+
+static int
+pyobject_to_category(PyObject *o)
+{
+ long c;
+
+ c = PYNUMBER_ASLONG(o);
+ if (c == -1 && PyErr_Occurred()) {
+ PyErr_Format(PyExc_TypeError,
+ "Invalid type for category element - must be an int\n");
+ return -1;
+ }
+
+ switch (c) {
+ case HBAC_CATEGORY_NULL:
+ case HBAC_CATEGORY_ALL:
+ return c;
+ }
+
+ PyErr_Format(PyExc_ValueError, "Invalid value %ld for category\n", c);
+ return -1;
+}
+
+static int
+native_category(PyObject *pycat, uint32_t *_category)
+{
+ PyObject *iterator;
+ PyObject *item;
+ uint32_t cat;
+ int ret;
+
+ iterator = PyObject_GetIter(pycat);
+ if (iterator == NULL) {
+ PyErr_Format(PyExc_RuntimeError, "Cannot iterate category\n");
+ return -1;
+ }
+
+ cat = 0;
+ while ((item = PyIter_Next(iterator))) {
+ ret = pyobject_to_category(item);
+ Py_DECREF(item);
+ if (ret == -1) {
+ Py_DECREF(iterator);
+ return -1;
+ }
+
+ cat |= ret;
+ }
+
+ Py_DECREF(iterator);
+
+ *_category = cat;
+ return 0;
+}
+
+static char *
+str_concat_sequence(PyObject *seq, const char *delim)
+{
+ Py_ssize_t size;
+ Py_ssize_t i;
+ PyObject *item;
+ char *s = NULL;
+ const char *part;
+
+ size = PySequence_Size(seq);
+
+ if (size == 0) {
+ s = py_strdup("");
+ if (s == NULL) {
+ return NULL;
+ }
+ return s;
+ }
+
+ for (i=0; i < size; i++) {
+ item = PySequence_GetItem(seq, i);
+ if (item == NULL) goto fail;
+
+#ifdef IS_PY3K
+ part = PyUnicode_AsUTF8(item);
+#else
+ part = PyString_AsString(item);
+#endif
+
+ if (s) {
+ s = py_strcat_realloc(s, delim);
+ if (s == NULL) goto fail;
+ s = py_strcat_realloc(s, part);
+ if (s == NULL) goto fail;
+ } else {
+ s = py_strdup(part);
+ if (s == NULL) goto fail;
+ }
+ Py_DECREF(item);
+ }
+
+ return s;
+
+fail:
+ Py_XDECREF(item);
+ PyMem_Free(s);
+ return NULL;
+}
+
+/* ================= HBAC Exception handling =====================*/
+static void
+set_hbac_exception(PyObject *exc, struct hbac_info *error)
+{
+ PyObject *obj;
+
+ obj = Py_BuildValue(sss_py_const_p(char, "(i,s)"), error->code,
+ error->rule_name ? error->rule_name : "no rule");
+
+ PyErr_SetObject(exc, obj);
+ Py_XDECREF(obj);
+}
+
+/* ==================== HBAC Rule Element ========================*/
+typedef struct {
+ PyObject_HEAD
+
+ PyObject *category;
+ PyObject *names;
+ PyObject *groups;
+} HbacRuleElement;
+
+static PyObject *
+HbacRuleElement_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ HbacRuleElement *self;
+
+ self = (HbacRuleElement *) type->tp_alloc(type, 0);
+ if (self == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ self->category = PySet_New(NULL);
+ self->names = PyList_New(0);
+ self->groups = PyList_New(0);
+ if (!self->names || !self->groups || !self->category) {
+ Py_DECREF(self);
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ return (PyObject *) self;
+}
+
+static int
+HbacRuleElement_clear(HbacRuleElement *self)
+{
+ Py_CLEAR(self->names);
+ Py_CLEAR(self->groups);
+ Py_CLEAR(self->category);
+ return 0;
+}
+
+static void
+HbacRuleElement_dealloc(HbacRuleElement *self)
+{
+ HbacRuleElement_clear(self);
+ Py_TYPE(self)->tp_free((PyObject*) self);
+}
+
+static int
+HbacRuleElement_traverse(HbacRuleElement *self, visitproc visit, void *arg)
+{
+ Py_VISIT(self->groups);
+ Py_VISIT(self->names);
+ Py_VISIT(self->category);
+ return 0;
+}
+
+static int
+hbac_rule_element_set_names(HbacRuleElement *self, PyObject *names,
+ void *closure);
+static int
+hbac_rule_element_set_groups(HbacRuleElement *self, PyObject *groups,
+ void *closure);
+static int
+hbac_rule_element_set_category(HbacRuleElement *self, PyObject *category,
+ void *closure);
+
+static int
+HbacRuleElement_init(HbacRuleElement *self, PyObject *args, PyObject *kwargs)
+{
+ const char * const kwlist[] = { "names", "groups", "category", NULL };
+ PyObject *names = NULL;
+ PyObject *groups = NULL;
+ PyObject *category = NULL;
+ PyObject *tmp = NULL;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ sss_py_const_p(char, "|OOO"),
+ discard_const_p(char *, kwlist),
+ &names, &groups, &category)) {
+ return -1;
+ }
+
+ if (names) {
+ if (hbac_rule_element_set_names(self, names, NULL) != 0) {
+ return -1;
+ }
+ }
+
+ if (groups) {
+ if (hbac_rule_element_set_groups(self, groups, NULL) != 0) {
+ return -1;
+ }
+ }
+
+ if (category) {
+ if (hbac_rule_element_set_category(self, category, NULL) != 0) {
+ return -1;
+ }
+ } else {
+ tmp = PYNUMBER_FROMLONG(HBAC_CATEGORY_NULL);
+ if (!tmp) {
+ return -1;
+ }
+
+ if (PySet_Add(self->category, tmp) != 0) {
+ Py_DECREF(tmp);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+hbac_rule_element_set_names(HbacRuleElement *self,
+ PyObject *names,
+ void *closure)
+{
+ CHECK_ATTRIBUTE_DELETE(names, "names");
+
+ if (!verify_sequence(names, "names")) {
+ return -1;
+ }
+
+ SAFE_SET(self->names, names);
+ return 0;
+}
+
+static PyObject *
+hbac_rule_element_get_names(HbacRuleElement *self, void *closure)
+{
+ Py_INCREF(self->names);
+ return self->names;
+}
+
+static int
+hbac_rule_element_set_groups(HbacRuleElement *self,
+ PyObject *groups,
+ void *closure)
+{
+ CHECK_ATTRIBUTE_DELETE(groups, "groups");
+
+ if (!verify_sequence(groups, "groups")) {
+ return -1;
+ }
+
+ SAFE_SET(self->groups, groups);
+ return 0;
+}
+
+static PyObject *
+hbac_rule_element_get_groups(HbacRuleElement *self, void *closure)
+{
+ Py_INCREF(self->groups);
+ return self->groups;
+}
+
+static int
+hbac_rule_element_set_category(HbacRuleElement *self,
+ PyObject *category,
+ void *closure)
+{
+ PyObject *iterator;
+ PyObject *item;
+ int ret;
+
+ CHECK_ATTRIBUTE_DELETE(category, "category");
+
+ if (!PySet_Check(category)) {
+ PyErr_Format(PyExc_TypeError, "The category must be a set type\n");
+ return -1;
+ }
+
+ /* Check the values, too */
+ iterator = PyObject_GetIter(category);
+ if (iterator == NULL) {
+ PyErr_Format(PyExc_RuntimeError, "Cannot iterate a set?\n");
+ return -1;
+ }
+
+ while ((item = PyIter_Next(iterator))) {
+ ret = pyobject_to_category(item);
+ Py_DECREF(item);
+ if (ret == -1) {
+ Py_DECREF(iterator);
+ return -1;
+ }
+ }
+
+ SAFE_SET(self->category, category);
+ Py_DECREF(iterator);
+ return 0;
+}
+
+static PyObject *
+hbac_rule_element_get_category(HbacRuleElement *self, void *closure)
+{
+ Py_INCREF(self->category);
+ return self->category;
+}
+
+static PyObject *
+HbacRuleElement_repr(HbacRuleElement *self)
+{
+ char *strnames = NULL;
+ char *strgroups = NULL;
+ uint32_t category;
+ int ret;
+ PyObject *o, *format, *args;
+
+ format = PyUnicode_FromString("<category %lu names [%s] groups [%s]>");
+ if (format == NULL) {
+ return NULL;
+ }
+
+ strnames = str_concat_sequence(self->names,
+ discard_const_p(char, ","));
+ strgroups = str_concat_sequence(self->groups,
+ discard_const_p(char, ","));
+ ret = native_category(self->category, &category);
+ if (strnames == NULL || strgroups == NULL || ret == -1) {
+ PyMem_Free(strnames);
+ PyMem_Free(strgroups);
+ Py_DECREF(format);
+ return NULL;
+ }
+
+ args = Py_BuildValue(sss_py_const_p(char, "Kss"),
+ (unsigned long long ) category,
+ strnames, strgroups);
+ if (args == NULL) {
+ PyMem_Free(strnames);
+ PyMem_Free(strgroups);
+ Py_DECREF(format);
+ return NULL;
+ }
+
+ o = PyUnicode_Format(format, args);
+ PyMem_Free(strnames);
+ PyMem_Free(strgroups);
+ Py_DECREF(format);
+ Py_DECREF(args);
+ return o;
+}
+
+PyDoc_STRVAR(HbacRuleElement_names__doc__,
+"(sequence of strings) A list of object names this element applies to");
+PyDoc_STRVAR(HbacRuleElement_groups__doc__,
+"(sequence of strings) A list of group names this element applies to");
+PyDoc_STRVAR(HbacRuleElement_category__doc__,
+"(set) A set of categories this rule falls into");
+
+static PyGetSetDef py_hbac_rule_element_getset[] = {
+ { discard_const_p(char, "names"),
+ (getter) hbac_rule_element_get_names,
+ (setter) hbac_rule_element_set_names,
+ HbacRuleElement_names__doc__,
+ NULL },
+
+ { discard_const_p(char, "groups"),
+ (getter) hbac_rule_element_get_groups,
+ (setter) hbac_rule_element_set_groups,
+ HbacRuleElement_groups__doc__,
+ NULL },
+
+ { discard_const_p(char, "category"),
+ (getter) hbac_rule_element_get_category,
+ (setter) hbac_rule_element_set_category,
+ HbacRuleElement_category__doc__,
+ NULL },
+
+ { NULL, 0, 0, 0, NULL } /* Sentinel */
+};
+
+PyDoc_STRVAR(HbacRuleElement__doc__,
+"IPA HBAC Rule Element\n\n"
+"HbacRuleElement() -> new empty rule element\n"
+"HbacRuleElement([names], [groups], [category]) -> optionally, provide\n"
+"names and/or groups and/or category\n");
+
+static PyTypeObject pyhbac_hbacrule_element_type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = sss_py_const_p(char, "pyhbac.HbacRuleElement"),
+ .tp_basicsize = sizeof(HbacRuleElement),
+ .tp_new = HbacRuleElement_new,
+ .tp_dealloc = (destructor) HbacRuleElement_dealloc,
+ .tp_traverse = (traverseproc) HbacRuleElement_traverse,
+ .tp_clear = (inquiry) HbacRuleElement_clear,
+ .tp_init = (initproc) HbacRuleElement_init,
+ .tp_repr = (reprfunc) HbacRuleElement_repr,
+ .tp_getset = py_hbac_rule_element_getset,
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
+ .tp_doc = HbacRuleElement__doc__
+};
+
+static void
+free_hbac_rule_element(struct hbac_rule_element *el)
+{
+ if (!el) return;
+
+ free_string_list(el->names);
+ free_string_list(el->groups);
+ PyMem_Free(el);
+}
+
+struct hbac_rule_element *
+HbacRuleElement_to_native(HbacRuleElement *pyel)
+{
+ struct hbac_rule_element *el = NULL;
+ int ret;
+
+ /* check the type, None would wreak havoc here because for some reason
+ * it would pass the sequence check */
+ if (!PyObject_IsInstance((PyObject *) pyel,
+ (PyObject *) &pyhbac_hbacrule_element_type)) {
+ PyErr_Format(PyExc_TypeError,
+ "The element must be of type HbacRuleElement\n");
+ goto fail;
+ }
+
+ el = PyMem_Malloc(sizeof(struct hbac_rule_element));
+ if (!el) {
+ PyErr_NoMemory();
+ goto fail;
+ }
+
+ ret = native_category(pyel->category, &el->category);
+ el->names = sequence_as_string_list(pyel->names, "names");
+ el->groups = sequence_as_string_list(pyel->groups, "groups");
+ if (!el->names || !el->groups || ret == -1) {
+ goto fail;
+ }
+
+ return el;
+
+fail:
+ free_hbac_rule_element(el);
+ return NULL;
+}
+
+/* ==================== HBAC Rule ========================*/
+typedef struct {
+ PyObject_HEAD
+
+ PyObject *name;
+ bool enabled;
+
+ HbacRuleElement *users;
+ HbacRuleElement *services;
+ HbacRuleElement *targethosts;
+ 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)
+{
+ HbacRuleObject *self;
+
+ self = (HbacRuleObject *) type->tp_alloc(type, 0);
+ if (self == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ self->name = PyUnicode_FromString("");
+ if (self->name == NULL) {
+ Py_DECREF(self);
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ self->enabled = false;
+
+ self->services = (HbacRuleElement *) HbacRuleElement_new(
+ &pyhbac_hbacrule_element_type,
+ NULL, NULL);
+ self->users = (HbacRuleElement *) HbacRuleElement_new(
+ &pyhbac_hbacrule_element_type,
+ NULL, NULL);
+ self->targethosts = (HbacRuleElement *) HbacRuleElement_new(
+ &pyhbac_hbacrule_element_type,
+ NULL, NULL);
+ self->srchosts = (HbacRuleElement *) HbacRuleElement_new(
+ &pyhbac_hbacrule_element_type,
+ NULL, NULL);
+ if (self->services == NULL || self->users == NULL ||
+ self->targethosts == NULL || self->srchosts == NULL) {
+ Py_XDECREF(self->services);
+ Py_XDECREF(self->users);
+ Py_XDECREF(self->targethosts);
+ Py_XDECREF(self->srchosts);
+ Py_DECREF(self->name);
+ Py_DECREF(self);
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ return (PyObject *) self;
+}
+
+static int
+HbacRule_clear(HbacRuleObject *self)
+{
+ Py_CLEAR(self->name);
+ Py_CLEAR(self->services);
+ Py_CLEAR(self->users);
+ Py_CLEAR(self->targethosts);
+ Py_CLEAR(self->srchosts);
+ return 0;
+}
+
+static void
+HbacRule_dealloc(HbacRuleObject *self)
+{
+ HbacRule_clear(self);
+ Py_TYPE(self)->tp_free((PyObject*) self);
+}
+
+static int
+HbacRule_traverse(HbacRuleObject *self, visitproc visit, void *arg)
+{
+ Py_VISIT((PyObject *) self->name);
+ Py_VISIT((PyObject *) self->services);
+ Py_VISIT((PyObject *) self->users);
+ Py_VISIT((PyObject *) self->targethosts);
+ Py_VISIT((PyObject *) self->srchosts);
+ return 0;
+}
+
+static int
+hbac_rule_set_enabled(HbacRuleObject *self, PyObject *enabled, void *closure);
+static int
+hbac_rule_set_name(HbacRuleObject *self, PyObject *name, void *closure);
+
+static int
+HbacRule_init(HbacRuleObject *self, PyObject *args, PyObject *kwargs)
+{
+ const char * const kwlist[] = { "name", "enabled", NULL };
+ PyObject *name = NULL;
+ PyObject *empty_tuple = NULL;
+ PyObject *enabled=NULL;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ sss_py_const_p(char, "O|O"),
+ discard_const_p(char *, kwlist),
+ &name, &enabled)) {
+ return -1;
+ }
+
+ if (enabled) {
+ if (hbac_rule_set_enabled(self, enabled, NULL) == -1) {
+ return -1;
+ }
+ }
+
+ if (hbac_rule_set_name(self, name, NULL) == -1) {
+ return -1;
+ }
+
+ empty_tuple = PyTuple_New(0);
+ if (!empty_tuple) {
+ return -1;
+ }
+
+ if (HbacRuleElement_init(self->users, empty_tuple, NULL) == -1 ||
+ HbacRuleElement_init(self->services, empty_tuple, NULL) == -1 ||
+ HbacRuleElement_init(self->targethosts, empty_tuple, NULL) == -1 ||
+ HbacRuleElement_init(self->srchosts, empty_tuple, NULL) == -1) {
+ Py_DECREF(empty_tuple);
+ return -1;
+ }
+
+ Py_DECREF(empty_tuple);
+ return 0;
+}
+
+static int
+hbac_rule_set_enabled(HbacRuleObject *self, PyObject *enabled, void *closure)
+{
+ CHECK_ATTRIBUTE_DELETE(enabled, "enabled");
+
+ if (PyBytes_Check(enabled) || PyUnicode_Check(enabled)) {
+ PyObject *utf8_str;
+ char *str;
+
+ utf8_str = get_utf8_string(enabled, "enabled");
+ if (!utf8_str) return -1;
+ str = PyBytes_AsString(utf8_str);
+ if (!str) {
+ Py_DECREF(utf8_str);
+ return -1;
+ }
+
+ if (strcasecmp(str, "true") == 0) {
+ self->enabled = true;
+ } else if (strcasecmp(str, "false") == 0) {
+ self->enabled = false;
+ } else {
+ PyErr_Format(PyExc_ValueError,
+ "enabled only accepts 'true' of 'false' "
+ "string literals");
+ Py_DECREF(utf8_str);
+ return -1;
+ }
+
+ Py_DECREF(utf8_str);
+ return 0;
+ } else if (PyBool_Check(enabled) == true) {
+ self->enabled = (enabled == Py_True);
+ return 0;
+ } else if (PYNUMBER_CHECK(enabled)) {
+ switch(PYNUMBER_ASLONG(enabled)) {
+ case 0:
+ self->enabled = false;
+ break;
+ case 1:
+ self->enabled = true;
+ break;
+ default:
+ PyErr_Format(PyExc_ValueError,
+ "enabled only accepts '0' of '1' "
+ "integer constants");
+ return -1;
+ }
+ return 0;
+ }
+
+ PyErr_Format(PyExc_TypeError, "enabled must be a boolean, an integer "
+ "1 or 0 or a string constant true/false");
+ return -1;
+
+}
+
+static PyObject *
+hbac_rule_get_enabled(HbacRuleObject *self, void *closure)
+{
+ if (self->enabled) {
+ Py_RETURN_TRUE;
+ }
+
+ Py_RETURN_FALSE;
+}
+
+static int
+hbac_rule_set_name(HbacRuleObject *self, PyObject *name, void *closure)
+{
+ CHECK_ATTRIBUTE_DELETE(name, "name");
+
+ if (!PyBytes_Check(name) && !PyUnicode_Check(name)) {
+ PyErr_Format(PyExc_TypeError, "name must be a string or Unicode");
+ return -1;
+ }
+
+ SAFE_SET(self->name, name);
+ return 0;
+}
+
+static PyObject *
+hbac_rule_get_name(HbacRuleObject *self, void *closure)
+{
+ if (PyUnicode_Check(self->name)) {
+ Py_INCREF(self->name);
+ return self->name;
+ } else if (PyBytes_Check(self->name)) {
+ return PyUnicode_FromEncodedObject(self->name,
+ PYHBAC_ENCODING, PYHBAC_ENCODING_ERRORS);
+ }
+
+ /* setter does typechecking but let us be paranoid */
+ PyErr_Format(PyExc_TypeError, "name must be a string or Unicode");
+ return NULL;
+}
+
+static PyObject *
+HbacRule_repr(HbacRuleObject *self)
+{
+ PyObject *users_repr;
+ PyObject *services_repr;
+ PyObject *targethosts_repr;
+ PyObject *srchosts_repr;
+ PyObject *o, *format, *args;
+
+ format = PyUnicode_FromString("<name %s enabled %d "
+ "users %s services %s "
+ "targethosts %s srchosts %s>");
+ if (format == NULL) {
+ return NULL;
+ }
+
+ users_repr = HbacRuleElement_repr(self->users);
+ services_repr = HbacRuleElement_repr(self->services);
+ targethosts_repr = HbacRuleElement_repr(self->targethosts);
+ srchosts_repr = HbacRuleElement_repr(self->srchosts);
+ if (users_repr == NULL || services_repr == NULL ||
+ targethosts_repr == NULL || srchosts_repr == NULL) {
+ Py_XDECREF(users_repr);
+ Py_XDECREF(services_repr);
+ Py_XDECREF(targethosts_repr);
+ Py_XDECREF(srchosts_repr);
+ Py_DECREF(format);
+ return NULL;
+ }
+
+ args = Py_BuildValue(sss_py_const_p(char, "OiOOOO"),
+ self->name, self->enabled,
+ users_repr, services_repr,
+ targethosts_repr, srchosts_repr);
+ if (args == NULL) {
+ Py_DECREF(users_repr);
+ Py_DECREF(services_repr);
+ Py_DECREF(targethosts_repr);
+ Py_DECREF(srchosts_repr);
+ Py_DECREF(format);
+ return NULL;
+ }
+
+ o = PyUnicode_Format(format, args);
+ Py_DECREF(users_repr);
+ Py_DECREF(services_repr);
+ Py_DECREF(targethosts_repr);
+ Py_DECREF(srchosts_repr);
+ Py_DECREF(format);
+ Py_DECREF(args);
+ 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 = PySet_New(NULL);
+ 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 = PYNUMBER_FROMLONG(attr);
+ if (!py_attr) {
+ PyErr_NoMemory();
+ goto fail;
+ }
+
+ if (PySet_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__,
+"(HbacRuleElement) Services and service groups for which this rule applies");
+PyDoc_STRVAR(HbacRuleObject_targethosts__doc__,
+"(HbacRuleElement) Target hosts for which this rule applies");
+PyDoc_STRVAR(HbacRuleObject_srchosts__doc__,
+"(HbacRuleElement) Source hosts for which this rule applies");
+
+static PyMemberDef py_hbac_rule_members[] = {
+ { discard_const_p(char, "users"), T_OBJECT_EX,
+ offsetof(HbacRuleObject, users), 0,
+ HbacRuleObject_users__doc__ },
+
+ { discard_const_p(char, "services"), T_OBJECT_EX,
+ offsetof(HbacRuleObject, services), 0,
+ HbacRuleObject_services__doc__ },
+
+ { discard_const_p(char, "targethosts"), T_OBJECT_EX,
+ offsetof(HbacRuleObject, targethosts), 0,
+ HbacRuleObject_targethosts__doc__},
+
+ { discard_const_p(char, "srchosts"), T_OBJECT_EX,
+ offsetof(HbacRuleObject, srchosts), 0,
+ HbacRuleObject_srchosts__doc__},
+
+ { NULL, 0, 0, 0, NULL } /* Sentinel */
+};
+
+PyDoc_STRVAR(HbacRuleObject_enabled__doc__,
+"(bool) Is the rule enabled");
+PyDoc_STRVAR(HbacRuleObject_name__doc__,
+"(string) The name of the rule");
+
+static PyGetSetDef py_hbac_rule_getset[] = {
+ { discard_const_p(char, "enabled"),
+ (getter) hbac_rule_get_enabled,
+ (setter) hbac_rule_set_enabled,
+ HbacRuleObject_enabled__doc__,
+ NULL },
+
+ { discard_const_p(char, "name"),
+ (getter) hbac_rule_get_name,
+ (setter) hbac_rule_set_name,
+ HbacRuleObject_name__doc__,
+ NULL },
+
+ {NULL, 0, 0, 0, NULL} /* Sentinel */
+};
+
+PyDoc_STRVAR(HbacRuleObject__doc__,
+"IPA HBAC Rule\n\n"
+"HbacRule(name, [enabled]) -> instantiate an empty rule, optionally\n"
+"specify whether it is enabled. Rules are created disabled by default and\n"
+"contain empty HbacRuleElement instances in services, users, targethosts\n"
+"and srchosts attributes.\n");
+
+static PyTypeObject pyhbac_hbacrule_type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = sss_py_const_p(char, "pyhbac.HbacRule"),
+ .tp_basicsize = sizeof(HbacRuleObject),
+ .tp_new = HbacRule_new,
+ .tp_dealloc = (destructor) HbacRule_dealloc,
+ .tp_traverse = (traverseproc) HbacRule_traverse,
+ .tp_clear = (inquiry) HbacRule_clear,
+ .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__
+};
+
+static void
+free_hbac_rule(struct hbac_rule *rule)
+{
+ if (!rule) return;
+
+ free_hbac_rule_element(rule->services);
+ free_hbac_rule_element(rule->users);
+ free_hbac_rule_element(rule->targethosts);
+ free_hbac_rule_element(rule->srchosts);
+
+ PyMem_Free(discard_const_p(char, rule->name));
+ PyMem_Free(rule);
+}
+
+static struct hbac_rule *
+HbacRule_to_native(HbacRuleObject *pyrule)
+{
+ struct hbac_rule *rule = NULL;
+ PyObject *utf_name;
+
+ rule = PyMem_Malloc(sizeof(struct hbac_rule));
+ if (!rule) {
+ PyErr_NoMemory();
+ goto fail;
+ }
+
+ if (!PyObject_IsInstance((PyObject *) pyrule,
+ (PyObject *) &pyhbac_hbacrule_type)) {
+ PyErr_Format(PyExc_TypeError,
+ "The rule must be of type HbacRule\n");
+ goto fail;
+ }
+
+ utf_name = get_utf8_string(pyrule->name, "name");
+ if (utf_name == NULL) {
+ return NULL;
+ }
+
+ rule->name = py_strdup(PyBytes_AsString(utf_name));
+ Py_DECREF(utf_name);
+ if (rule->name == NULL) {
+ goto fail;
+ }
+
+ rule->services = HbacRuleElement_to_native(pyrule->services);
+ rule->users = HbacRuleElement_to_native(pyrule->users);
+ rule->targethosts = HbacRuleElement_to_native(pyrule->targethosts);
+ rule->srchosts = HbacRuleElement_to_native(pyrule->srchosts);
+ if (!rule->services || !rule->users ||
+ !rule->targethosts || !rule->srchosts) {
+ goto fail;
+ }
+
+ rule->enabled = pyrule->enabled;
+ return rule;
+
+fail:
+ free_hbac_rule(rule);
+ return NULL;
+}
+
+/* ==================== HBAC Request Element ========================*/
+typedef struct {
+ PyObject_HEAD
+
+ PyObject *name;
+ PyObject *groups;
+} HbacRequestElement;
+
+static PyObject *
+HbacRequestElement_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ HbacRequestElement *self;
+
+ self = (HbacRequestElement *) type->tp_alloc(type, 0);
+ if (self == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ self->name = PyUnicode_FromString("");
+ if (self->name == NULL) {
+ PyErr_NoMemory();
+ Py_DECREF(self);
+ return NULL;
+ }
+
+ self->groups = PyList_New(0);
+ if (self->groups == NULL) {
+ Py_DECREF(self->name);
+ Py_DECREF(self);
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ return (PyObject *) self;
+}
+
+static int
+HbacRequestElement_clear(HbacRequestElement *self)
+{
+ Py_CLEAR(self->name);
+ Py_CLEAR(self->groups);
+ return 0;
+}
+
+static void
+HbacRequestElement_dealloc(HbacRequestElement *self)
+{
+ HbacRequestElement_clear(self);
+ Py_TYPE(self)->tp_free((PyObject*) self);
+}
+
+static int
+HbacRequestElement_traverse(HbacRequestElement *self,
+ visitproc visit, void *arg)
+{
+ Py_VISIT(self->name);
+ Py_VISIT(self->groups);
+ return 0;
+}
+
+static int
+hbac_request_element_set_groups(HbacRequestElement *self,
+ PyObject *groups,
+ void *closure);
+static int
+hbac_request_element_set_name(HbacRequestElement *self,
+ PyObject *name,
+ void *closure);
+
+static int
+HbacRequestElement_init(HbacRequestElement *self,
+ PyObject *args,
+ PyObject *kwargs)
+{
+ const char * const kwlist[] = { "name", "groups", NULL };
+ PyObject *name = NULL;
+ PyObject *groups = NULL;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ sss_py_const_p(char, "|OO"),
+ discard_const_p(char *, kwlist),
+ &name, &groups)) {
+ return -1;
+ }
+
+ if (name) {
+ if (hbac_request_element_set_name(self, name, NULL) != 0) {
+ return -1;
+ }
+ }
+
+ if (groups) {
+ if (hbac_request_element_set_groups(self, groups, NULL) != 0) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+hbac_request_element_set_name(HbacRequestElement *self,
+ PyObject *name,
+ void *closure)
+{
+ CHECK_ATTRIBUTE_DELETE(name, "name");
+
+ if (!PyBytes_Check(name) && !PyUnicode_Check(name)) {
+ PyErr_Format(PyExc_TypeError, "name must be a string or Unicode");
+ return -1;
+ }
+
+ SAFE_SET(self->name, name);
+ return 0;
+}
+
+static PyObject *
+hbac_request_element_get_name(HbacRequestElement *self, void *closure)
+{
+ if (PyUnicode_Check(self->name)) {
+ Py_INCREF(self->name);
+ return self->name;
+ } else if (PyBytes_Check(self->name)) {
+ return PyUnicode_FromEncodedObject(self->name,
+ PYHBAC_ENCODING, PYHBAC_ENCODING_ERRORS);
+ }
+
+ /* setter does typechecking but let us be paranoid */
+ PyErr_Format(PyExc_TypeError, "name must be a string or Unicode");
+ return NULL;
+}
+
+static int
+hbac_request_element_set_groups(HbacRequestElement *self,
+ PyObject *groups,
+ void *closure)
+{
+ CHECK_ATTRIBUTE_DELETE(groups, "groups");
+
+ if (!verify_sequence(groups, "groups")) {
+ return -1;
+ }
+
+ SAFE_SET(self->groups, groups);
+ return 0;
+}
+
+static PyObject *
+hbac_request_element_get_groups(HbacRequestElement *self, void *closure)
+{
+ Py_INCREF(self->groups);
+ return self->groups;
+}
+
+static PyObject *
+HbacRequestElement_repr(HbacRequestElement *self)
+{
+ char *strgroups;
+ PyObject *o, *format, *args;
+
+ format = PyUnicode_FromString("<name %s groups [%s]>");
+ if (format == NULL) {
+ return NULL;
+ }
+
+ strgroups = str_concat_sequence(self->groups, discard_const_p(char, ","));
+ if (strgroups == NULL) {
+ Py_DECREF(format);
+ return NULL;
+ }
+
+ args = Py_BuildValue(sss_py_const_p(char, "Os"), self->name, strgroups);
+ if (args == NULL) {
+ PyMem_Free(strgroups);
+ Py_DECREF(format);
+ return NULL;
+ }
+
+ o = PyUnicode_Format(format, args);
+ PyMem_Free(strgroups);
+ Py_DECREF(format);
+ Py_DECREF(args);
+ return o;
+}
+
+PyDoc_STRVAR(HbacRequestElement_name__doc__,
+"(string) An object name this element applies to");
+PyDoc_STRVAR(HbacRequestElement_groups__doc__,
+"(list of strings) A list of group names this element applies to");
+
+static PyGetSetDef py_hbac_request_element_getset[] = {
+ { discard_const_p(char, "name"),
+ (getter) hbac_request_element_get_name,
+ (setter) hbac_request_element_set_name,
+ HbacRequestElement_name__doc__,
+ NULL },
+
+ { discard_const_p(char, "groups"),
+ (getter) hbac_request_element_get_groups,
+ (setter) hbac_request_element_set_groups,
+ HbacRequestElement_groups__doc__,
+ NULL },
+
+ { NULL, 0, 0, 0, NULL } /* Sentinel */
+};
+
+PyDoc_STRVAR(HbacRequestElement__doc__,
+"IPA HBAC Request Element\n\n"
+"HbacRequestElement() -> new empty request element\n"
+"HbacRequestElement([name], [groups]) -> optionally, provide name and/or "
+"groups\n");
+
+static PyTypeObject pyhbac_hbacrequest_element_type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = sss_py_const_p(char, "pyhbac.HbacRequestElement"),
+ .tp_basicsize = sizeof(HbacRequestElement),
+ .tp_new = HbacRequestElement_new,
+ .tp_dealloc = (destructor) HbacRequestElement_dealloc,
+ .tp_traverse = (traverseproc) HbacRequestElement_traverse,
+ .tp_clear = (inquiry) HbacRequestElement_clear,
+ .tp_init = (initproc) HbacRequestElement_init,
+ .tp_repr = (reprfunc) HbacRequestElement_repr,
+ .tp_getset = py_hbac_request_element_getset,
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
+ .tp_doc = HbacRequestElement__doc__
+};
+
+static void
+free_hbac_request_element(struct hbac_request_element *el)
+{
+ if (!el) return;
+
+ PyMem_Free(discard_const_p(char, el->name));
+ free_string_list(el->groups);
+ PyMem_Free(el);
+}
+
+static struct hbac_request_element *
+HbacRequestElement_to_native(HbacRequestElement *pyel)
+{
+ struct hbac_request_element *el = NULL;
+ PyObject *utf_name;
+
+ if (!PyObject_IsInstance((PyObject *) pyel,
+ (PyObject *) &pyhbac_hbacrequest_element_type)) {
+ PyErr_Format(PyExc_TypeError,
+ "The element must be of type HbacRequestElement\n");
+ goto fail;
+ }
+
+ el = PyMem_Malloc(sizeof(struct hbac_request_element));
+ if (!el) {
+ PyErr_NoMemory();
+ goto fail;
+ }
+
+ utf_name = get_utf8_string(pyel->name, "name");
+ if (utf_name == NULL) {
+ return NULL;
+ }
+
+ el->name = py_strdup(PyBytes_AsString(utf_name));
+ Py_DECREF(utf_name);
+ if (!el->name) {
+ goto fail;
+ }
+
+ el->groups = sequence_as_string_list(pyel->groups, "groups");
+ if (!el->groups) {
+ goto fail;
+ }
+
+ return el;
+
+fail:
+ free_hbac_request_element(el);
+ return NULL;
+}
+
+/* ==================== HBAC Request ========================*/
+typedef struct {
+ PyObject_HEAD
+
+ HbacRequestElement *service;
+ HbacRequestElement *user;
+ HbacRequestElement *targethost;
+ HbacRequestElement *srchost;
+
+ PyObject *rule_name;
+} HbacRequest;
+
+static PyObject *
+HbacRequest_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ HbacRequest *self;
+
+ self = (HbacRequest *) type->tp_alloc(type, 0);
+ if (self == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ self->service = (HbacRequestElement *) HbacRequestElement_new(
+ &pyhbac_hbacrequest_element_type,
+ NULL, NULL);
+ self->user = (HbacRequestElement *) HbacRequestElement_new(
+ &pyhbac_hbacrequest_element_type,
+ NULL, NULL);
+ self->targethost = (HbacRequestElement *) HbacRequestElement_new(
+ &pyhbac_hbacrequest_element_type,
+ NULL, NULL);
+ self->srchost = (HbacRequestElement *) HbacRequestElement_new(
+ &pyhbac_hbacrequest_element_type,
+ NULL, NULL);
+ if (self->service == NULL || self->user == NULL ||
+ self->targethost == NULL || self->srchost == NULL) {
+ Py_XDECREF(self->service);
+ Py_XDECREF(self->user);
+ Py_XDECREF(self->targethost);
+ Py_XDECREF(self->srchost);
+ Py_DECREF(self);
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ return (PyObject *) self;
+}
+
+static int
+HbacRequest_clear(HbacRequest *self)
+{
+ Py_CLEAR(self->service);
+ Py_CLEAR(self->user);
+ Py_CLEAR(self->targethost);
+ Py_CLEAR(self->srchost);
+ Py_CLEAR(self->rule_name);
+ return 0;
+}
+
+static void
+HbacRequest_dealloc(HbacRequest *self)
+{
+ HbacRequest_clear(self);
+ Py_TYPE(self)->tp_free((PyObject*) self);
+}
+
+static int
+HbacRequest_traverse(HbacRequest *self, visitproc visit, void *arg)
+{
+ Py_VISIT((PyObject *) self->service);
+ Py_VISIT((PyObject *) self->user);
+ Py_VISIT((PyObject *) self->targethost);
+ Py_VISIT((PyObject *) self->srchost);
+ return 0;
+}
+
+static int
+HbacRequest_init(HbacRequest *self, PyObject *args, PyObject *kwargs)
+{
+ PyObject *empty_tuple = NULL;
+
+ empty_tuple = PyTuple_New(0);
+ if (!empty_tuple) {
+ PyErr_NoMemory();
+ return -1;
+ }
+
+ self->rule_name = NULL;
+
+ if (HbacRequestElement_init(self->user, empty_tuple, NULL) == -1 ||
+ HbacRequestElement_init(self->service, empty_tuple, NULL) == -1 ||
+ HbacRequestElement_init(self->targethost, empty_tuple, NULL) == -1 ||
+ HbacRequestElement_init(self->srchost, empty_tuple, NULL) == -1) {
+ Py_DECREF(empty_tuple);
+ return -1;
+ }
+
+ Py_DECREF(empty_tuple);
+ return 0;
+}
+
+PyDoc_STRVAR(py_hbac_evaluate__doc__,
+"evaluate(rules) -> int\n\n"
+"Evaluate a set of HBAC rules.\n"
+"rules is a sequence of HbacRule objects. The returned value describes\n"
+"the result of evaluation and will have one of HBAC_EVAL_* values.\n"
+"Use hbac_result_string() to get textual representation of the result\n"
+"On error, HbacError exception is raised.\n"
+"If HBAC_EVAL_ALLOW is returned, the class attribute rule_name would\n"
+"contain the name of the rule that matched. Otherwise, the attribute\n"
+"contains None\n");
+
+static struct hbac_eval_req *
+HbacRequest_to_native(HbacRequest *pyreq);
+
+static void
+free_hbac_rule_list(struct hbac_rule **rules)
+{
+ int i;
+
+ if (!rules) return;
+
+ for(i=0; rules[i]; i++) {
+ free_hbac_rule(rules[i]);
+ }
+ PyMem_Free(rules);
+}
+
+static void
+free_hbac_eval_req(struct hbac_eval_req *req);
+
+static PyObject *
+py_hbac_evaluate(HbacRequest *self, PyObject *args)
+{
+ PyObject *py_rules_list = NULL;
+ PyObject *py_rule = NULL;
+ Py_ssize_t num_rules;
+ struct hbac_rule **rules = NULL;
+ struct hbac_eval_req *hbac_req = NULL;
+ enum hbac_eval_result eres;
+ struct hbac_info *info = NULL;
+ PyObject *ret = NULL;
+ long i;
+
+ if (!PyArg_ParseTuple(args, sss_py_const_p(char, "O"), &py_rules_list)) {
+ goto fail;
+ }
+
+ if (!PySequence_Check(py_rules_list)) {
+ PyErr_Format(PyExc_TypeError,
+ "The parameter rules must be a sequence\n");
+ goto fail;
+ }
+
+ num_rules = PySequence_Size(py_rules_list);
+ rules = PyMem_New(struct hbac_rule *, num_rules+1);
+ if (!rules) {
+ PyErr_NoMemory();
+ goto fail;
+ }
+
+ for (i=0; i < num_rules; i++) {
+ py_rule = PySequence_GetItem(py_rules_list, i);
+
+ if (!PyObject_IsInstance(py_rule,
+ (PyObject *) &pyhbac_hbacrule_type)) {
+ PyErr_Format(PyExc_TypeError,
+ "A rule must be of type HbacRule\n");
+ goto fail;
+ }
+
+ rules[i] = HbacRule_to_native((HbacRuleObject *) py_rule);
+ if (!rules[i]) {
+ /* 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;
+ }
+ }
+ rules[num_rules] = NULL;
+
+ hbac_req = HbacRequest_to_native(self);
+ if (!hbac_req) {
+ if (!PyErr_Occurred()) {
+ PyErr_Format(PyExc_IOError,
+ "Could not convert HbacRequest to native type\n");
+ }
+ goto fail;
+ }
+
+ Py_XDECREF(self->rule_name);
+ self->rule_name = NULL;
+
+ eres = hbac_evaluate(rules, hbac_req, &info);
+ switch (eres) {
+ case HBAC_EVAL_ALLOW:
+ self->rule_name = PyUnicode_FromString(info->rule_name);
+ if (!self->rule_name) {
+ PyErr_NoMemory();
+ goto fail;
+ }
+ /* FALLTHROUGH */
+ SSS_ATTRIBUTE_FALLTHROUGH;
+ case HBAC_EVAL_DENY:
+ ret = PYNUMBER_FROMLONG(eres);
+ break;
+ case HBAC_EVAL_ERROR:
+ set_hbac_exception(PyExc_HbacError, info);
+ goto fail;
+ case HBAC_EVAL_OOM:
+ PyErr_NoMemory();
+ goto fail;
+ }
+
+ free_hbac_eval_req(hbac_req);
+ free_hbac_rule_list(rules);
+ hbac_free_info(info);
+ return ret;
+
+fail:
+ hbac_free_info(info);
+ free_hbac_eval_req(hbac_req);
+ free_hbac_rule_list(rules);
+ return NULL;
+}
+
+static PyObject *
+hbac_request_element_get_rule_name(HbacRequest *self, void *closure)
+{
+ if (self->rule_name == NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ } else if (PyUnicode_Check(self->rule_name)) {
+ Py_INCREF(self->rule_name);
+ return self->rule_name;
+ }
+
+ PyErr_Format(PyExc_TypeError, "rule_name is not Unicode");
+ return NULL;
+}
+
+static PyObject *
+HbacRequest_repr(HbacRequest *self)
+{
+ PyObject *user_repr;
+ PyObject *service_repr;
+ PyObject *targethost_repr;
+ PyObject *srchost_repr;
+ PyObject *o, *format, *args;
+
+ format = PyUnicode_FromString("<user %s service %s "
+ "targethost %s srchost %s>");
+ if (format == NULL) {
+ return NULL;
+ }
+
+ user_repr = HbacRequestElement_repr(self->user);
+ service_repr = HbacRequestElement_repr(self->service);
+ targethost_repr = HbacRequestElement_repr(self->targethost);
+ srchost_repr = HbacRequestElement_repr(self->srchost);
+ if (user_repr == NULL || service_repr == NULL ||
+ targethost_repr == NULL || srchost_repr == NULL) {
+ Py_XDECREF(user_repr);
+ Py_XDECREF(service_repr);
+ Py_XDECREF(targethost_repr);
+ Py_XDECREF(srchost_repr);
+ Py_DECREF(format);
+ return NULL;
+ }
+
+ args = Py_BuildValue(sss_py_const_p(char, "OOOO"),
+ user_repr, service_repr,
+ targethost_repr, srchost_repr);
+ if (args == NULL) {
+ Py_DECREF(user_repr);
+ Py_DECREF(service_repr);
+ Py_DECREF(targethost_repr);
+ Py_DECREF(srchost_repr);
+ Py_DECREF(format);
+ return NULL;
+ }
+
+ o = PyUnicode_Format(format, args);
+ Py_DECREF(user_repr);
+ Py_DECREF(service_repr);
+ Py_DECREF(targethost_repr);
+ Py_DECREF(srchost_repr);
+ Py_DECREF(format);
+ Py_DECREF(args);
+ return o;
+}
+
+static PyMethodDef py_hbac_request_methods[] = {
+ { sss_py_const_p(char, "evaluate"),
+ (PyCFunction) py_hbac_evaluate,
+ METH_VARARGS, py_hbac_evaluate__doc__
+ },
+ { NULL, NULL, 0, NULL } /* Sentinel */
+};
+
+PyDoc_STRVAR(HbacRequest_service__doc__,
+"(HbacRequestElement) This is a list of service DNs to check, it must\n"
+"consist of the actual service requested, as well as all parent groups\n"
+"containing that service");
+PyDoc_STRVAR(HbacRequest_user__doc__,
+"(HbacRequestElement) This is a list of user DNs to check, it must consist\n"
+"of the actual user requested, as well as all parent groups containing\n"
+"that user.");
+PyDoc_STRVAR(HbacRequest_targethost__doc__,
+"(HbacRequestElement) This is a list of target hosts to check, it must\n"
+"consist of the actual target host requested, as well as all parent groups\n"
+"containing that target host.");
+PyDoc_STRVAR(HbacRequest_srchost__doc__,
+"(HbacRequestElement) This is a list of source hosts to check, it must\n"
+"consist of the actual source host requested, as well as all parent groups\n"
+"containing that source host.");
+
+static PyMemberDef py_hbac_request_members[] = {
+ { discard_const_p(char, "service"), T_OBJECT_EX,
+ offsetof(HbacRequest, service), 0,
+ HbacRequest_service__doc__ },
+
+ { discard_const_p(char, "user"), T_OBJECT_EX,
+ offsetof(HbacRequest, user), 0,
+ HbacRequest_user__doc__ },
+
+ { discard_const_p(char, "targethost"), T_OBJECT_EX,
+ offsetof(HbacRequest, targethost), 0,
+ HbacRequest_targethost__doc__ },
+
+ { discard_const_p(char, "srchost"), T_OBJECT_EX,
+ offsetof(HbacRequest, srchost), 0,
+ HbacRequest_srchost__doc__ },
+
+ { NULL, 0, 0, 0, NULL } /* Sentinel */
+};
+
+PyDoc_STRVAR(HbacRequest_rule_name__doc__,
+"(string) If result of evaluation was to allow access, this member contains\n"
+"the name of the rule that allowed it. Otherwise, this attribute contains \n"
+"None. This attribute is read-only.\n");
+
+static PyGetSetDef py_hbac_request_getset[] = {
+ { discard_const_p(char, "rule_name"),
+ (getter) hbac_request_element_get_rule_name,
+ NULL, /* read only */
+ HbacRequest_rule_name__doc__,
+ NULL },
+
+ { NULL, 0, 0, 0, NULL } /* Sentinel */
+};
+
+PyDoc_STRVAR(HbacRequest__doc__,
+"IPA HBAC Request\n\n"
+"HbacRequest() -> new empty HBAC request");
+
+static PyTypeObject pyhbac_hbacrequest_type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = sss_py_const_p(char, "pyhbac.HbacRequest"),
+ .tp_basicsize = sizeof(HbacRequest),
+ .tp_new = HbacRequest_new,
+ .tp_dealloc = (destructor) HbacRequest_dealloc,
+ .tp_traverse = (traverseproc) HbacRequest_traverse,
+ .tp_clear = (inquiry) HbacRequest_clear,
+ .tp_init = (initproc) HbacRequest_init,
+ .tp_repr = (reprfunc) HbacRequest_repr,
+ .tp_methods = py_hbac_request_methods,
+ .tp_members = py_hbac_request_members,
+ .tp_getset = py_hbac_request_getset,
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ .tp_doc = HbacRequest__doc__
+};
+
+static void
+free_hbac_eval_req(struct hbac_eval_req *req)
+{
+ if (!req) return;
+
+ free_hbac_request_element(req->service);
+ free_hbac_request_element(req->user);
+ free_hbac_request_element(req->targethost);
+ free_hbac_request_element(req->srchost);
+
+ PyMem_Free(req);
+}
+
+static struct hbac_eval_req *
+HbacRequest_to_native(HbacRequest *pyreq)
+{
+ struct hbac_eval_req *req = NULL;
+
+ req = PyMem_Malloc(sizeof(struct hbac_eval_req));
+ if (!req) {
+ PyErr_NoMemory();
+ goto fail;
+ }
+
+ if (!PyObject_IsInstance((PyObject *) pyreq,
+ (PyObject *) &pyhbac_hbacrequest_type)) {
+ PyErr_Format(PyExc_TypeError,
+ "The request must be of type HbacRequest\n");
+ goto fail;
+ }
+
+ req->service = HbacRequestElement_to_native(pyreq->service);
+ req->user = HbacRequestElement_to_native(pyreq->user);
+ req->targethost = HbacRequestElement_to_native(pyreq->targethost);
+ req->srchost = HbacRequestElement_to_native(pyreq->srchost);
+ if (!req->service || !req->user ||
+ !req->targethost || !req->srchost) {
+ goto fail;
+ }
+ return req;
+
+fail:
+ free_hbac_eval_req(req);
+ return NULL;
+}
+
+/* =================== the pyhbac module initialization =====================*/
+PyDoc_STRVAR(py_hbac_result_string__doc__,
+"hbac_result_string(code) -> string\n"
+"Returns a string representation of the HBAC result code");
+
+static PyObject *
+py_hbac_result_string(PyObject *module, PyObject *args)
+{
+ enum hbac_eval_result result;
+ const char *str;
+
+ if (!PyArg_ParseTuple(args, sss_py_const_p(char, "i"), &result)) {
+ return NULL;
+ }
+
+ str = hbac_result_string(result);
+ if (str == NULL) {
+ /* None needs to be referenced, too */
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ return PyUnicode_FromString(str);
+}
+
+PyDoc_STRVAR(py_hbac_error_string__doc__,
+"hbac_error_string(code) -> string\n"
+"Returns a string representation of the HBAC error code");
+
+static PyObject *
+py_hbac_error_string(PyObject *module, PyObject *args)
+{
+ enum hbac_error_code code;
+ const char *str;
+
+ if (!PyArg_ParseTuple(args, sss_py_const_p(char, "i"), &code)) {
+ return NULL;
+ }
+
+ str = hbac_error_string(code);
+ if (str == NULL) {
+ /* None needs to be referenced, too */
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ return PyUnicode_FromString(str);
+}
+
+static PyMethodDef pyhbac_module_methods[] = {
+ { sss_py_const_p(char, "hbac_result_string"),
+ (PyCFunction) py_hbac_result_string,
+ METH_VARARGS,
+ py_hbac_result_string__doc__,
+ },
+
+ { sss_py_const_p(char, "hbac_error_string"),
+ (PyCFunction) py_hbac_error_string,
+ METH_VARARGS,
+ py_hbac_error_string__doc__,
+ },
+
+ {NULL, NULL, 0, NULL} /* Sentinel */
+};
+
+PyDoc_STRVAR(HbacError__doc__,
+"An HBAC processing exception\n\n"
+"This exception is raised when there is an internal error during the\n"
+"HBAC processing, such as an Out-Of-Memory situation or unparseable\n"
+"rule. HbacError.args argument is a tuple that contains error code and\n"
+"the name of the rule that was being processed. Use hbac_error_string()\n"
+"to get the text representation of the HBAC error");
+
+#ifdef IS_PY3K
+static struct PyModuleDef pyhbacdef = {
+ PyModuleDef_HEAD_INIT,
+ PYTHON_MODULE_NAME,
+ NULL,
+ -1,
+ pyhbac_module_methods,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+PyMODINIT_FUNC
+PyInit_pyhbac(void)
+#else
+PyMODINIT_FUNC
+initpyhbac(void)
+#endif
+{
+ PyObject *m;
+ int ret;
+
+#ifdef IS_PY3K
+ m = PyModule_Create(&pyhbacdef);
+#else
+ m = Py_InitModule(sss_py_const_p(char, PYTHON_MODULE_NAME),
+ pyhbac_module_methods);
+#endif
+ if (m == NULL) {
+ MODINITERROR(NULL);
+ }
+
+ /* The HBAC module exception */
+ PyExc_HbacError = sss_exception_with_doc(
+ "hbac.HbacError", HbacError__doc__,
+ PyExc_EnvironmentError, NULL);
+ Py_INCREF(PyExc_HbacError);
+ ret = PyModule_AddObject(m, sss_py_const_p(char, "HbacError"), PyExc_HbacError);
+ if (ret == -1) {
+ Py_XDECREF(PyExc_HbacError);
+ MODINITERROR(m);
+ }
+
+ /* HBAC rule categories */
+ ret = PyModule_AddIntMacro(m, HBAC_CATEGORY_NULL);
+ if (ret == -1) {
+ MODINITERROR(m);
+ }
+ ret = PyModule_AddIntMacro(m, HBAC_CATEGORY_ALL);
+ if (ret == -1) {
+ MODINITERROR(m);
+ }
+
+ /* HBAC rule elements */
+ ret = PyModule_AddIntMacro(m, HBAC_RULE_ELEMENT_USERS);
+ if (ret == -1) {
+ MODINITERROR(m);
+ }
+ ret = PyModule_AddIntMacro(m, HBAC_RULE_ELEMENT_SERVICES);
+ if (ret == -1) {
+ MODINITERROR(m);
+ }
+ ret = PyModule_AddIntMacro(m, HBAC_RULE_ELEMENT_TARGETHOSTS);
+ if (ret == -1) {
+ MODINITERROR(m);
+ }
+ ret = PyModule_AddIntMacro(m, HBAC_RULE_ELEMENT_SOURCEHOSTS);
+ if (ret == -1) {
+ MODINITERROR(m);
+ }
+
+ /* enum hbac_eval_result */
+ ret = PyModule_AddIntMacro(m, HBAC_EVAL_ALLOW);
+ if (ret == -1) {
+ MODINITERROR(m);
+ }
+ ret = PyModule_AddIntMacro(m, HBAC_EVAL_DENY);
+ if (ret == -1) {
+ MODINITERROR(m);
+ }
+ ret = PyModule_AddIntMacro(m, HBAC_EVAL_ERROR);
+ if (ret == -1) {
+ MODINITERROR(m);
+ }
+
+ /* enum hbac_error_code */
+ ret = PyModule_AddIntMacro(m, HBAC_ERROR_UNKNOWN);
+ if (ret == -1) {
+ MODINITERROR(m);
+ }
+ ret = PyModule_AddIntMacro(m, HBAC_SUCCESS);
+ if (ret == -1) {
+ MODINITERROR(m);
+ }
+ ret = PyModule_AddIntMacro(m, HBAC_ERROR_NOT_IMPLEMENTED);
+ if (ret == -1) {
+ MODINITERROR(m);
+ }
+ ret = PyModule_AddIntMacro(m, HBAC_ERROR_OUT_OF_MEMORY);
+ if (ret == -1) {
+ MODINITERROR(m);
+ }
+ ret = PyModule_AddIntMacro(m, HBAC_ERROR_UNPARSEABLE_RULE);
+ if (ret == -1) {
+ MODINITERROR(m);
+ }
+
+ TYPE_READY(m, pyhbac_hbacrule_type, "HbacRule");
+ TYPE_READY(m, pyhbac_hbacrule_element_type, "HbacRuleElement");
+ TYPE_READY(m, pyhbac_hbacrequest_element_type, "HbacRequestElement");
+ TYPE_READY(m, pyhbac_hbacrequest_type, "HbacRequest");
+
+#ifdef IS_PY3K
+ return m;
+#endif
+}
diff --git a/src/python/pysss.c b/src/python/pysss.c
new file mode 100644
index 0000000..f08497a
--- /dev/null
+++ b/src/python/pysss.c
@@ -0,0 +1,358 @@
+/*
+ Authors:
+ Jakub Hrozek <jhrozek@redhat.com>
+
+ Copyright (C) 2009 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "config.h"
+
+#define PY_SSIZE_T_CLEAN 1
+#include <Python.h>
+#include <structmember.h>
+#include <talloc.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include "util/util.h"
+#include "util/sss_python.h"
+#include "db/sysdb.h"
+#include "util/crypto/sss_crypto.h"
+
+
+static void PyErr_SetSssErrorWithMessage(int ret, const char *message)
+{
+ PyObject *exc = Py_BuildValue(discard_const_p(char, "(is)"),
+ ret, message);
+
+ PyErr_SetObject(PyExc_IOError, exc);
+ Py_XDECREF(exc);
+}
+
+static void PyErr_SetSssError(int ret)
+{
+ PyErr_SetSssErrorWithMessage(ret, strerror(ret));
+}
+
+/* ==================== obfuscation python wrappers ========================*/
+
+/*
+ * The sss.password object
+ */
+typedef struct {
+ PyObject_HEAD
+
+ int aes_256;
+} PySssPasswordObject;
+
+PyDoc_STRVAR(py_sss_encrypt__doc__,
+"Obfuscate a password\n\n"
+":param password: The password to obfuscate\n\n"
+":param method: The obfuscation method\n\n");
+
+static PyObject *py_sss_encrypt(PySssPasswordObject *self,
+ PyObject *args)
+{
+ char *password = NULL;
+ Py_ssize_t plen; /* may contain NULL bytes */
+ char *obfpwd = NULL;
+ TALLOC_CTX *tctx = NULL;
+ int ret;
+ int mode;
+ PyObject *retval = NULL;
+
+ /* parse arguments */
+ if (!PyArg_ParseTuple(args, discard_const_p(char, "s#i"),
+ &password, &plen, &mode)) {
+ return NULL;
+ }
+
+ tctx = talloc_new(NULL);
+ if (!tctx) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ ret = sss_password_encrypt(tctx, password, (int)(plen + 1),
+ mode, &obfpwd);
+ if (ret != EOK) {
+ PyErr_SetSssError(ret);
+ goto fail;
+ }
+
+ retval = Py_BuildValue(sss_py_const_p(char, "s"), obfpwd);
+ if (retval == NULL) {
+ goto fail;
+ }
+
+fail:
+ talloc_zfree(tctx);
+ return retval;
+}
+
+#if 0
+PyDoc_STRVAR(py_sss_decrypt__doc__,
+"Deobfuscate a password\n\n"
+":param obfpwd: The password to convert back to clear text\n\n");
+
+static PyObject *py_sss_decrypt(PySssPasswordObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ char *password = NULL;
+ char *obfpwd = NULL;
+ TALLOC_CTX *tctx = NULL;
+ int ret;
+ PyObject *retval = NULL;
+
+ /* parse arguments */
+ if (!PyArg_ParseTuple(args, discard_const_p(char, "s"),
+ &obfpwd)) {
+ return NULL;
+ }
+
+ tctx = talloc_new(NULL);
+ if (!tctx) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ ret = sss_password_decrypt(tctx, obfpwd, &password);
+ if (ret != EOK) {
+ PyErr_SetSssError(ret);
+ goto fail;
+ }
+
+ retval = Py_BuildValue("s", password);
+ if (retval == NULL) {
+ goto fail;
+ }
+
+fail:
+ talloc_zfree(tctx);
+ return retval;
+}
+#endif
+
+/*
+ * The sss.password destructor
+ */
+static void PySssPasswordObject_dealloc(PySssPasswordObject *self)
+{
+ Py_TYPE(self)->tp_free((PyObject*) self);
+}
+
+/*
+ * The sss.password constructor
+ */
+static PyObject *PySssPasswordObject_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds)
+{
+ PySssPasswordObject *self;
+
+ self = (PySssPasswordObject *) type->tp_alloc(type, 0);
+ if (self == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ self->aes_256 = AES_256;
+
+ return (PyObject *) self;
+}
+
+/*
+ * sss.password object methods
+ */
+static PyMethodDef sss_password_methods[] = {
+ { sss_py_const_p(char, "encrypt"), (PyCFunction) py_sss_encrypt,
+ METH_VARARGS | METH_STATIC, py_sss_encrypt__doc__
+ },
+#if 0
+ { "decrypt", (PyCFunction) py_sss_decrypt,
+ METH_VARARGS | METH_STATIC, py_sss_decrypt__doc__
+ },
+#endif
+ {NULL, NULL, 0, NULL} /* Sentinel */
+};
+
+/*
+ * sss.password object members
+ */
+static PyMemberDef sss_password_members[] = {
+ { discard_const_p(char, "AES_256"), T_INT,
+ offsetof(PySssPasswordObject, aes_256), READONLY, NULL},
+ {NULL, 0, 0, 0, NULL} /* Sentinel */
+};
+
+/*
+ * sss.password object properties
+ */
+static PyTypeObject pysss_password_type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = sss_py_const_p(char, "sss.password"),
+ .tp_basicsize = sizeof(PySssPasswordObject),
+ .tp_new = PySssPasswordObject_new,
+ .tp_dealloc = (destructor) PySssPasswordObject_dealloc,
+ .tp_methods = sss_password_methods,
+ .tp_members = sss_password_members,
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ .tp_doc = sss_py_const_p(char, "SSS password obfuscation"),
+};
+
+/*
+ * Get list of groups user belongs to
+ */
+PyDoc_STRVAR(py_sss_getgrouplist__doc__,
+ "Get list of groups user belongs to.\n\n"
+ "NOTE: The interface uses the system NSS calls and is not limited to "
+ "users served by the SSSD!\n"
+ ":param username: name of user to get list for\n");
+
+static PyObject *py_sss_getgrouplist(PyObject *self, PyObject *args)
+{
+ char *username = NULL;
+ gid_t *groups = NULL;
+ struct passwd *pw;
+ struct group *gr;
+ int ngroups;
+ int ret;
+ Py_ssize_t i, idx;
+ PyObject *groups_tuple;
+
+ if(!PyArg_ParseTuple(args, discard_const_p(char, "s"), &username)) {
+ goto fail;
+ }
+
+ pw = getpwnam(username);
+ if (pw == NULL) {
+ goto fail;
+ }
+
+ ngroups = 32;
+ groups = malloc(sizeof(gid_t) * ngroups);
+ if (groups == NULL) {
+ goto fail;
+ }
+
+ do {
+ ret = getgrouplist(username, pw->pw_gid, groups, &ngroups);
+ if (ret < ngroups) {
+ gid_t *tmp_groups = realloc(groups, ngroups * sizeof(gid_t));
+ if (tmp_groups == NULL) {
+ goto fail;
+ }
+ groups = tmp_groups;
+ }
+ } while (ret != ngroups);
+
+ groups_tuple = PyTuple_New((Py_ssize_t) ngroups);
+ if (groups_tuple == NULL) {
+ goto fail;
+ }
+
+ /* Populate a tuple with names of groups
+ * In unlikely case of group not being able to resolve, skip it
+ * We also need to resize resulting tuple to avoid empty elements there */
+ idx = 0;
+ for (i = 0; i < ngroups; i++) {
+ gr = getgrgid(groups[i]);
+ if (gr) {
+ PyTuple_SetItem(groups_tuple, idx,
+#ifdef IS_PY3K
+ PyUnicode_FromString(gr->gr_name)
+#else
+ PyString_FromString(gr->gr_name)
+#endif
+ );
+ idx++;
+ }
+ }
+ free(groups);
+ groups = NULL;
+
+ if (i != idx) {
+ _PyTuple_Resize(&groups_tuple, idx);
+ }
+
+ return groups_tuple;
+
+fail:
+ free(groups);
+ return NULL;
+}
+
+/* ==================== the sss module initialization =======================*/
+
+/*
+ * Module methods
+ */
+static PyMethodDef module_methods[] = {
+ {"getgrouplist", py_sss_getgrouplist, METH_VARARGS, py_sss_getgrouplist__doc__},
+ {NULL, NULL, 0, NULL} /* Sentinel */
+};
+
+/*
+ * Module initialization
+ */
+#ifdef IS_PY3K
+static struct PyModuleDef pysssdef = {
+ PyModuleDef_HEAD_INIT,
+ "pysss",
+ NULL,
+ -1,
+ module_methods,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+PyMODINIT_FUNC
+PyInit_pysss(void)
+#else
+PyMODINIT_FUNC
+initpysss(void)
+#endif
+{
+ PyObject *m;
+
+ if (PyType_Ready(&pysss_password_type) < 0) {
+ MODINITERROR(NULL);
+ }
+
+#ifdef IS_PY3K
+ m = PyModule_Create(&pysssdef);
+#else
+ m = Py_InitModule(discard_const_p(char, "pysss"), module_methods);
+#endif
+ if (m == NULL){
+ MODINITERROR(NULL);
+ }
+
+ Py_INCREF(&pysss_password_type);
+ if (PyModule_AddObject(m, discard_const_p(char, "password"),
+ (PyObject *)&pysss_password_type) == -1) {
+ Py_XDECREF(&pysss_password_type);
+ MODINITERROR(m);
+ }
+
+#ifdef IS_PY3K
+ return m;
+#endif
+}
+
diff --git a/src/python/pysss_murmur.c b/src/python/pysss_murmur.c
new file mode 100644
index 0000000..f20e5cf
--- /dev/null
+++ b/src/python/pysss_murmur.c
@@ -0,0 +1,100 @@
+/*
+ Authors:
+ Sumit Bose <sbose@redhat.com>
+
+ Copyright (C) 2012 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "config.h"
+
+#define PY_SSIZE_T_CLEAN 1
+#include <Python.h>
+
+#include "util/sss_python.h"
+#include "shared/murmurhash3.h"
+
+PyDoc_STRVAR(murmurhash3_doc,
+"murmurhash3(key, key_len, seed) -> 32bit integer hash\n\
+\n\
+Calculate the murmur hash version 3 of the first key_len bytes from key\n\
+using the given seed."
+);
+
+static PyObject * py_murmurhash3(PyObject *module, PyObject *args)
+{
+ const char *key;
+ long key_len;
+ long long seed;
+ uint32_t hash;
+ Py_ssize_t input_len;
+
+ if (!PyArg_ParseTuple(args, sss_py_const_p(char, "z#lL"),
+ &key, &input_len, &key_len, &seed)) {
+ PyErr_Format(PyExc_ValueError, "Invalid argument\n");
+ return NULL;
+ }
+
+ if (seed > UINT32_MAX || key_len > INT_MAX || key_len < 0 ||
+ key_len > input_len) {
+ PyErr_Format(PyExc_ValueError, "Invalid value\n");
+ return NULL;
+ }
+
+ hash = murmurhash3(key, key_len, seed);
+
+ return PyLong_FromUnsignedLong((unsigned long) hash);
+}
+
+static PyMethodDef methods[] = {
+ { sss_py_const_p(char, "murmurhash3"), (PyCFunction) py_murmurhash3,
+ METH_VARARGS, murmurhash3_doc },
+ { NULL,NULL, 0, NULL }
+};
+
+#ifdef IS_PY3K
+static struct PyModuleDef pysss_murmurdef = {
+ PyModuleDef_HEAD_INIT,
+ "pysss_murmur",
+ NULL,
+ -1,
+ methods,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+PyMODINIT_FUNC
+PyInit_pysss_murmur(void)
+#else
+PyMODINIT_FUNC
+initpysss_murmur(void)
+#endif
+{
+ PyObject *m;
+#ifdef IS_PY3K
+ m = PyModule_Create(&pysss_murmurdef);
+#else
+ m = Py_InitModule3(sss_py_const_p(char, "pysss_murmur"),
+ methods, sss_py_const_p(char, "murmur hash functions"));
+#endif
+ if (m == NULL) {
+ MODINITERROR(NULL);
+ }
+#ifdef IS_PY3K
+ return m;
+#endif
+}
diff --git a/src/python/pysss_nss_idmap.c b/src/python/pysss_nss_idmap.c
new file mode 100644
index 0000000..aa9db3b
--- /dev/null
+++ b/src/python/pysss_nss_idmap.c
@@ -0,0 +1,676 @@
+/*
+ Authors:
+ Sumit Bose <sbose@redhat.com>
+ Alexander Bokovoy <abokovoy@redhat.com>
+
+ Copyright (C) 2013 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "config.h"
+
+#include <Python.h>
+
+#include "util/sss_python.h"
+#include "sss_client/idmap/sss_nss_idmap.h"
+
+#define SSS_NAME_KEY "name"
+#define SSS_SID_KEY "sid"
+#define SSS_ID_KEY "id"
+#define SSS_TYPE_KEY "type"
+
+enum lookup_type {
+ SIDBYNAME,
+ SIDBYUSERNAME,
+ SIDBYGROUPNAME,
+ SIDBYID,
+ SIDBYUID,
+ SIDBYGID,
+ NAMEBYSID,
+ IDBYSID,
+ NAMEBYCERT,
+ LISTBYCERT
+};
+
+static int add_dict_to_list(PyObject *py_list, PyObject *res_type,
+ PyObject *res, PyObject *id_type)
+{
+ int ret;
+ PyObject *py_dict;
+
+ py_dict = PyDict_New();
+ if (py_dict == NULL) {
+ return ENOMEM;
+ }
+
+ ret = PyDict_SetItem(py_dict, res_type, res);
+ if (ret != 0) {
+ Py_XDECREF(py_dict);
+ return ret;
+ }
+
+ ret = PyDict_SetItem(py_dict, PyUnicode_FromString(SSS_TYPE_KEY), id_type);
+ if (ret != 0) {
+ Py_XDECREF(py_dict);
+ return ret;
+ }
+
+ ret = PyList_Append(py_list, py_dict);
+
+ return ret;
+}
+static int add_dict(PyObject *py_result, PyObject *key, PyObject *res_type,
+ PyObject *res, PyObject *id_type)
+{
+ int ret;
+ PyObject *py_dict;
+
+ py_dict = PyDict_New();
+ if (py_dict == NULL) {
+ return ENOMEM;
+ }
+
+ ret = PyDict_SetItem(py_dict, res_type, res);
+ if (ret != 0) {
+ Py_XDECREF(py_dict);
+ return ret;
+ }
+
+ ret = PyDict_SetItem(py_dict, PyUnicode_FromString(SSS_TYPE_KEY), id_type);
+ if (ret != 0) {
+ Py_XDECREF(py_dict);
+ return ret;
+ }
+
+ ret = PyDict_SetItem(py_result, key, py_dict);
+
+ return ret;
+}
+
+static char *py_string_or_unicode_as_string(PyObject *inp)
+{
+ PyObject *py_str = NULL;
+
+ if (PyUnicode_Check(inp)) {
+ py_str = PyUnicode_AsUTF8String(inp);
+ } else if (PyBytes_Check(inp)) {
+ py_str = inp;
+ } else {
+ PyErr_Format(PyExc_TypeError, "input must be unicode or a string");
+ return NULL;
+ }
+
+ return PyBytes_AS_STRING(py_str);
+}
+
+static int do_getsidbyname(enum lookup_type type,
+ PyObject *py_result,
+ PyObject *py_name)
+{
+ int ret;
+ const char *name;
+ char *sid = NULL;
+ enum sss_id_type id_type;
+
+ name = py_string_or_unicode_as_string(py_name);
+ if (name == NULL) {
+ return EINVAL;
+ }
+
+ switch (type) {
+ case SIDBYNAME:
+ ret = sss_nss_getsidbyname(name, &sid, &id_type);
+ break;
+ case SIDBYUSERNAME:
+ ret = sss_nss_getsidbyusername(name, &sid, &id_type);
+ break;
+ case SIDBYGROUPNAME:
+ ret = sss_nss_getsidbygroupname(name, &sid, &id_type);
+ break;
+ default:
+ return EINVAL;
+ }
+ if (ret == 0) {
+ ret = add_dict(py_result, py_name, PyUnicode_FromString(SSS_SID_KEY),
+ PyUnicode_FromString(sid), PYNUMBER_FROMLONG(id_type));
+ }
+ free(sid);
+
+ return ret;
+}
+
+static int do_getnamebysid(PyObject *py_result, PyObject *py_sid)
+{
+ int ret;
+ const char *sid;
+ char *name = NULL;
+ enum sss_id_type id_type;
+
+ sid = py_string_or_unicode_as_string(py_sid);
+ if (sid == NULL) {
+ return EINVAL;
+ }
+
+ ret = sss_nss_getnamebysid(sid, &name, &id_type);
+ if (ret == 0) {
+ ret = add_dict(py_result, py_sid, PyUnicode_FromString(SSS_NAME_KEY),
+ PyUnicode_FromString(name), PYNUMBER_FROMLONG(id_type));
+ }
+ free(name);
+
+ return ret;
+}
+
+static int do_getsidbyid(enum lookup_type type, PyObject *py_result,
+ PyObject *py_id)
+{
+ long id;
+ const char *id_str;
+ char *endptr;
+ char *sid = NULL;
+ int ret;
+ enum sss_id_type id_type;
+
+#ifndef IS_PY3K
+ if (PyInt_Check(py_id)) {
+ id = PyInt_AS_LONG(py_id);
+ } else
+#endif
+ if (PyLong_Check(py_id)) {
+ id = PyLong_AsLong(py_id);
+ } else {
+ id_str = py_string_or_unicode_as_string(py_id);
+ if (id_str == NULL) {
+ return EINVAL;
+ }
+ errno = 0;
+ id = strtol(id_str, &endptr, 10);
+ if (errno != 0 || *endptr != '\0') {
+ return EINVAL;
+ }
+ }
+
+ if (id < 0 || id > UINT32_MAX) {
+ return EINVAL;
+ }
+
+ switch (type) {
+ case SIDBYID:
+ ret = sss_nss_getsidbyid((uint32_t) id, &sid, &id_type);
+ break;
+ case SIDBYUID:
+ ret = sss_nss_getsidbyuid((uint32_t) id, &sid, &id_type);
+ break;
+ case SIDBYGID:
+ ret = sss_nss_getsidbygid((uint32_t) id, &sid, &id_type);
+ break;
+ default:
+ return EINVAL;
+ }
+ if (ret == 0) {
+ ret = add_dict(py_result, py_id, PyUnicode_FromString(SSS_SID_KEY),
+ PyUnicode_FromString(sid), PYNUMBER_FROMLONG(id_type));
+ }
+ free(sid);
+
+ return ret;
+}
+
+static int do_getnamebycert(PyObject *py_result, PyObject *py_cert)
+{
+ int ret;
+ const char *cert;
+ char *name = NULL;
+ enum sss_id_type id_type;
+
+ cert = py_string_or_unicode_as_string(py_cert);
+ if (cert == NULL) {
+ return EINVAL;
+ }
+
+ ret = sss_nss_getnamebycert(cert, &name, &id_type);
+ if (ret == 0) {
+ ret = add_dict(py_result, py_cert, PyUnicode_FromString(SSS_NAME_KEY),
+ PyUnicode_FromString(name), PYNUMBER_FROMLONG(id_type));
+ }
+ free(name);
+
+ return ret;
+}
+
+static int do_getlistbycert(PyObject *py_result, PyObject *py_cert)
+{
+ int ret;
+ const char *cert;
+ char **names = NULL;
+ enum sss_id_type *id_types = NULL;
+ size_t c;
+
+ cert = py_string_or_unicode_as_string(py_cert);
+ if (cert == NULL) {
+ return EINVAL;
+ }
+
+ ret = sss_nss_getlistbycert(cert, &names, &id_types);
+ if (ret == 0) {
+
+ PyObject *py_list;
+
+ py_list = PyList_New(0);
+ if (py_list == NULL) {
+ return ENOMEM;
+ }
+
+ for (c = 0; names[c] != NULL; c++) {
+ ret = add_dict_to_list(py_list,
+ PyUnicode_FromString(SSS_NAME_KEY),
+ PyUnicode_FromString(names[c]),
+ PYNUMBER_FROMLONG(id_types[c]));
+ if (ret != 0) {
+ goto done;
+ }
+ }
+ ret = PyDict_SetItem(py_result, py_cert, py_list);
+ if (ret != 0) {
+ goto done;
+ }
+ }
+
+done:
+ free(id_types);
+ if (names != NULL) {
+ for (c = 0; names[c] != NULL; c++) {
+ free(names[c]);
+ }
+ free(names);
+ }
+
+ return ret;
+}
+
+
+static int do_getidbysid(PyObject *py_result, PyObject *py_sid)
+{
+ const char *sid;
+ uint32_t id;
+ enum sss_id_type id_type;
+ int ret;
+
+ sid = py_string_or_unicode_as_string(py_sid);
+ if (sid == NULL) {
+ return EINVAL;
+ }
+
+ ret = sss_nss_getidbysid(sid, &id, &id_type);
+ if (ret == 0) {
+ ret = add_dict(py_result, py_sid, PyUnicode_FromString(SSS_ID_KEY),
+ PYNUMBER_FROMLONG(id), PYNUMBER_FROMLONG(id_type));
+ }
+
+ return ret;
+}
+
+static int do_lookup(enum lookup_type type, PyObject *py_result,
+ PyObject *py_inp)
+{
+ switch(type) {
+ case SIDBYNAME:
+ case SIDBYUSERNAME:
+ case SIDBYGROUPNAME:
+ return do_getsidbyname(type, py_result, py_inp);
+ break;
+ case NAMEBYSID:
+ return do_getnamebysid(py_result, py_inp);
+ break;
+ case SIDBYID:
+ case SIDBYUID:
+ case SIDBYGID:
+ return do_getsidbyid(type, py_result, py_inp);
+ break;
+ case IDBYSID:
+ return do_getidbysid(py_result, py_inp);
+ break;
+ case NAMEBYCERT:
+ return do_getnamebycert(py_result, py_inp);
+ break;
+ case LISTBYCERT:
+ return do_getlistbycert(py_result, py_inp);
+ break;
+ default:
+ return ENOSYS;
+ }
+
+ return ENOSYS;
+}
+
+static PyObject *check_args(enum lookup_type type, PyObject *args)
+{
+ PyObject *obj, *py_value;
+ int ret;
+ Py_ssize_t len, i;
+ PyObject *py_result;
+
+ if (!PyArg_ParseTuple(args, sss_py_const_p(char, "O"), &obj)) {
+ PyErr_Format(PyExc_ValueError, "Unable to retrieve argument\n");
+ return NULL;
+ }
+
+ if (!(PyList_Check(obj) || PyTuple_Check(obj) ||
+ PyBytes_Check(obj) || PyUnicode_Check(obj) ||
+ ((type == SIDBYID
+ || type == SIDBYUID
+ || type == SIDBYGID) && (PYNUMBER_CHECK(obj))))) {
+ PyErr_Format(PyExc_ValueError,
+ "Only string, long or list or tuples of them " \
+ "are accepted\n");
+ return NULL;
+ }
+
+ py_result = PyDict_New();
+ Py_XINCREF(py_result);
+ if (py_result == NULL) {
+ PyErr_Format(PyExc_MemoryError,
+ "Unable to allocate resulting dictionary\n");
+ return NULL;
+ }
+
+ if (PyList_Check(obj) || PyTuple_Check(obj)) {
+ len = PySequence_Size(obj);
+ for(i=0; i < len; i++) {
+ py_value = PySequence_GetItem(obj, i);
+ if ((py_value != NULL) &&
+ (PyBytes_Check(py_value) || PyUnicode_Check(py_value) ||
+ ((type == SIDBYID
+ || type == SIDBYUID
+ || type == SIDBYGID) && PYNUMBER_CHECK(py_value)))) {
+ ret = do_lookup(type, py_result, py_value);
+ if (ret != 0) {
+ /* Skip this name */
+ continue;
+ }
+ }
+ }
+ } else {
+ ret = do_lookup(type, py_result, obj);
+ switch (ret) {
+ case 0:
+ case ENOENT: /* nothing found, return empty dict */
+ break;
+ case EINVAL:
+ PyErr_Format(PyExc_ValueError, "Unable to retrieve result\n");
+ Py_XDECREF(py_result);
+ return NULL;
+ break;
+ default:
+ PyErr_Format(PyExc_IOError, "Operation not supported\n");
+ Py_XDECREF(py_result);
+ return NULL;
+ }
+ }
+
+ Py_XDECREF(py_result);
+ return py_result;
+
+}
+
+PyDoc_STRVAR(getsidbyname_doc,
+"getsidbyname(name or list/tuple of names) -> dict(name => dict(results))\n\
+\n\
+Returns a dictionary with a dictionary of results for each given name.\n\
+The result dictionary contain the SID and the type of the object which can be\n\
+accessed with the key constants SID_KEY and TYPE_KEY, respectively.\n\
+\n\
+The return type can be one of the following constants:\n\
+- ID_NOT_SPECIFIED\n\
+- ID_USER\n\
+- ID_GROUP\n\
+- ID_BOTH"
+);
+
+static PyObject * py_getsidbyname(PyObject *module, PyObject *args)
+{
+ return check_args(SIDBYNAME, args);
+}
+
+PyDoc_STRVAR(getsidbyusername_doc,
+"getsidbyusername(name or list/tuple of names) -> dict(name => dict(results))\n\
+\n\
+Returns a dictionary with a dictionary of results for each given name.\n\
+The result dictionary contain the SID and the type of the object which can be\n\
+accessed with the key constants SID_KEY and TYPE_KEY, respectively.\n\
+\n\
+The return type can be one of the following constants:\n\
+- ID_NOT_SPECIFIED\n\
+- ID_USER\n\
+- ID_GROUP\n\
+- ID_BOTH"
+);
+
+static PyObject * py_getsidbyusername(PyObject *module, PyObject *args)
+{
+ return check_args(SIDBYUSERNAME, args);
+}
+
+PyDoc_STRVAR(getsidbygroupname_doc,
+"getsidbygroupname(name or list/tuple of names) -> dict(name => dict(results))\n\
+\n\
+Returns a dictionary with a dictionary of results for each given name.\n\
+The result dictionary contain the SID and the type of the object which can be\n\
+accessed with the key constants SID_KEY and TYPE_KEY, respectively.\n\
+\n\
+The return type can be one of the following constants:\n\
+- ID_NOT_SPECIFIED\n\
+- ID_USER\n\
+- ID_GROUP\n\
+- ID_BOTH"
+);
+
+static PyObject * py_getsidbygroupname(PyObject *module, PyObject *args)
+{
+ return check_args(SIDBYGROUPNAME, args);
+}
+
+PyDoc_STRVAR(getsidbyid_doc,
+"getsidbyid(id or list/tuple of id) -> dict(id => dict(results))\n\
+\n\
+Returns a dictionary with a dictionary of results for each given POSIX ID.\n\
+The result dictionary contain the SID and the type of the object which can be\n\
+accessed with the key constants SID_KEY and TYPE_KEY, respectively."
+);
+
+static PyObject * py_getsidbyid(PyObject *module, PyObject *args)
+{
+ return check_args(SIDBYID, args);
+}
+
+PyDoc_STRVAR(getsidbyuid_doc,
+"getsidbyuid(uid or list/tuple of uid) -> dict(uid => dict(results))\n\
+\n\
+Returns a dictionary with a dictionary of results for each given POSIX UID.\n\
+The result dictionary contain the SID and the type of the object which can be\n\
+accessed with the key constants SID_KEY and TYPE_KEY, respectively. Since \n\
+given ID is assumed to be a user ID is not expected that group objects are\n\
+returned."
+);
+
+static PyObject * py_getsidbyuid(PyObject *module, PyObject *args)
+{
+ return check_args(SIDBYUID, args);
+}
+
+PyDoc_STRVAR(getsidbygid_doc,
+"getsidbygid(gid or list/tuple of gid) -> dict(gid => dict(results))\n\
+\n\
+Returns a dictionary with a dictionary of results for each given POSIX GID.\n\
+The result dictionary contain the SID and the type of the object which can be\n\
+accessed with the key constants SID_KEY and TYPE_KEY, respectively. Since \n\
+given ID is assumed to be a group ID is is not expected that user objects are\n\
+returned."
+);
+
+static PyObject * py_getsidbygid(PyObject *module, PyObject *args)
+{
+ return check_args(SIDBYGID, args);
+}
+
+PyDoc_STRVAR(getnamebysid_doc,
+"getnamebysid(sid or list/tuple of sid) -> dict(sid => dict(results))\n\
+\n\
+Returns a dictionary with a dictionary of results for each given SID.\n\
+The result dictionary contain the name and the type of the object which can be\n\
+accessed with the key constants NAME_KEY and TYPE_KEY, respectively.\n\
+\n\
+NOTE: getnamebysid currently works only with id_provider set as \"ad\" or \"ipa\""
+);
+
+static PyObject * py_getnamebysid(PyObject *module, PyObject *args)
+{
+ return check_args(NAMEBYSID, args);
+}
+
+PyDoc_STRVAR(getidbysid_doc,
+"getidbysid(sid) -> POSIX ID\n\
+\n\
+Returns the POSIX ID of the object with the given SID."
+"getidbysid(sid or list/tuple of sid) -> dict(sid => dict(results))\n\
+\n\
+Returns a dictionary with a dictionary of results for each given SID.\n\
+The result dictionary contain the POSIX ID and the type of the object which\n\
+can be accessed with the key constants ID_KEY and TYPE_KEY, respectively."
+);
+
+static PyObject * py_getidbysid(PyObject *module, PyObject *args)
+{
+ return check_args(IDBYSID, args);
+}
+
+PyDoc_STRVAR(getnamebycert_doc,
+"getnamebycert(certificate or list/tuple of certificates) -> dict(certificate => dict(results))\n\
+\n\
+Returns a dictionary with a dictionary of results for each given certificates.\n\
+The result dictionary contain the name and the type of the object which can be\n\
+accessed with the key constants NAME_KEY and TYPE_KEY, respectively.\n\
+\n\
+NOTE: getnamebycert currently works only with id_provider set as \"ad\" or \"ipa\""
+);
+
+static PyObject * py_getnamebycert(PyObject *module, PyObject *args)
+{
+ return check_args(NAMEBYCERT, args);
+}
+
+PyDoc_STRVAR(getlistbycert_doc,
+"getnamebycert(certificate or list/tuple of certificates) -> dict(certificate => dict(results))\n\
+\n\
+Returns a dictionary with a dictionary of results for each given certificates.\n\
+The result dictionary contain the name and the type of the object which can be\n\
+accessed with the key constants NAME_KEY and TYPE_KEY, respectively.\n\
+\n\
+NOTE: getlistbycert currently works only with id_provider set as \"ad\" or \"ipa\""
+);
+
+static PyObject * py_getlistbycert(PyObject *module, PyObject *args)
+{
+ return check_args(LISTBYCERT, args);
+}
+
+static PyMethodDef methods[] = {
+ { sss_py_const_p(char, "getsidbyname"), (PyCFunction) py_getsidbyname,
+ METH_VARARGS, getsidbyname_doc },
+ { sss_py_const_p(char, "getsidbyusername"), (PyCFunction) py_getsidbyusername,
+ METH_VARARGS, getsidbyusername_doc },
+ { sss_py_const_p(char, "getsidbygroupname"), (PyCFunction) py_getsidbygroupname,
+ METH_VARARGS, getsidbygroupname_doc },
+ { sss_py_const_p(char, "getsidbyid"), (PyCFunction) py_getsidbyid,
+ METH_VARARGS, getsidbyid_doc },
+ { sss_py_const_p(char, "getsidbyuid"), (PyCFunction) py_getsidbyuid,
+ METH_VARARGS, getsidbyuid_doc },
+ { sss_py_const_p(char, "getsidbygid"), (PyCFunction) py_getsidbygid,
+ METH_VARARGS, getsidbygid_doc },
+ { sss_py_const_p(char, "getnamebysid"), (PyCFunction) py_getnamebysid,
+ METH_VARARGS, getnamebysid_doc },
+ { sss_py_const_p(char, "getidbysid"), (PyCFunction) py_getidbysid,
+ METH_VARARGS, getidbysid_doc },
+ { sss_py_const_p(char, "getnamebycert"), (PyCFunction) py_getnamebycert,
+ METH_VARARGS, getnamebycert_doc },
+ { sss_py_const_p(char, "getlistbycert"), (PyCFunction) py_getlistbycert,
+ METH_VARARGS, getlistbycert_doc },
+ { NULL,NULL, 0, NULL }
+};
+
+#ifdef IS_PY3K
+static struct PyModuleDef pysss_nss_idmap_def = {
+ PyModuleDef_HEAD_INIT,
+ "pysss_nss_idmap",
+ NULL,
+ -1,
+ methods,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+PyMODINIT_FUNC
+PyInit_pysss_nss_idmap(void)
+#else
+PyMODINIT_FUNC
+initpysss_nss_idmap(void)
+#endif
+{
+ PyObject *module;
+
+#ifdef IS_PY3K
+ module = PyModule_Create(&pysss_nss_idmap_def);
+#else
+ module = Py_InitModule3(sss_py_const_p(char, "pysss_nss_idmap"),
+ methods,
+ sss_py_const_p(char, "SSSD ID-mapping functions"));
+#endif
+ if (module == NULL) {
+ MODINITERROR(NULL);
+ }
+
+ if (PyModule_AddIntConstant(module, "ID_NOT_SPECIFIED",
+ SSS_ID_TYPE_NOT_SPECIFIED) == -1) {
+ MODINITERROR(module);
+ }
+ if (PyModule_AddIntConstant(module, "ID_USER", SSS_ID_TYPE_UID) == -1) {
+ MODINITERROR(module);
+ }
+ if (PyModule_AddIntConstant(module, "ID_GROUP", SSS_ID_TYPE_GID) == -1) {
+ MODINITERROR(module);
+ }
+ if (PyModule_AddIntConstant(module, "ID_BOTH", SSS_ID_TYPE_BOTH) == -1) {
+ MODINITERROR(module);
+ }
+
+ if (PyModule_AddStringConstant(module, "SID_KEY", SSS_SID_KEY) == -1) {
+ MODINITERROR(module);
+ }
+ if (PyModule_AddStringConstant(module, "NAME_KEY", SSS_NAME_KEY) == -1) {
+ MODINITERROR(module);
+ }
+ if (PyModule_AddStringConstant(module, "ID_KEY", SSS_ID_KEY) == -1) {
+ MODINITERROR(module);
+ }
+ if (PyModule_AddStringConstant(module, "TYPE_KEY", SSS_TYPE_KEY) == -1) {
+ MODINITERROR(module);
+ }
+
+#ifdef IS_PY3K
+ return module;
+#endif
+}