LCOV - code coverage report
Current view: top level - lib/ldb-samba - pyldb.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 104 137 75.9 %
Date: 2024-02-28 12:06:22 Functions: 8 9 88.9 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Python interface to ldb, Samba-specific functions
       5             : 
       6             :    Copyright (C) 2007-2010 Jelmer Vernooij <jelmer@samba.org>
       7             : 
       8             :    This library is free software; you can redistribute it and/or
       9             :    modify it under the terms of the GNU Lesser General Public
      10             :    License as published by the Free Software Foundation; either
      11             :    version 3 of the License, or (at your option) any later version.
      12             : 
      13             :    This library is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :    Lesser General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU Lesser General Public
      19             :    License along with this library; if not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "lib/replace/system/python.h"
      23             : #include "python/py3compat.h"
      24             : #include "includes.h"
      25             : #include <ldb.h>
      26             : #include <pyldb.h>
      27             : #include "param/pyparam.h"
      28             : #include "auth/credentials/pycredentials.h"
      29             : #include "ldb_wrap.h"
      30             : #include "lib/ldb-samba/ldif_handlers.h"
      31             : #include "auth/pyauth.h"
      32             : #include "source4/dsdb/common/util.h"
      33             : #include "lib/ldb/include/ldb_private.h"
      34             : 
      35             : 
      36             : static PyObject *pyldb_module;
      37             : static PyObject *py_ldb_error;
      38             : static PyTypeObject PySambaLdb;
      39             : 
      40           0 : static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx)
      41             : {
      42           0 :         if (ret == LDB_ERR_PYTHON_EXCEPTION)
      43           0 :                 return; /* Python exception should already be set, just keep that */
      44             : 
      45           0 :         PyErr_SetObject(error, 
      46             :                         Py_BuildValue(discard_const_p(char, "(i,s)"), ret,
      47           0 :                         ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
      48             : }
      49             : 
      50       34545 : static PyObject *py_ldb_set_loadparm(PyObject *self, PyObject *args)
      51             : {
      52         407 :         PyObject *py_lp_ctx;
      53         407 :         struct loadparm_context *lp_ctx;
      54         407 :         struct ldb_context *ldb;
      55             : 
      56       34545 :         if (!PyArg_ParseTuple(args, "O", &py_lp_ctx))
      57           0 :                 return NULL;
      58             : 
      59       34545 :         ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
      60             : 
      61       34545 :         lp_ctx = lpcfg_from_py_object(ldb, py_lp_ctx);
      62       34545 :         if (lp_ctx == NULL) {
      63           0 :                 PyErr_SetString(PyExc_TypeError, "Expected loadparm object");
      64           0 :                 return NULL;
      65             :         }
      66             : 
      67       34545 :         ldb_set_opaque(ldb, "loadparm", lp_ctx);
      68             : 
      69       34545 :         Py_RETURN_NONE;
      70             : }
      71             : 
      72       31485 : static PyObject *py_ldb_set_credentials(PyObject *self, PyObject *args)
      73             : {
      74         110 :         PyObject *py_creds;
      75         110 :         struct cli_credentials *creds;
      76         110 :         struct ldb_context *ldb;
      77             : 
      78       31485 :         if (!PyArg_ParseTuple(args, "O", &py_creds))
      79           0 :                 return NULL;
      80             : 
      81       31485 :         creds = cli_credentials_from_py_object(py_creds);
      82       31485 :         if (creds == NULL) {
      83           0 :                 PyErr_SetString(PyExc_TypeError, "Expected credentials object");
      84           0 :                 return NULL;
      85             :         }
      86             : 
      87       31485 :         ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
      88             : 
      89       31485 :         ldb_set_opaque(ldb, "credentials", creds);
      90             : 
      91       31485 :         Py_RETURN_NONE;
      92             : }
      93             : 
      94             : /* XXX: This function really should be in libldb's pyldb.c */
      95         527 : static PyObject *py_ldb_set_opaque_integer(PyObject *self, PyObject *args)
      96             : {
      97          66 :         int value;
      98          66 :         int *old_val, *new_val;
      99          66 :         char *py_opaque_name, *opaque_name_talloc;
     100          66 :         struct ldb_context *ldb;
     101          66 :         int ret;
     102          66 :         TALLOC_CTX *tmp_ctx;
     103             : 
     104         527 :         if (!PyArg_ParseTuple(args, "si", &py_opaque_name, &value))
     105           0 :                 return NULL;
     106             : 
     107         527 :         ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
     108             : 
     109             :         /* see if we have a cached copy */
     110         527 :         old_val = (int *)ldb_get_opaque(ldb, py_opaque_name);
     111             :         /* XXX: We shouldn't just blindly assume that the value that is 
     112             :          * already present has the size of an int and is not shared 
     113             :          * with other code that may rely on it not changing. 
     114             :          * JRV 20100403 */
     115             : 
     116         527 :         if (old_val) {
     117          68 :                 *old_val = value;
     118          68 :                 Py_RETURN_NONE;
     119             :         }
     120             : 
     121         459 :         tmp_ctx = talloc_new(ldb);
     122         459 :         if (tmp_ctx == NULL) {
     123           0 :                 PyErr_NoMemory();
     124           0 :                 return NULL;
     125             :         }
     126             : 
     127         459 :         new_val = talloc(tmp_ctx, int);
     128         459 :         if (new_val == NULL) {
     129           0 :                 talloc_free(tmp_ctx);
     130           0 :                 PyErr_NoMemory();
     131           0 :                 return NULL;
     132             :         }
     133             : 
     134         459 :         opaque_name_talloc = talloc_strdup(tmp_ctx, py_opaque_name);
     135         459 :         if (opaque_name_talloc == NULL) {
     136           0 :                 talloc_free(tmp_ctx);
     137           0 :                 PyErr_NoMemory();
     138           0 :                 return NULL;
     139             :         }
     140             : 
     141         459 :         *new_val = value;
     142             : 
     143             :         /* cache the domain_sid in the ldb */
     144         459 :         ret = ldb_set_opaque(ldb, opaque_name_talloc, new_val);
     145             : 
     146         459 :         if (ret != LDB_SUCCESS) {
     147           0 :                 talloc_free(tmp_ctx);
     148           0 :                 PyErr_SetLdbError(py_ldb_error, ret, ldb);
     149           0 :                 return NULL;
     150             :         }
     151             : 
     152         459 :         talloc_steal(ldb, new_val);
     153         459 :         talloc_steal(ldb, opaque_name_talloc);
     154         459 :         talloc_free(tmp_ctx);
     155             : 
     156         459 :         Py_RETURN_NONE;
     157             : }
     158             : 
     159       35026 : static PyObject *py_ldb_set_utf8_casefold(PyObject *self,
     160             :                 PyObject *Py_UNUSED(ignored))
     161             : {
     162         450 :         struct ldb_context *ldb;
     163             : 
     164       35026 :         ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
     165             : 
     166       35026 :         ldb_set_utf8_fns(ldb, NULL, wrap_casefold);
     167             : 
     168       35026 :         Py_RETURN_NONE;
     169             : }
     170             : 
     171       24129 : static PyObject *py_ldb_set_session_info(PyObject *self, PyObject *args)
     172             : {
     173         463 :         PyObject *py_session_info;
     174         463 :         struct auth_session_info *info;
     175         463 :         struct ldb_context *ldb;
     176         463 :         PyObject *mod_samba_auth;
     177         463 :         PyObject *PyAuthSession_Type;
     178         463 :         bool ret;
     179             : 
     180       24129 :         mod_samba_auth = PyImport_ImportModule("samba.dcerpc.auth");
     181       24129 :         if (mod_samba_auth == NULL)
     182           0 :                 return NULL;
     183             : 
     184       24129 :         PyAuthSession_Type = PyObject_GetAttrString(mod_samba_auth, "session_info");
     185       24129 :         if (PyAuthSession_Type == NULL) {
     186           0 :                 Py_CLEAR(mod_samba_auth);
     187           0 :                 return NULL;
     188             :         }
     189             : 
     190       24129 :         ret = PyArg_ParseTuple(args, "O!", PyAuthSession_Type, &py_session_info);
     191             : 
     192       17647 :         Py_DECREF(PyAuthSession_Type);
     193       24129 :         Py_DECREF(mod_samba_auth);
     194             : 
     195       24129 :         if (!ret)
     196           0 :                 return NULL;
     197             : 
     198       24129 :         ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
     199             : 
     200       24129 :         info = PyAuthSession_AsSession(py_session_info);
     201             : 
     202       24129 :         ldb_set_opaque(ldb, DSDB_SESSION_INFO, info);
     203             : 
     204       24129 :         Py_RETURN_NONE;
     205             : }
     206             : 
     207           4 : static PyObject *py_ldb_samba_schema_attribute_add(PyLdbObject *self,
     208             :                                                    PyObject *args)
     209             : {
     210           4 :         char *attribute, *syntax;
     211           4 :         const struct ldb_schema_syntax *s;
     212           4 :         unsigned int flags;
     213           4 :         int ret;
     214           4 :         struct ldb_context *ldb_ctx;
     215             : 
     216           4 :         if (!PyArg_ParseTuple(args, "sIs", &attribute, &flags, &syntax))
     217           0 :                 return NULL;
     218             : 
     219           4 :         ldb_ctx = pyldb_Ldb_AsLdbContext((PyObject *)self);
     220             : 
     221           4 :         s = ldb_samba_syntax_by_name(ldb_ctx, syntax);
     222           4 :         ret = ldb_schema_attribute_add_with_syntax(ldb_ctx, attribute,
     223             :                                                    flags, s);
     224             : 
     225           4 :         PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_error, ret, ldb_ctx);
     226             : 
     227           4 :         Py_RETURN_NONE;
     228             : }
     229             : 
     230       35026 : static PyObject *py_ldb_register_samba_handlers(PyObject *self,
     231             :                 PyObject *Py_UNUSED(ignored))
     232             : {
     233         450 :         struct ldb_context *ldb;
     234         450 :         int ret;
     235             : 
     236             :         /* XXX: Perhaps call this from PySambaLdb's init function ? */
     237             : 
     238       35026 :         ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
     239       35026 :         ret = ldb_register_samba_handlers(ldb);
     240             : 
     241       35026 :         PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_error, ret, ldb);
     242             : 
     243       35026 :         Py_RETURN_NONE;
     244             : }
     245             : 
     246             : static PyMethodDef py_samba_ldb_methods[] = {
     247             :         { "set_loadparm", (PyCFunction)py_ldb_set_loadparm, METH_VARARGS, 
     248             :                 "set_loadparm(session_info)\n"
     249             :                 "Set loadparm context to use when connecting." },
     250             :         { "set_credentials", (PyCFunction)py_ldb_set_credentials, METH_VARARGS,
     251             :                 "set_credentials(credentials)\n"
     252             :                 "Set credentials to use when connecting." },
     253             :         { "set_opaque_integer", (PyCFunction)py_ldb_set_opaque_integer,
     254             :                 METH_VARARGS, NULL },
     255             :         { "set_utf8_casefold", (PyCFunction)py_ldb_set_utf8_casefold, 
     256             :                 METH_NOARGS,
     257             :                 "set_utf8_casefold()\n"
     258             :                 "Set the right Samba casefolding function for UTF8 charset." },
     259             :         { "register_samba_handlers", (PyCFunction)py_ldb_register_samba_handlers,
     260             :                 METH_NOARGS,
     261             :                 "register_samba_handlers()\n"
     262             :                 "Register Samba-specific LDB modules and schemas." },
     263             :         { "set_session_info", (PyCFunction)py_ldb_set_session_info, METH_VARARGS,
     264             :                 "set_session_info(session_info)\n"
     265             :                 "Set session info to use when connecting." },
     266             :         { "samba_schema_attribute_add",
     267             :                 (PyCFunction)py_ldb_samba_schema_attribute_add,
     268             :                 METH_VARARGS, NULL },
     269             :         {0},
     270             : };
     271             : 
     272             : static struct PyModuleDef moduledef = {
     273             :     PyModuleDef_HEAD_INIT,
     274             :     .m_name = "_ldb",
     275             :     .m_doc = "Samba-specific LDB python bindings",
     276             :     .m_size = -1,
     277             :     .m_methods = py_samba_ldb_methods,
     278             : };
     279             : 
     280             : static PyTypeObject PySambaLdb = {
     281             :         .tp_name = "samba._ldb.Ldb",
     282             :         .tp_doc = "Connection to a LDB database.",
     283             :         .tp_methods = py_samba_ldb_methods,
     284             :         .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
     285             : };
     286             : 
     287             : 
     288       13165 : MODULE_INIT_FUNC(_ldb)
     289             : {
     290         537 :         PyObject *m;
     291             : 
     292       13165 :         pyldb_module = PyImport_ImportModule("ldb");
     293       13165 :         if (pyldb_module == NULL)
     294           0 :                 return NULL;
     295             : 
     296       13165 :         PySambaLdb.tp_base = (PyTypeObject *)PyObject_GetAttrString(pyldb_module, "Ldb");
     297       13165 :         if (PySambaLdb.tp_base == NULL) {
     298           0 :                 Py_CLEAR(pyldb_module);
     299           0 :                 return NULL;
     300             :         }
     301             : 
     302       13165 :         py_ldb_error = PyObject_GetAttrString(pyldb_module, "LdbError");
     303             : 
     304       13165 :         Py_CLEAR(pyldb_module);
     305             : 
     306       13165 :         if (PyType_Ready(&PySambaLdb) < 0)
     307           0 :                 return NULL;
     308             : 
     309       13165 :         m = PyModule_Create(&moduledef);
     310       13165 :         if (m == NULL)
     311           0 :                 return NULL;
     312             : 
     313       11035 :         Py_INCREF(&PySambaLdb);
     314       13165 :         PyModule_AddObject(m, "Ldb", (PyObject *)&PySambaLdb);
     315             : 
     316             : #define ADD_LDB_STRING(val)  PyModule_AddStringConstant(m, #val, LDB_## val)
     317       13165 :         ADD_LDB_STRING(SYNTAX_SAMBA_INT32);
     318             : 
     319       13165 :         return m;
     320             : }

Generated by: LCOV version 1.14