ldb:pyldb: PyErr_LDB_DN_OR_RAISE makes more rigourous checks
authorDouglas Bagnall <douglas.bagnall@catalyst.net.nz>
Thu, 14 Mar 2024 02:10:07 +0000 (15:10 +1300)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 10 Apr 2024 05:13:32 +0000 (05:13 +0000)
This changes what happens all over the place
(lib/ldb/pyldb.c, source4/dns_server/pydns.c, source4/dsdb/pydsdb.c),
but causes no problems because it just checks what we always assumed.

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
lib/ldb/pyldb.h

index 1c6372c2ed9a5825b577297887bf2fdc8fa8d933..5487def58a03005d43061571ccd8041c7b02210b 100644 (file)
@@ -66,12 +66,31 @@ PyObject *pyldb_Dn_FromDn(struct ldb_dn *dn, PyLdbObject *pyldb);
 bool pyldb_Object_AsDn(TALLOC_CTX *mem_ctx, PyObject *object, struct ldb_context *ldb_ctx, struct ldb_dn **dn);
 #define pyldb_Dn_AS_DN(pyobj) ((PyLdbDnObject *)pyobj)->dn
 
-#define PyErr_LDB_DN_OR_RAISE(py_ldb_dn, dn) \
-       if (!pyldb_check_type(py_ldb_dn, "Dn")) { \
+
+/*
+ * PyErr_LDB_DN_OR_RAISE does 3 things:
+ * 1. checks that a PyObject is really a PyLdbDnObject.
+ * 2. checks that the ldb that the PyLdbDnObject knows is the ldb that its dn
+ *    knows.
+ * 3. sets the (struct ldb_dn *) dn argument to the dn the pyobject refers to.
+ *
+ * why so much? because we almost always need it.
+ */
+#define PyErr_LDB_DN_OR_RAISE(_py_obj, dn) do {                                \
+       PyLdbDnObject *_py_dn = NULL;                                   \
+       if (!pyldb_check_type(_py_obj, "Dn")) {                         \
                PyErr_SetString(PyExc_TypeError, "ldb Dn object required"); \
-               return NULL; \
-       } \
-       dn = pyldb_Dn_AS_DN(py_ldb_dn);
+               return NULL;                                            \
+       }                                                               \
+       _py_dn = (PyLdbDnObject *)_py_obj;                              \
+       dn = pyldb_Dn_AS_DN(_py_dn);                                    \
+       if (_py_dn->pyldb->ldb_ctx != ldb_dn_get_ldb_context(dn)) {     \
+               PyErr_SetString(PyExc_RuntimeError,                     \
+                               "Dn has a stale LDB connection");       \
+               return NULL;                                           \
+       }                                                              \
+} while(0)
+
 
 bool pyldb_check_type(PyObject *obj, const char *type_name);