summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2013-04-22 17:57:53 +0200
committerJakub Hrozek <jhrozek@redhat.com>2013-05-03 20:06:29 +0200
commitc080a11e9e88f35e40aff4e476cabbd971833019 (patch)
tree21e09bfcf64d754ea5236c089e0dc0655f9f5041
parent2a9af1f71887f02935e2fb6ad5023afba5b6d43e (diff)
downloadsssd2-c080a11e9e88f35e40aff4e476cabbd971833019.tar.gz
sssd2-c080a11e9e88f35e40aff4e476cabbd971833019.tar.xz
sssd2-c080a11e9e88f35e40aff4e476cabbd971833019.zip
Add python interface to libsss_nss_idmap
To allow to use libsss_nss_idmap from python applications, e.g. the FreeIPA server, the patch adds pythin bindings to libsss_nss_idmap. The contributed spec file will place the python bindings in a new package called libsss_nss_idmap-python. Alexander Bokovoy <abokovoy@redhat.com> kindly provided the code to check the type of the python objects and loop over the list entries.
-rw-r--r--Makefile.am15
-rw-r--r--contrib/sssd.spec.in14
-rw-r--r--src/python/pysss_nss_idmap.c351
3 files changed, 379 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index 85c754c8..19248667 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -228,7 +228,8 @@ if BUILD_PYTHON_BINDINGS
pyexec_LTLIBRARIES = \
pysss.la \
pyhbac.la \
- pysss_murmur.la
+ pysss_murmur.la \
+ pysss_nss_idmap.la
endif
dist_noinst_SCRIPTS = \
@@ -1750,6 +1751,18 @@ pysss_murmur_la_LIBADD = \
pysss_murmur_la_LDFLAGS = \
-avoid-version \
-module
+
+pysss_nss_idmap_la_SOURCES = \
+ src/python/pysss_nss_idmap.c
+pysss_nss_idmap_la_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(PYTHON_CFLAGS)
+pysss_nss_idmap_la_LIBADD = \
+ $(PYTHON_LIBS) \
+ libsss_nss_idmap.la
+pysss_nss_idmap_la_LDFLAGS = \
+ -avoid-version \
+ -module
endif
################
diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in
index d799ca21..0ad83a48 100644
--- a/contrib/sssd.spec.in
+++ b/contrib/sssd.spec.in
@@ -249,6 +249,16 @@ Requires: libsss_nss_idmap = %{version}-%{release}
%description -n libsss_nss_idmap-devel
Utility library for SID based lookups
+%package -n libsss_nss_idmap-python
+Summary: Python bindings for libsss_nss_idmap
+Group: Development/Libraries
+License: LGPLv3+
+Requires: libsss_nss_idmap = %{version}-%{release}
+
+%description -n libsss_nss_idmap-python
+The libsss_nss_idmap-python contains the bindings so that libsss_nss_idmap can
+be used by Python applications.
+
%package -n libsss_sudo
Summary: A library to allow communication between SUDO and SSSD
Group: Development/Libraries
@@ -558,6 +568,10 @@ rm -rf $RPM_BUILD_ROOT
%{_libdir}/libsss_nss_idmap.so
%{_libdir}/pkgconfig/sss_nss_idmap.pc
+%files -n libsss_nss_idmap-python
+%defattr(-,root,root,-)
+%{python_sitearch}/pysss_nss_idmap.so
+
%package -n libsss_autofs
Summary: A library to allow communication between Autofs and SSSD
Group: Development/Libraries
diff --git a/src/python/pysss_nss_idmap.c b/src/python/pysss_nss_idmap.c
new file mode 100644
index 00000000..dd1fb4c9
--- /dev/null
+++ b/src/python/pysss_nss_idmap.c
@@ -0,0 +1,351 @@
+/*
+ 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 <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,
+ SIDBYID,
+ NAMEBYSID,
+ IDBYSID
+};
+
+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, PyString_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 int do_getsidbyname(PyObject *py_result, PyObject *py_name)
+{
+ int ret;
+ const char *name;
+ char *sid = NULL;
+ enum sss_id_type id_type;
+
+ name = PyString_AS_STRING(py_name);
+ if (name == NULL) {
+ return EINVAL;
+ }
+
+ ret = sss_nss_getsidbyname(name, &sid, &id_type);
+ if (ret == 0) {
+ ret = add_dict(py_result, py_name, PyString_FromString(SSS_SID_KEY),
+ PyString_FromString(sid), PyInt_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 = PyString_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, PyString_FromString(SSS_NAME_KEY),
+ PyString_FromString(name), PyInt_FromLong(id_type));
+ }
+ free(name);
+
+ return ret;
+}
+
+static int do_getsidbyid(PyObject *py_result, PyObject *py_id)
+{
+ long id;
+ const char *id_str;
+ char *endptr;
+ char *sid;
+ int ret;
+ enum sss_id_type id_type;
+
+ if (PyInt_Check(py_id)) {
+ id = PyInt_AS_LONG(py_id);
+ } else if (PyLong_Check(py_id)) {
+ id = PyLong_AsLong(py_id);
+ } else if (PyString_Check(py_id)) {
+ id_str = PyString_AS_STRING(py_id);
+ errno = 0;
+ id = strtol(id_str, &endptr, 10);
+ if (errno != 0 || *endptr != '\0') {
+ return EINVAL;
+ }
+ } else {
+ return EINVAL;
+ }
+
+ if (id < 0 || id > UINT32_MAX) {
+ return EINVAL;
+ }
+
+ ret = sss_nss_getsidbyid((uint32_t) id, &sid, &id_type);
+ if (ret == 0) {
+ ret = add_dict(py_result, py_id, PyString_FromString(SSS_SID_KEY),
+ PyString_FromString(sid), PyInt_FromLong(id_type));
+ }
+ free(sid);
+
+ 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 = PyString_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, PyString_FromString(SSS_ID_KEY),
+ PyInt_FromLong(id), PyInt_FromLong(id_type));
+ }
+
+ return ret;
+}
+
+static int do_lookup(enum lookup_type type, PyObject *py_result,
+ PyObject *py_inp)
+{
+ switch(type) {
+ case SIDBYNAME:
+ return do_getsidbyname(py_result, py_inp);
+ break;
+ case NAMEBYSID:
+ return do_getnamebysid(py_result, py_inp);
+ break;
+ case SIDBYID:
+ return do_getsidbyid(py_result, py_inp);
+ break;
+ case IDBYSID:
+ return do_getidbysid(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) || PyString_Check(obj) ||
+ (type == SIDBYID && (PyInt_Check(obj) || PyLong_Check(obj))))) {
+ PyErr_Format(PyExc_ValueError,
+ "Only string, long or list 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)) {
+ len = PyList_Size(obj);
+ for(i=0; i < len; i++) {
+ py_value = PyList_GetItem(obj, i);
+ if ((py_value != NULL) &&
+ (PyString_Check(py_value) ||
+ (type == SIDBYID &&
+ (PyInt_Check(py_value) || PyLong_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 argument\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 of names) -> dict(name => dict(results))\n\
+\n\
+Returns a dictionary with a dictonary of results for each given name.\n\
+The result dictonary 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(getsidbyid_doc,
+"getsidbyid(id or list of id) -> dict(id => dict(results))\n\
+\n\
+Returns a dictionary with a dictonary of results for each given POSIX ID.\n\
+The result dictonary 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(getnamebysid_doc,
+"getnamebysid(sid or list of sid) -> dict(sid => dict(results))\n\
+\n\
+Returns a dictionary with a dictonary of results for each given SID.\n\
+The result dictonary contain the name and the type of the object which can be\n\
+accessed with the key constants NAME_KEY and TYPE_KEY, respectively."
+);
+
+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 of sid) -> dict(sid => dict(results))\n\
+\n\
+Returns a dictionary with a dictonary of results for each given SID.\n\
+The result dictonary 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);
+}
+
+static PyMethodDef methods[] = {
+ { sss_py_const_p(char, "getsidbyname"), (PyCFunction) py_getsidbyname,
+ METH_VARARGS, getsidbyname_doc },
+ { sss_py_const_p(char, "getsidbyid"), (PyCFunction) py_getsidbyid,
+ METH_VARARGS, getsidbyid_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 },
+ { NULL,NULL, 0, NULL }
+};
+
+
+PyMODINIT_FUNC
+initpysss_nss_idmap(void)
+{
+ PyObject *module;
+
+ module = Py_InitModule3(sss_py_const_p(char, "pysss_nss_idmap"),
+ methods,
+ sss_py_const_p(char, "SSSD ID-mapping functions"));
+
+ PyModule_AddIntConstant(module, "ID_NOT_SPECIFIED",
+ SSS_ID_TYPE_NOT_SPECIFIED);
+ PyModule_AddIntConstant(module, "ID_USER", SSS_ID_TYPE_UID);
+ PyModule_AddIntConstant(module, "ID_GROUP", SSS_ID_TYPE_GID);
+ PyModule_AddIntConstant(module, "ID_BOTH", SSS_ID_TYPE_BOTH);
+
+ PyModule_AddStringConstant(module, "SID_KEY", SSS_SID_KEY);
+ PyModule_AddStringConstant(module, "NAME_KEY", SSS_NAME_KEY);
+ PyModule_AddStringConstant(module, "ID_KEY", SSS_ID_KEY);
+ PyModule_AddStringConstant(module, "TYPE_KEY", SSS_TYPE_KEY);
+}