LCOV - code coverage report
Current view: top level - source4/dsdb - pydsdb.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 597 826 72.3 %
Date: 2021-09-23 10:06:22 Functions: 37 38 97.4 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2010
       4             :    Copyright (C) Matthias Dieter Wallnöfer          2009
       5             :    
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             :    
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             :    
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include <Python.h>
      21             : #include "python/py3compat.h"
      22             : #include "includes.h"
      23             : #include <ldb.h>
      24             : #include <pyldb.h>
      25             : #include "dsdb/samdb/samdb.h"
      26             : #include "libcli/security/security.h"
      27             : #include "librpc/ndr/libndr.h"
      28             : #include "system/kerberos.h"
      29             : #include "auth/kerberos/kerberos.h"
      30             : #include "librpc/rpc/pyrpc_util.h"
      31             : #include "lib/policy/policy.h"
      32             : #include "param/pyparam.h"
      33             : #include "lib/util/dlinklist.h"
      34             : #include "dsdb/kcc/garbage_collect_tombstones.h"
      35             : #include "dsdb/kcc/scavenge_dns_records.h"
      36             : #include "libds/common/flag_mapping.h"
      37             : 
      38             : #undef strcasecmp
      39             : 
      40             : /* FIXME: These should be in a header file somewhere */
      41             : #define PyErr_LDB_OR_RAISE(py_ldb, ldb) \
      42             :         if (!py_check_dcerpc_type(py_ldb, "ldb", "Ldb")) { \
      43             :                 PyErr_SetString(PyExc_TypeError, "Ldb connection object required"); \
      44             :                 return NULL; \
      45             :         } \
      46             :         ldb = pyldb_Ldb_AS_LDBCONTEXT(py_ldb);
      47             : 
      48             : #define PyErr_LDB_DN_OR_RAISE(py_ldb_dn, dn) \
      49             :         if (!py_check_dcerpc_type(py_ldb_dn, "ldb", "Dn")) { \
      50             :                 PyErr_SetString(PyExc_TypeError, "ldb Dn object required"); \
      51             :                 return NULL; \
      52             :         } \
      53             :         dn = pyldb_Dn_AS_DN(py_ldb_dn);
      54             : 
      55          13 : static PyObject *py_ldb_get_exception(void)
      56             : {
      57          13 :         PyObject *mod = PyImport_ImportModule("ldb");
      58          13 :         PyObject *result = NULL;
      59          13 :         if (mod == NULL)
      60           0 :                 return NULL;
      61             : 
      62          13 :         result = PyObject_GetAttrString(mod, "LdbError");
      63          13 :         Py_CLEAR(mod);
      64          13 :         return result;
      65             : }
      66             : 
      67          13 : static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx)
      68             : {
      69          13 :         if (ret == LDB_ERR_PYTHON_EXCEPTION)
      70           0 :                 return; /* Python exception should already be set, just keep that */
      71             : 
      72          13 :         PyErr_SetObject(error, 
      73             :                         Py_BuildValue(discard_const_p(char, "(i,s)"), ret,
      74           0 :                         ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
      75             : }
      76             : 
      77         800 : static PyObject *py_samdb_server_site_name(PyObject *self, PyObject *args)
      78             : {
      79             :         PyObject *py_ldb, *result;
      80             :         struct ldb_context *ldb;
      81             :         const char *site;
      82             :         TALLOC_CTX *mem_ctx;
      83             : 
      84         800 :         if (!PyArg_ParseTuple(args, "O", &py_ldb))
      85           0 :                 return NULL;
      86             : 
      87         800 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
      88             : 
      89         800 :         mem_ctx = talloc_new(NULL);
      90         800 :         if (mem_ctx == NULL) {
      91           0 :                 PyErr_NoMemory();
      92           0 :                 return NULL;
      93             :         }
      94             : 
      95         800 :         site = samdb_server_site_name(ldb, mem_ctx);
      96         800 :         if (site == NULL) {
      97           3 :                 PyErr_SetString(PyExc_RuntimeError, "Failed to find server site");
      98           3 :                 talloc_free(mem_ctx);
      99           3 :                 return NULL;
     100             :         }
     101             : 
     102         797 :         result = PyUnicode_FromString(site);
     103         797 :         talloc_free(mem_ctx);
     104         797 :         return result;
     105             : }
     106             : 
     107           0 : static PyObject *py_dsdb_convert_schema_to_openldap(PyObject *self,
     108             :                                                     PyObject *args)
     109             : {
     110             :         char *target_str, *mapping;
     111             :         PyObject *py_ldb;
     112             :         struct ldb_context *ldb;
     113             :         PyObject *ret;
     114             :         char *retstr;
     115             : 
     116           0 :         if (!PyArg_ParseTuple(args, "Oss", &py_ldb, &target_str, &mapping))
     117           0 :                 return NULL;
     118             : 
     119           0 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
     120             : 
     121           0 :         retstr = dsdb_convert_schema_to_openldap(ldb, target_str, mapping);
     122           0 :         if (retstr == NULL) {
     123           0 :                 PyErr_SetString(PyExc_RuntimeError,
     124             :                                                 "dsdb_convert_schema_to_openldap failed");
     125           0 :                 return NULL;
     126             :         } 
     127             : 
     128           0 :         ret = PyUnicode_FromString(retstr);
     129           0 :         talloc_free(retstr);
     130           0 :         return ret;
     131             : }
     132             : 
     133         121 : static PyObject *py_samdb_set_domain_sid(PyLdbObject *self, PyObject *args)
     134             : {
     135             :         PyObject *py_ldb, *py_sid;
     136             :         struct ldb_context *ldb;
     137             :         struct dom_sid *sid;
     138             :         bool ret;
     139         121 :         const char *sid_str = NULL;
     140             : 
     141         121 :         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_sid))
     142           0 :                 return NULL;
     143             : 
     144         121 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
     145             : 
     146         121 :         sid_str = PyUnicode_AsUTF8(py_sid);
     147         121 :         if (sid_str == NULL) {
     148           0 :                 PyErr_NoMemory();
     149           0 :                 return NULL;
     150             :         }
     151             : 
     152         121 :         sid = dom_sid_parse_talloc(NULL, sid_str);
     153         121 :         if (sid == NULL) {
     154           0 :                 PyErr_NoMemory();
     155           0 :                 return NULL;
     156             :         }
     157             : 
     158         121 :         ret = samdb_set_domain_sid(ldb, sid);
     159         121 :         talloc_free(sid);
     160         121 :         if (!ret) {
     161           0 :                 PyErr_SetString(PyExc_RuntimeError, "set_domain_sid failed");
     162           0 :                 return NULL;
     163             :         } 
     164         121 :         Py_RETURN_NONE;
     165             : }
     166             : 
     167         324 : static PyObject *py_samdb_set_ntds_settings_dn(PyLdbObject *self, PyObject *args)
     168             : { 
     169             :         PyObject *py_ldb, *py_ntds_settings_dn;
     170             :         struct ldb_context *ldb;
     171             :         struct ldb_dn *ntds_settings_dn;
     172             :         TALLOC_CTX *tmp_ctx;
     173             :         bool ret;
     174             : 
     175         324 :         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_ntds_settings_dn))
     176           0 :                 return NULL;
     177             : 
     178         324 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
     179             : 
     180         324 :         tmp_ctx = talloc_new(NULL);
     181         324 :         if (tmp_ctx == NULL) {
     182           0 :                 PyErr_NoMemory();
     183           0 :                 return NULL;
     184             :         }
     185             : 
     186         324 :         if (!pyldb_Object_AsDn(tmp_ctx, py_ntds_settings_dn, ldb, &ntds_settings_dn)) {
     187             :                 /* exception thrown by "pyldb_Object_AsDn" */
     188           0 :                 talloc_free(tmp_ctx);
     189           0 :                 return NULL;
     190             :         }
     191             : 
     192         324 :         ret = samdb_set_ntds_settings_dn(ldb, ntds_settings_dn);
     193         324 :         talloc_free(tmp_ctx);
     194         324 :         if (!ret) {
     195           0 :                 PyErr_SetString(PyExc_RuntimeError, "set_ntds_settings_dn failed");
     196           0 :                 return NULL;
     197             :         } 
     198         324 :         Py_RETURN_NONE;
     199             : }
     200             : 
     201       10782 : static PyObject *py_samdb_get_domain_sid(PyLdbObject *self, PyObject *args)
     202             : { 
     203             :         PyObject *py_ldb;
     204             :         struct ldb_context *ldb;
     205             :         const struct dom_sid *sid;
     206             :         struct dom_sid_buf buf;
     207             :         PyObject *ret;
     208             : 
     209       10782 :         if (!PyArg_ParseTuple(args, "O", &py_ldb))
     210           0 :                 return NULL;
     211             : 
     212       10782 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
     213             : 
     214       10782 :         sid = samdb_domain_sid(ldb);
     215       10782 :         if (!sid) {
     216           0 :                 PyErr_SetString(PyExc_RuntimeError, "samdb_domain_sid failed");
     217           0 :                 return NULL;
     218             :         }
     219             : 
     220       10782 :         ret = PyUnicode_FromString(dom_sid_str_buf(sid, &buf));
     221       10782 :         return ret;
     222             : }
     223             : 
     224         842 : static PyObject *py_samdb_ntds_invocation_id(PyObject *self, PyObject *args)
     225             : {
     226             :         PyObject *py_ldb, *result;
     227             :         struct ldb_context *ldb;
     228             :         const struct GUID *guid;
     229             :         char *retstr;
     230             : 
     231         842 :         if (!PyArg_ParseTuple(args, "O", &py_ldb)) {
     232           0 :                 return NULL;
     233             :         }
     234             : 
     235         842 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
     236             : 
     237         842 :         guid = samdb_ntds_invocation_id(ldb);
     238         842 :         if (guid == NULL) {
     239           0 :                 PyErr_SetString(PyExc_RuntimeError,
     240             :                                                 "Failed to find NTDS invocation ID");
     241           0 :                 return NULL;
     242             :         }
     243             : 
     244         842 :         retstr = GUID_string(NULL, guid);
     245         842 :         if (retstr == NULL) {
     246           0 :                 PyErr_NoMemory();
     247           0 :                 return NULL;
     248             :         }
     249         842 :         result = PyUnicode_FromString(retstr);
     250         842 :         talloc_free(retstr);
     251         842 :         return result;
     252             : }
     253             : 
     254      107243 : static PyObject *py_dsdb_get_oid_from_attid(PyObject *self, PyObject *args)
     255             : {
     256             :         PyObject *py_ldb;
     257             :         struct ldb_context *ldb;
     258             :         uint32_t attid;
     259             :         struct dsdb_schema *schema;
     260             :         const char *oid;
     261             :         PyObject *ret;
     262             :         WERROR status;
     263             :         TALLOC_CTX *mem_ctx;
     264             : 
     265      107243 :         if (!PyArg_ParseTuple(args, "OI", &py_ldb, &attid))
     266           0 :                 return NULL;
     267             : 
     268      107243 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
     269             : 
     270      107243 :         mem_ctx = talloc_new(NULL);
     271      107243 :         if (!mem_ctx) {
     272           0 :                 PyErr_NoMemory();
     273           0 :                 return NULL;
     274             :         }
     275             : 
     276      107243 :         schema = dsdb_get_schema(ldb, mem_ctx);
     277      107243 :         if (!schema) {
     278           0 :                 PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb \n");
     279           0 :                 talloc_free(mem_ctx);
     280           0 :                 return NULL;
     281             :         }
     282             :         
     283      107243 :         status = dsdb_schema_pfm_oid_from_attid(schema->prefixmap, attid,
     284             :                                                 mem_ctx, &oid);
     285      107243 :         if (!W_ERROR_IS_OK(status)) {
     286           0 :                 PyErr_SetWERROR(status);
     287           0 :                 talloc_free(mem_ctx);
     288           0 :                 return NULL;
     289             :         }
     290             : 
     291      107243 :         ret = PyUnicode_FromString(oid);
     292             : 
     293      107243 :         talloc_free(mem_ctx);
     294             : 
     295      107243 :         return ret;
     296             : }
     297             : 
     298             : 
     299    11493553 : static PyObject *py_dsdb_get_attid_from_lDAPDisplayName(PyObject *self, PyObject *args)
     300             : {
     301             :         PyObject *py_ldb, *is_schema_nc;
     302             :         struct ldb_context *ldb;
     303             :         struct dsdb_schema *schema;
     304             :         const char *ldap_display_name;
     305    11493553 :         bool schema_nc = false;
     306             :         const struct dsdb_attribute *a;
     307             :         uint32_t attid;
     308             : 
     309    11493553 :         if (!PyArg_ParseTuple(args, "OsO", &py_ldb, &ldap_display_name, &is_schema_nc))
     310           0 :                 return NULL;
     311             : 
     312    11493553 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
     313             : 
     314    11493553 :         if (is_schema_nc) {
     315    11493553 :                 if (!PyBool_Check(is_schema_nc)) {
     316           0 :                         PyErr_SetString(PyExc_TypeError, "Expected boolean is_schema_nc");
     317           0 :                         return NULL;
     318             :                 }
     319    11493553 :                 if (is_schema_nc == Py_True) {
     320     5529289 :                         schema_nc = true;
     321             :                 }
     322             :         }
     323             : 
     324    11493553 :         schema = dsdb_get_schema(ldb, NULL);
     325             : 
     326    11493553 :         if (!schema) {
     327           0 :                 PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb");
     328           0 :                 return NULL;
     329             :         }
     330             : 
     331    11493553 :         a = dsdb_attribute_by_lDAPDisplayName(schema, ldap_display_name);
     332    11493553 :         if (a == NULL) {
     333          70 :                 PyErr_Format(PyExc_KeyError, "Failed to find attribute '%s'", ldap_display_name);
     334          70 :                 return NULL;
     335             :         }
     336             : 
     337    11493483 :         attid = dsdb_attribute_get_attid(a, schema_nc);
     338             : 
     339    11493483 :         return PyLong_FromUnsignedLong(attid);
     340             : }
     341             : 
     342             : /*
     343             :   return the systemFlags as int from the attribute name
     344             :  */
     345     7275609 : static PyObject *py_dsdb_get_systemFlags_from_lDAPDisplayName(PyObject *self, PyObject *args)
     346             : {
     347             :         PyObject *py_ldb;
     348             :         struct ldb_context *ldb;
     349             :         struct dsdb_schema *schema;
     350             :         const char *ldap_display_name;
     351             :         const struct dsdb_attribute *attribute;
     352             : 
     353     7275609 :         if (!PyArg_ParseTuple(args, "Os", &py_ldb, &ldap_display_name))
     354           0 :                 return NULL;
     355             : 
     356     7275609 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
     357             : 
     358     7275609 :         schema = dsdb_get_schema(ldb, NULL);
     359             : 
     360     7275609 :         if (!schema) {
     361           0 :                 PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb");
     362           0 :                 return NULL;
     363             :         }
     364             : 
     365     7275609 :         attribute = dsdb_attribute_by_lDAPDisplayName(schema, ldap_display_name);
     366     7275609 :         if (attribute == NULL) {
     367           0 :                 PyErr_Format(PyExc_KeyError, "Failed to find attribute '%s'", ldap_display_name);
     368           0 :                 return NULL;
     369             :         }
     370             : 
     371     7275609 :         return PyLong_FromLong(attribute->systemFlags);
     372             : }
     373             : 
     374             : /*
     375             :   return the linkID from the attribute name
     376             :  */
     377       21481 : static PyObject *py_dsdb_get_linkId_from_lDAPDisplayName(PyObject *self, PyObject *args)
     378             : {
     379             :         PyObject *py_ldb;
     380             :         struct ldb_context *ldb;
     381             :         struct dsdb_schema *schema;
     382             :         const char *ldap_display_name;
     383             :         const struct dsdb_attribute *attribute;
     384             : 
     385       21481 :         if (!PyArg_ParseTuple(args, "Os", &py_ldb, &ldap_display_name))
     386           0 :                 return NULL;
     387             : 
     388       21481 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
     389             : 
     390       21481 :         schema = dsdb_get_schema(ldb, NULL);
     391             : 
     392       21481 :         if (!schema) {
     393           0 :                 PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb");
     394           0 :                 return NULL;
     395             :         }
     396             : 
     397       21481 :         attribute = dsdb_attribute_by_lDAPDisplayName(schema, ldap_display_name);
     398       21481 :         if (attribute == NULL) {
     399           0 :                 PyErr_Format(PyExc_KeyError, "Failed to find attribute '%s'", ldap_display_name);
     400           0 :                 return NULL;
     401             :         }
     402             : 
     403       21481 :         return PyLong_FromLong(attribute->linkID);
     404             : }
     405             : 
     406             : /*
     407             :   return the backlink attribute name (if any) for an attribute
     408             :  */
     409        1427 : static PyObject *py_dsdb_get_backlink_from_lDAPDisplayName(PyObject *self, PyObject *args)
     410             : {
     411             :         PyObject *py_ldb;
     412             :         struct ldb_context *ldb;
     413             :         struct dsdb_schema *schema;
     414             :         const char *ldap_display_name;
     415             :         const struct dsdb_attribute *attribute, *target_attr;
     416             : 
     417        1427 :         if (!PyArg_ParseTuple(args, "Os", &py_ldb, &ldap_display_name))
     418           0 :                 return NULL;
     419             : 
     420        1427 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
     421             : 
     422        1427 :         schema = dsdb_get_schema(ldb, NULL);
     423             : 
     424        1427 :         if (!schema) {
     425           0 :                 PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb");
     426           0 :                 return NULL;
     427             :         }
     428             : 
     429        1427 :         attribute = dsdb_attribute_by_lDAPDisplayName(schema, ldap_display_name);
     430        1427 :         if (attribute == NULL) {
     431           0 :                 PyErr_Format(PyExc_KeyError, "Failed to find attribute '%s'", ldap_display_name);
     432           0 :                 return NULL;
     433             :         }
     434             : 
     435        1427 :         if (attribute->linkID == 0) {
     436           0 :                 Py_RETURN_NONE;
     437             :         }
     438             : 
     439        1427 :         target_attr = dsdb_attribute_by_linkID(schema, attribute->linkID ^ 1);
     440        1427 :         if (target_attr == NULL) {
     441             :                 /* when we add pseudo-backlinks we'll need to handle
     442             :                    them here */
     443         311 :                 Py_RETURN_NONE;
     444             :         }
     445             : 
     446        1116 :         return PyUnicode_FromString(target_attr->lDAPDisplayName);
     447             : }
     448             : 
     449             : 
     450    11906234 : static PyObject *py_dsdb_get_lDAPDisplayName_by_attid(PyObject *self, PyObject *args)
     451             : {
     452             :         PyObject *py_ldb;
     453             :         struct ldb_context *ldb;
     454             :         struct dsdb_schema *schema;
     455             :         const struct dsdb_attribute *a;
     456             :         uint32_t attid;
     457             : 
     458    11906234 :         if (!PyArg_ParseTuple(args, "OI", &py_ldb, &attid))
     459           0 :                 return NULL;
     460             : 
     461    11906234 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
     462             : 
     463    11906234 :         schema = dsdb_get_schema(ldb, NULL);
     464             : 
     465    11906234 :         if (!schema) {
     466           0 :                 PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb");
     467           0 :                 return NULL;
     468             :         }
     469             : 
     470    11906234 :         a = dsdb_attribute_by_attributeID_id(schema, attid);
     471    11906234 :         if (a == NULL) {
     472           0 :                 PyErr_Format(PyExc_KeyError, "Failed to find attribute '0x%08x'", attid);
     473           0 :                 return NULL;
     474             :         }
     475             : 
     476    11906234 :         return PyUnicode_FromString(a->lDAPDisplayName);
     477             : }
     478             : 
     479             : 
     480             : /*
     481             :   return the attribute syntax oid as a string from the attribute name
     482             :  */
     483     7280899 : static PyObject *py_dsdb_get_syntax_oid_from_lDAPDisplayName(PyObject *self, PyObject *args)
     484             : {
     485             :         PyObject *py_ldb;
     486             :         struct ldb_context *ldb;
     487             :         struct dsdb_schema *schema;
     488             :         const char *ldap_display_name;
     489             :         const struct dsdb_attribute *attribute;
     490             : 
     491     7280899 :         if (!PyArg_ParseTuple(args, "Os", &py_ldb, &ldap_display_name))
     492           0 :                 return NULL;
     493             : 
     494     7280899 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
     495             : 
     496     7280899 :         schema = dsdb_get_schema(ldb, NULL);
     497             : 
     498     7280899 :         if (!schema) {
     499           0 :                 PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb");
     500           0 :                 return NULL;
     501             :         }
     502             : 
     503     7280899 :         attribute = dsdb_attribute_by_lDAPDisplayName(schema, ldap_display_name);
     504     7280899 :         if (attribute == NULL) {
     505           0 :                 PyErr_Format(PyExc_KeyError, "Failed to find attribute '%s'", ldap_display_name);
     506           0 :                 return NULL;
     507             :         }
     508             : 
     509     7280899 :         return PyUnicode_FromString(attribute->syntax->ldap_oid);
     510             : }
     511             : 
     512             : /*
     513             :   convert a python string to a DRSUAPI drsuapi_DsReplicaAttribute attribute
     514             :  */
     515         569 : static PyObject *py_dsdb_DsReplicaAttribute(PyObject *self, PyObject *args)
     516             : {
     517             :         PyObject *py_ldb, *el_list, *ret;
     518             :         struct ldb_context *ldb;
     519             :         char *ldap_display_name;
     520             :         const struct dsdb_attribute *a;
     521             :         struct dsdb_schema *schema;
     522             :         struct dsdb_syntax_ctx syntax_ctx;
     523             :         struct ldb_message_element *el;
     524             :         struct drsuapi_DsReplicaAttribute *attr;
     525             :         TALLOC_CTX *tmp_ctx;
     526             :         WERROR werr;
     527             :         Py_ssize_t i;
     528             : 
     529         569 :         if (!PyArg_ParseTuple(args, "OsO", &py_ldb, &ldap_display_name, &el_list)) {
     530           0 :                 return NULL;
     531             :         }
     532             : 
     533         569 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
     534             : 
     535         569 :         schema = dsdb_get_schema(ldb, NULL);
     536         569 :         if (!schema) {
     537           0 :                 PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb");
     538           0 :                 return NULL;
     539             :         }
     540             : 
     541         569 :         a = dsdb_attribute_by_lDAPDisplayName(schema, ldap_display_name);
     542         569 :         if (a == NULL) {
     543           0 :                 PyErr_Format(PyExc_KeyError, "Failed to find attribute '%s'", ldap_display_name);
     544           0 :                 return NULL;
     545             :         }
     546             : 
     547         569 :         dsdb_syntax_ctx_init(&syntax_ctx, ldb, schema);
     548         569 :         syntax_ctx.is_schema_nc = false;
     549             : 
     550         569 :         tmp_ctx = talloc_new(ldb);
     551         569 :         if (tmp_ctx == NULL) {
     552           0 :                 PyErr_NoMemory();
     553           0 :                 return NULL;
     554             :         }
     555             : 
     556             :         /* If we were not given an LdbMessageElement */
     557         569 :         if (!PyList_Check(el_list)) {
     558           0 :                 if (!py_check_dcerpc_type(el_list, "ldb", "MessageElement")) {
     559           0 :                         PyErr_SetString(py_ldb_get_exception(),
     560             :                                         "list of strings or ldb MessageElement object required");
     561           0 :                         return NULL;
     562             :                 }
     563             :                 /*
     564             :                  * NOTE:
     565             :                  * el may not be a valid talloc context, it
     566             :                  * could be part of an array
     567             :                  */
     568           0 :                 el = pyldb_MessageElement_AsMessageElement(el_list);
     569             :         } else {
     570         569 :                 el = talloc_zero(tmp_ctx, struct ldb_message_element);
     571         569 :                 if (el == NULL) {
     572           0 :                         PyErr_NoMemory();
     573           0 :                         talloc_free(tmp_ctx);
     574           0 :                         return NULL;
     575             :                 }
     576             : 
     577         569 :                 el->name = ldap_display_name;
     578         569 :                 el->num_values = PyList_Size(el_list);
     579             : 
     580         569 :                 el->values = talloc_array(el, struct ldb_val, el->num_values);
     581         569 :                 if (el->values == NULL) {
     582           0 :                         PyErr_NoMemory();
     583           0 :                         talloc_free(tmp_ctx);
     584           0 :                         return NULL;
     585             :                 }
     586             : 
     587        1414 :                 for (i = 0; i < el->num_values; i++) {
     588         845 :                         PyObject *item = PyList_GetItem(el_list, i);
     589         845 :                         if (!(PyBytes_Check(item))) {
     590           0 :                                 PyErr_Format(PyExc_TypeError,
     591             :                                              "ldif_element type should be bytes"
     592             :                                              );
     593           0 :                                 talloc_free(tmp_ctx);
     594           0 :                                 return NULL;
     595             :                         }
     596        1690 :                         el->values[i].data =
     597         845 :                                 (uint8_t *)PyBytes_AsString(item);
     598         845 :                         el->values[i].length = PyBytes_Size(item);
     599             :                 }
     600             :         }
     601             : 
     602         569 :         attr = talloc_zero(tmp_ctx, struct drsuapi_DsReplicaAttribute);
     603         569 :         if (attr == NULL) {
     604           0 :                 PyErr_NoMemory();
     605           0 :                 talloc_free(tmp_ctx);
     606           0 :                 return NULL;
     607             :         }
     608             : 
     609         569 :         werr = a->syntax->ldb_to_drsuapi(&syntax_ctx, a, el, attr, attr);
     610         569 :         PyErr_WERROR_NOT_OK_RAISE(werr);
     611             : 
     612         569 :         ret = py_return_ndr_struct("samba.dcerpc.drsuapi", "DsReplicaAttribute", attr, attr);
     613             : 
     614         569 :         talloc_free(tmp_ctx);
     615             : 
     616         569 :         return ret;
     617             : }
     618             : 
     619             : 
     620             : /*
     621             :   normalise a ldb attribute list
     622             :  */
     623     8431422 : static PyObject *py_dsdb_normalise_attributes(PyObject *self, PyObject *args)
     624             : {
     625             :         PyObject *py_ldb, *el_list, *py_ret;
     626             :         struct ldb_context *ldb;
     627             :         char *ldap_display_name;
     628             :         const struct dsdb_attribute *a;
     629             :         struct dsdb_schema *schema;
     630             :         struct dsdb_syntax_ctx syntax_ctx;
     631             :         struct ldb_message_element *el, *new_el;
     632             :         struct drsuapi_DsReplicaAttribute *attr;
     633             :         PyLdbMessageElementObject *ret;
     634             :         TALLOC_CTX *tmp_ctx;
     635             :         WERROR werr;
     636             :         Py_ssize_t i;
     637     8431422 :         PyTypeObject *py_type = NULL;
     638     8431422 :         PyObject *module = NULL;
     639             : 
     640     8431422 :         if (!PyArg_ParseTuple(args, "OsO", &py_ldb, &ldap_display_name, &el_list)) {
     641           0 :                 return NULL;
     642             :         }
     643             : 
     644     8431422 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
     645             : 
     646     8431422 :         schema = dsdb_get_schema(ldb, NULL);
     647     8431422 :         if (!schema) {
     648           0 :                 PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb");
     649           0 :                 return NULL;
     650             :         }
     651             : 
     652     8431422 :         a = dsdb_attribute_by_lDAPDisplayName(schema, ldap_display_name);
     653     8431422 :         if (a == NULL) {
     654           0 :                 PyErr_Format(PyExc_KeyError, "Failed to find attribute '%s'", ldap_display_name);
     655           0 :                 return NULL;
     656             :         }
     657             : 
     658     8431422 :         dsdb_syntax_ctx_init(&syntax_ctx, ldb, schema);
     659     8431422 :         syntax_ctx.is_schema_nc = false;
     660             : 
     661     8431422 :         tmp_ctx = talloc_new(ldb);
     662     8431422 :         if (tmp_ctx == NULL) {
     663           0 :                 PyErr_NoMemory();
     664           0 :                 return NULL;
     665             :         }
     666             : 
     667     8431422 :         if (!PyList_Check(el_list)) {
     668      371883 :                 if (!py_check_dcerpc_type(el_list, "ldb", "MessageElement")) {
     669           0 :                         PyErr_SetString(py_ldb_get_exception(),
     670             :                                         "list of strings or ldb MessageElement object required");
     671           0 :                         return NULL;
     672             :                 }
     673             :                 /*
     674             :                  * NOTE:
     675             :                  * el may not be a valid talloc context, it
     676             :                  * could be part of an array
     677             :                  */
     678      371883 :                 el = pyldb_MessageElement_AsMessageElement(el_list);
     679             :         } else {
     680     8059539 :                 el = talloc_zero(tmp_ctx, struct ldb_message_element);
     681     8059539 :                 if (el == NULL) {
     682           0 :                         PyErr_NoMemory();
     683           0 :                         talloc_free(tmp_ctx);
     684           0 :                         return NULL;
     685             :                 }
     686             : 
     687     8059539 :                 el->name = ldap_display_name;
     688     8059539 :                 el->num_values = PyList_Size(el_list);
     689             : 
     690     8059539 :                 el->values = talloc_array(el, struct ldb_val, el->num_values);
     691     8059539 :                 if (el->values == NULL) {
     692           0 :                         PyErr_NoMemory();
     693           0 :                         talloc_free(tmp_ctx);
     694           0 :                         return NULL;
     695             :                 }
     696             : 
     697    14830262 :                 for (i = 0; i < el->num_values; i++) {
     698     8059539 :                         PyObject *item = PyList_GetItem(el_list, i);
     699     8059539 :                         if (!PyBytes_Check(item)) {
     700           0 :                                 PyErr_Format(PyExc_TypeError,
     701             :                                              "ldif_element type should be bytes"
     702             :                                              );
     703           0 :                                 talloc_free(tmp_ctx);
     704           0 :                                 return NULL;
     705             :                         }
     706     8059539 :                         el->values[i].data = (uint8_t *)PyBytes_AsString(item);
     707     8059539 :                         el->values[i].length = PyBytes_Size(item);
     708             :                 }
     709             :         }
     710             : 
     711     8431422 :         new_el = talloc_zero(tmp_ctx, struct ldb_message_element);
     712     8431422 :         if (new_el == NULL) {
     713           0 :                 PyErr_NoMemory();
     714           0 :                 talloc_free(tmp_ctx);
     715           0 :                 return NULL;
     716             :         }
     717             : 
     718             :         /* Normalise "objectClass" attribute if needed */
     719     8431422 :         if (ldb_attr_cmp(a->lDAPDisplayName, "objectClass") == 0) {
     720             :                 int iret;
     721      371883 :                 iret = dsdb_sort_objectClass_attr(ldb, schema, el, new_el, new_el);
     722      371883 :                 if (iret != LDB_SUCCESS) {
     723           0 :                         PyErr_SetString(PyExc_RuntimeError, ldb_errstring(ldb));
     724           0 :                         talloc_free(tmp_ctx);
     725           0 :                         return NULL;
     726             :                 }
     727             :         }
     728             : 
     729             :         /* first run ldb_to_drsuapi, then convert back again. This has
     730             :          * the effect of normalising the attributes
     731             :          */
     732             : 
     733     8431422 :         attr = talloc_zero(tmp_ctx, struct drsuapi_DsReplicaAttribute);
     734     8431422 :         if (attr == NULL) {
     735           0 :                 PyErr_NoMemory();
     736           0 :                 talloc_free(tmp_ctx);
     737           0 :                 return NULL;
     738             :         }
     739             : 
     740     8431422 :         werr = a->syntax->ldb_to_drsuapi(&syntax_ctx, a, el, attr, attr);
     741     8431422 :         PyErr_WERROR_NOT_OK_RAISE(werr);
     742             : 
     743             :         /* now convert back again */
     744     8431422 :         werr = a->syntax->drsuapi_to_ldb(&syntax_ctx, a, attr, new_el, new_el);
     745     8431422 :         PyErr_WERROR_NOT_OK_RAISE(werr);
     746             : 
     747     8431422 :         module = PyImport_ImportModule("ldb");
     748     8431422 :         if (module == NULL) {
     749           0 :                 return NULL;
     750             :         }
     751             : 
     752     8431422 :         py_type = (PyTypeObject *)PyObject_GetAttrString(module, "MessageElement");
     753     8431422 :         if (py_type == NULL) {
     754           0 :                 Py_DECREF(module);
     755           0 :                 return NULL;
     756             :         }
     757             : 
     758     8431422 :         Py_CLEAR(module);
     759             : 
     760     8431422 :         py_ret = py_type->tp_alloc(py_type, 0);
     761     8431422 :         Py_CLEAR(py_type);
     762     8431422 :         if (py_ret == NULL) {
     763           0 :                 PyErr_NoMemory();
     764           0 :                 return NULL;
     765             :         }
     766     8431422 :         ret = (PyLdbMessageElementObject *)py_ret;
     767             : 
     768     8431422 :         ret->mem_ctx = talloc_new(NULL);
     769     8431422 :         if (talloc_reference(ret->mem_ctx, new_el) == NULL) {
     770           0 :                 Py_CLEAR(py_ret);
     771           0 :                 PyErr_NoMemory();
     772           0 :                 return NULL;
     773             :         }
     774     8431422 :         ret->el = new_el;
     775             : 
     776     8431422 :         talloc_free(tmp_ctx);
     777             : 
     778     8431422 :         return py_ret;
     779             : }
     780             : 
     781             : 
     782         254 : static PyObject *py_dsdb_set_ntds_invocation_id(PyObject *self, PyObject *args)
     783             : {
     784             :         PyObject *py_ldb, *py_guid;
     785             :         bool ret;
     786             :         struct GUID guid;
     787             :         struct ldb_context *ldb;
     788         254 :         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_guid))
     789           0 :                 return NULL;
     790             : 
     791         254 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
     792         254 :         GUID_from_string(PyUnicode_AsUTF8(py_guid), &guid);
     793             : 
     794         254 :         if (GUID_all_zero(&guid)) {
     795           0 :                 PyErr_SetString(PyExc_RuntimeError, "set_ntds_invocation_id rejected due to all-zero invocation ID");
     796           0 :                 return NULL;
     797             :         }
     798             : 
     799         254 :         ret = samdb_set_ntds_invocation_id(ldb, &guid);
     800         254 :         if (!ret) {
     801           0 :                 PyErr_SetString(PyExc_RuntimeError, "set_ntds_invocation_id failed");
     802           0 :                 return NULL;
     803             :         }
     804         254 :         Py_RETURN_NONE;
     805             : }
     806             : 
     807        1597 : static PyObject *py_samdb_ntds_objectGUID(PyObject *self, PyObject *args)
     808             : {
     809             :         PyObject *py_ldb, *result;
     810             :         struct ldb_context *ldb;
     811             :         const struct GUID *guid;
     812             :         char *retstr;
     813             : 
     814        1597 :         if (!PyArg_ParseTuple(args, "O", &py_ldb)) {
     815           0 :                 return NULL;
     816             :         }
     817             : 
     818        1597 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
     819             : 
     820        1597 :         guid = samdb_ntds_objectGUID(ldb);
     821        1597 :         if (guid == NULL) {
     822           0 :                 PyErr_SetString(PyExc_RuntimeError, "Failed to find NTDS GUID");
     823           0 :                 return NULL;
     824             :         }
     825             : 
     826        1597 :         retstr = GUID_string(NULL, guid);
     827        1597 :         if (retstr == NULL) {
     828           0 :                 PyErr_NoMemory();
     829           0 :                 return NULL;
     830             :         }
     831        1597 :         result = PyUnicode_FromString(retstr);
     832        1597 :         talloc_free(retstr);
     833        1597 :         return result;
     834             : }
     835             : 
     836       21461 : static PyObject *py_dsdb_set_global_schema(PyObject *self, PyObject *args)
     837             : {
     838             :         PyObject *py_ldb;
     839             :         struct ldb_context *ldb;
     840             :         int ret;
     841       21461 :         if (!PyArg_ParseTuple(args, "O", &py_ldb))
     842           0 :                 return NULL;
     843             : 
     844       21461 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
     845             : 
     846       21461 :         ret = dsdb_set_global_schema(ldb);
     847       21461 :         PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
     848             : 
     849       21461 :         Py_RETURN_NONE;
     850             : }
     851             : 
     852          25 : static PyObject *py_dsdb_load_partition_usn(PyObject *self, PyObject *args)
     853             : {
     854             :         PyObject *py_dn, *py_ldb, *result;
     855             :         struct ldb_dn *dn;
     856             :         uint64_t highest_uSN, urgent_uSN;
     857             :         struct ldb_context *ldb;
     858             :         TALLOC_CTX *mem_ctx;
     859             :         int ret;
     860             : 
     861          25 :         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_dn)) {
     862           0 :                 return NULL;
     863             :         }
     864             : 
     865          25 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
     866             : 
     867          25 :         mem_ctx = talloc_new(NULL);
     868          25 :         if (mem_ctx == NULL) {
     869           0 :                 PyErr_NoMemory();
     870           0 :                 return NULL;
     871             :         }
     872             : 
     873          25 :         if (!pyldb_Object_AsDn(mem_ctx, py_dn, ldb, &dn)) {
     874           0 :                 talloc_free(mem_ctx);
     875           0 :                 return NULL;
     876             :         }
     877             : 
     878          25 :         ret = dsdb_load_partition_usn(ldb, dn, &highest_uSN, &urgent_uSN);
     879          25 :         if (ret != LDB_SUCCESS) {
     880           0 :            PyErr_Format(PyExc_RuntimeError,
     881             :                         "Failed to load partition [%s] uSN - %s",
     882             :                         ldb_dn_get_linearized(dn),
     883             :                         ldb_errstring(ldb));
     884           0 :            talloc_free(mem_ctx);
     885           0 :            return NULL;
     886             :         }
     887             : 
     888          25 :         talloc_free(mem_ctx);
     889             : 
     890          25 :         result = Py_BuildValue(
     891             :                         "{s:l, s:l}",
     892             :                         "uSNHighest", (uint64_t)highest_uSN,
     893             :                         "uSNUrgent", (uint64_t)urgent_uSN);
     894             : 
     895          25 :         return result;
     896             : }
     897             : 
     898         603 : static PyObject *py_dsdb_set_am_rodc(PyObject *self, PyObject *args)
     899             : {
     900             :         PyObject *py_ldb;
     901             :         bool ret;
     902             :         struct ldb_context *ldb;
     903             :         int py_val;
     904             : 
     905         603 :         if (!PyArg_ParseTuple(args, "Oi", &py_ldb, &py_val))
     906           0 :                 return NULL;
     907             : 
     908         603 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
     909         603 :         ret = samdb_set_am_rodc(ldb, (bool)py_val);
     910         603 :         if (!ret) {
     911           0 :                 PyErr_SetString(PyExc_RuntimeError, "set_am_rodc failed");
     912           0 :                 return NULL;
     913             :         }
     914         603 :         Py_RETURN_NONE;
     915             : }
     916             : 
     917         340 : static PyObject *py_dsdb_set_schema_from_ldif(PyObject *self, PyObject *args)
     918             : {
     919             :         WERROR result;
     920             :         char *pf, *df, *dn;
     921             :         PyObject *py_ldb;
     922             :         struct ldb_context *ldb;
     923             : 
     924         340 :         if (!PyArg_ParseTuple(args, "Osss", &py_ldb, &pf, &df, &dn))
     925           0 :                 return NULL;
     926             : 
     927         340 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
     928             : 
     929         340 :         result = dsdb_set_schema_from_ldif(ldb, pf, df, dn);
     930         340 :         PyErr_WERROR_NOT_OK_RAISE(result);
     931             : 
     932         340 :         Py_RETURN_NONE;
     933             : }
     934             : 
     935         456 : static PyObject *py_dsdb_set_schema_from_ldb(PyObject *self, PyObject *args)
     936             : {
     937             :         PyObject *py_ldb;
     938             :         struct ldb_context *ldb;
     939             :         PyObject *py_from_ldb;
     940             :         struct ldb_context *from_ldb;
     941             :         struct dsdb_schema *schema;
     942             :         int ret;
     943         456 :         char write_indices_and_attributes = SCHEMA_WRITE;
     944         456 :         if (!PyArg_ParseTuple(args, "OO|b",
     945             :                               &py_ldb, &py_from_ldb, &write_indices_and_attributes))
     946           0 :                 return NULL;
     947             : 
     948         456 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
     949             : 
     950         456 :         PyErr_LDB_OR_RAISE(py_from_ldb, from_ldb);
     951             : 
     952         456 :         schema = dsdb_get_schema(from_ldb, NULL);
     953         456 :         if (!schema) {
     954           0 :                 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on 'from' ldb!\n");
     955           0 :                 return NULL;
     956             :         }
     957             : 
     958         456 :         ret = dsdb_reference_schema(ldb, schema, write_indices_and_attributes);
     959         456 :         PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
     960             : 
     961         456 :         Py_RETURN_NONE;
     962             : }
     963             : 
     964         121 : static PyObject *py_dsdb_write_prefixes_from_schema_to_ldb(PyObject *self, PyObject *args)
     965             : {
     966             :         PyObject *py_ldb;
     967             :         struct ldb_context *ldb;
     968             :         WERROR result;
     969             :         struct dsdb_schema *schema;
     970             : 
     971         121 :         if (!PyArg_ParseTuple(args, "O", &py_ldb))
     972           0 :                 return NULL;
     973             : 
     974         121 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
     975             : 
     976         121 :         schema = dsdb_get_schema(ldb, NULL);
     977         121 :         if (!schema) {
     978           0 :                 PyErr_SetString(PyExc_RuntimeError, "Failed to set find a schema on ldb!\n");
     979           0 :                 return NULL;
     980             :         }
     981             : 
     982         121 :         result = dsdb_write_prefixes_from_schema_to_ldb(NULL, ldb, schema);
     983         121 :         PyErr_WERROR_NOT_OK_RAISE(result);
     984             : 
     985         121 :         Py_RETURN_NONE;
     986             : }
     987             : 
     988             : 
     989        2611 : static PyObject *py_dsdb_get_partitions_dn(PyObject *self, PyObject *args)
     990             : {
     991             :         struct ldb_context *ldb;
     992             :         struct ldb_dn *dn;
     993             :         PyObject *py_ldb, *ret;
     994             : 
     995        2611 :         if (!PyArg_ParseTuple(args, "O", &py_ldb))
     996           0 :                 return NULL;
     997             : 
     998        2611 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
     999             : 
    1000        2611 :         dn = samdb_partitions_dn(ldb, NULL);
    1001        2611 :         if (dn == NULL) {
    1002           0 :                 PyErr_NoMemory();
    1003           0 :                 return NULL;
    1004             :         }
    1005        2611 :         ret = pyldb_Dn_FromDn(dn);
    1006        2611 :         talloc_free(dn);
    1007        2611 :         return ret;
    1008             : }
    1009             : 
    1010             : 
    1011     1439654 : static PyObject *py_dsdb_get_nc_root(PyObject *self, PyObject *args)
    1012             : {
    1013             :         struct ldb_context *ldb;
    1014             :         struct ldb_dn *dn, *nc_root;
    1015             :         PyObject *py_ldb, *py_ldb_dn, *py_nc_root;
    1016             :         int ret;
    1017             : 
    1018     1439654 :         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_ldb_dn))
    1019           0 :                 return NULL;
    1020             : 
    1021     1439654 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
    1022     1439654 :         PyErr_LDB_DN_OR_RAISE(py_ldb_dn, dn);
    1023             : 
    1024     1439654 :         ret = dsdb_find_nc_root(ldb, ldb, dn, &nc_root);
    1025     1439654 :         PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
    1026             : 
    1027     1439644 :         py_nc_root = pyldb_Dn_FromDn(nc_root);
    1028     1439644 :         talloc_unlink(ldb, nc_root);
    1029     1439644 :         return py_nc_root;
    1030             : }
    1031             : 
    1032      508359 : static PyObject *py_dsdb_get_wellknown_dn(PyObject *self, PyObject *args)
    1033             : {
    1034             :         struct ldb_context *ldb;
    1035             :         struct ldb_dn *nc_dn, *wk_dn;
    1036             :         char *wkguid;
    1037             :         PyObject *py_ldb, *py_nc_dn, *py_wk_dn;
    1038             :         int ret;
    1039             : 
    1040      508359 :         if (!PyArg_ParseTuple(args, "OOs", &py_ldb, &py_nc_dn, &wkguid))
    1041           0 :                 return NULL;
    1042             : 
    1043      508359 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
    1044      508359 :         PyErr_LDB_DN_OR_RAISE(py_nc_dn, nc_dn);
    1045             : 
    1046      508359 :         ret = dsdb_wellknown_dn(ldb, ldb, nc_dn, wkguid, &wk_dn);
    1047      508359 :         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
    1048      505752 :                 PyErr_Format(PyExc_KeyError, "Failed to find well known DN for GUID %s", wkguid);
    1049      505752 :                 return NULL;
    1050             :         }
    1051             : 
    1052        2607 :         PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
    1053             : 
    1054        2607 :         py_wk_dn = pyldb_Dn_FromDn(wk_dn);
    1055        2607 :         talloc_unlink(ldb, wk_dn);
    1056        2607 :         return py_wk_dn;
    1057             : }
    1058             : 
    1059             : 
    1060             : /*
    1061             :   call into samdb_rodc()
    1062             :  */
    1063         376 : static PyObject *py_dsdb_am_rodc(PyObject *self, PyObject *args)
    1064             : {
    1065             :         PyObject *py_ldb;
    1066             :         struct ldb_context *ldb;
    1067             :         int ret;
    1068             :         bool am_rodc;
    1069             : 
    1070         376 :         if (!PyArg_ParseTuple(args, "O", &py_ldb))
    1071           0 :                 return NULL;
    1072             : 
    1073         376 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
    1074             : 
    1075         376 :         ret = samdb_rodc(ldb, &am_rodc);
    1076         376 :         if (ret != LDB_SUCCESS) {
    1077           0 :                 PyErr_SetString(PyExc_RuntimeError, ldb_errstring(ldb));
    1078           0 :                 return NULL;
    1079             :         }
    1080             : 
    1081         376 :         return PyBool_FromLong(am_rodc);
    1082             : }
    1083             : 
    1084             : /*
    1085             :   call into samdb_is_pdc()
    1086             :  */
    1087         275 : static PyObject *py_dsdb_am_pdc(PyObject *self, PyObject *args)
    1088             : {
    1089             :         PyObject *py_ldb;
    1090             :         struct ldb_context *ldb;
    1091             :         bool am_pdc;
    1092             : 
    1093         275 :         if (!PyArg_ParseTuple(args, "O", &py_ldb))
    1094           0 :                 return NULL;
    1095             : 
    1096         275 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
    1097             : 
    1098         275 :         am_pdc = samdb_is_pdc(ldb);
    1099         275 :         return PyBool_FromLong(am_pdc);
    1100             : }
    1101             : 
    1102             : /*
    1103             :   call DSDB_EXTENDED_CREATE_OWN_RID_SET to get a new RID set for this server
    1104             :  */
    1105          39 : static PyObject *py_dsdb_create_own_rid_set(PyObject *self, PyObject *args)
    1106             : {
    1107             :         PyObject *py_ldb;
    1108             :         struct ldb_context *ldb;
    1109             :         int ret;
    1110             :         struct ldb_result *ext_res;
    1111             : 
    1112          39 :         if (!PyArg_ParseTuple(args, "O", &py_ldb))
    1113           0 :                 return NULL;
    1114             : 
    1115          39 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
    1116             : 
    1117             :         /*
    1118             :          * Run DSDB_EXTENDED_CREATE_OWN_RID_SET to get a RID set
    1119             :          */
    1120             : 
    1121          39 :         ret = ldb_extended(ldb, DSDB_EXTENDED_CREATE_OWN_RID_SET, NULL, &ext_res);
    1122             : 
    1123          39 :         PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
    1124             : 
    1125          38 :         TALLOC_FREE(ext_res);
    1126             : 
    1127          38 :         Py_RETURN_NONE;
    1128             : }
    1129             : 
    1130             : /*
    1131             :   call DSDB_EXTENDED_ALLOCATE_RID to get a new RID set for this server
    1132             :  */
    1133         995 : static PyObject *py_dsdb_allocate_rid(PyObject *self, PyObject *args)
    1134             : {
    1135             :         PyObject *py_ldb;
    1136             :         struct ldb_context *ldb;
    1137             :         int ret;
    1138             :         uint32_t rid;
    1139         995 :         struct ldb_result *ext_res = NULL;
    1140         995 :         struct dsdb_extended_allocate_rid *rid_return = NULL;
    1141         995 :         if (!PyArg_ParseTuple(args, "O", &py_ldb)) {
    1142           0 :                 return NULL;
    1143             :         }
    1144             : 
    1145         995 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
    1146             : 
    1147         995 :         rid_return = talloc_zero(ldb, struct dsdb_extended_allocate_rid);
    1148         995 :         if (rid_return == NULL) {
    1149           0 :                 return PyErr_NoMemory();
    1150             :         }
    1151             : 
    1152             :         /*
    1153             :          * Run DSDB_EXTENDED_ALLOCATE_RID to get a new RID
    1154             :          */
    1155             : 
    1156         995 :         ret = ldb_extended(ldb, DSDB_EXTENDED_ALLOCATE_RID, rid_return, &ext_res);
    1157         995 :         if (ret != LDB_SUCCESS) {
    1158           2 :                 TALLOC_FREE(rid_return);
    1159           2 :                 TALLOC_FREE(ext_res);
    1160           2 :                 PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
    1161             :         }
    1162             : 
    1163         993 :         rid = rid_return->rid;
    1164         993 :         TALLOC_FREE(rid_return);
    1165         993 :         TALLOC_FREE(ext_res);
    1166             : 
    1167         993 :         return PyLong_FromLong(rid);
    1168             : }
    1169             : 
    1170             : #ifdef AD_DC_BUILD_IS_ENABLED
    1171           8 : static PyObject *py_dns_delete_tombstones(PyObject *self, PyObject *args)
    1172             : {
    1173             :         PyObject *py_ldb;
    1174             :         NTSTATUS status;
    1175           8 :         struct ldb_context *ldb = NULL;
    1176           8 :         TALLOC_CTX *mem_ctx = NULL;
    1177           8 :         char *error_string = NULL;
    1178             : 
    1179           8 :         if (!PyArg_ParseTuple(args, "O", &py_ldb)) {
    1180           0 :                 return NULL;
    1181             :         }
    1182           8 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
    1183             : 
    1184           8 :         mem_ctx = talloc_new(ldb);
    1185           8 :         if (mem_ctx == NULL) {
    1186           0 :                 return PyErr_NoMemory();
    1187             :         }
    1188             : 
    1189           8 :         status = dns_delete_tombstones(mem_ctx, ldb, &error_string);
    1190             : 
    1191           8 :         if (!NT_STATUS_IS_OK(status)) {
    1192           0 :                 if (error_string) {
    1193           0 :                         PyErr_Format(PyExc_RuntimeError, "%s", error_string);
    1194             :                 } else {
    1195           0 :                         PyErr_SetNTSTATUS(status);
    1196             :                 }
    1197           0 :                 TALLOC_FREE(mem_ctx);
    1198           0 :                 return NULL;
    1199             :         }
    1200             : 
    1201           8 :         TALLOC_FREE(mem_ctx);
    1202           8 :         Py_RETURN_NONE;
    1203             : }
    1204             : 
    1205           4 : static PyObject *py_scavenge_dns_records(PyObject *self, PyObject *args)
    1206             : {
    1207             :         PyObject *py_ldb;
    1208             :         NTSTATUS status;
    1209           4 :         struct ldb_context *ldb = NULL;
    1210           4 :         TALLOC_CTX *mem_ctx = NULL;
    1211           4 :         char *error_string = NULL;
    1212             : 
    1213           4 :         if (!PyArg_ParseTuple(args, "O", &py_ldb)) {
    1214           0 :                 return NULL;
    1215             :         }
    1216           4 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
    1217             : 
    1218           4 :         mem_ctx = talloc_new(ldb);
    1219           4 :         if (mem_ctx == NULL) {
    1220           0 :                 return PyErr_NoMemory();
    1221             :         }
    1222             : 
    1223           4 :         status = dns_tombstone_records(mem_ctx, ldb, &error_string);
    1224             : 
    1225           4 :         if (!NT_STATUS_IS_OK(status)) {
    1226           0 :                 if (error_string) {
    1227           0 :                         PyErr_Format(PyExc_RuntimeError, "%s", error_string);
    1228             :                 } else {
    1229           0 :                         PyErr_SetNTSTATUS(status);
    1230             :                 }
    1231           0 :                 TALLOC_FREE(mem_ctx);
    1232           0 :                 return NULL;
    1233             :         }
    1234             : 
    1235           4 :         TALLOC_FREE(mem_ctx);
    1236           4 :         Py_RETURN_NONE;
    1237             : }
    1238             : 
    1239           4 : static PyObject *py_dsdb_garbage_collect_tombstones(PyObject *self, PyObject *args)
    1240             : {
    1241             :         PyObject *py_ldb, *py_list_dn;
    1242           4 :         struct ldb_context *ldb = NULL;
    1243             :         Py_ssize_t i;
    1244             :         Py_ssize_t length;
    1245           4 :         long long _current_time, _tombstone_lifetime = LLONG_MAX;
    1246             :         uint32_t tombstone_lifetime32;
    1247           4 :         struct dsdb_ldb_dn_list_node *part = NULL;
    1248             :         time_t current_time, tombstone_lifetime;
    1249           4 :         TALLOC_CTX *mem_ctx = NULL;
    1250             :         NTSTATUS status;
    1251           4 :         unsigned int num_objects_removed = 0;
    1252           4 :         unsigned int num_links_removed = 0;
    1253           4 :         char *error_string = NULL;
    1254             : 
    1255           4 :         if (!PyArg_ParseTuple(args, "OOL|L", &py_ldb,
    1256             :                               &py_list_dn, &_current_time, &_tombstone_lifetime)) {
    1257           0 :                 return NULL;
    1258             :         }
    1259             : 
    1260             : 
    1261           4 :         PyErr_LDB_OR_RAISE(py_ldb, ldb);
    1262             : 
    1263           4 :         mem_ctx = talloc_new(ldb);
    1264           4 :         if (mem_ctx == NULL) {
    1265           0 :                 return PyErr_NoMemory();
    1266             :         }
    1267             : 
    1268           4 :         current_time = _current_time;
    1269             : 
    1270           4 :         if (_tombstone_lifetime == LLONG_MAX) {
    1271           0 :                 int ret = dsdb_tombstone_lifetime(ldb, &tombstone_lifetime32);
    1272           0 :                 if (ret != LDB_SUCCESS) {
    1273           0 :                         PyErr_Format(PyExc_RuntimeError,
    1274             :                                      "Failed to get tombstone lifetime: %s",
    1275             :                                      ldb_errstring(ldb));
    1276           0 :                         TALLOC_FREE(mem_ctx);
    1277           0 :                         return NULL;
    1278             :                 }
    1279           0 :                 tombstone_lifetime = tombstone_lifetime32;
    1280             :         } else {
    1281           3 :                 tombstone_lifetime = _tombstone_lifetime;
    1282             :         }
    1283             : 
    1284           4 :         if (!PyList_Check(py_list_dn)) {
    1285           0 :                 PyErr_SetString(PyExc_TypeError, "A list of DNs were expected");
    1286           0 :                 TALLOC_FREE(mem_ctx);
    1287           0 :                 return NULL;
    1288             :         }
    1289             : 
    1290           4 :         length = PyList_GET_SIZE(py_list_dn);
    1291             : 
    1292          20 :         for (i = 0; i < length; i++) {
    1293          16 :                 const char *part_str = PyUnicode_AsUTF8(PyList_GetItem(py_list_dn, i));
    1294             :                 struct ldb_dn *p;
    1295             :                 struct dsdb_ldb_dn_list_node *node;
    1296             : 
    1297          16 :                 if (part_str == NULL) {
    1298           0 :                         TALLOC_FREE(mem_ctx);
    1299           0 :                         return PyErr_NoMemory();
    1300             :                 }
    1301             : 
    1302          16 :                 p = ldb_dn_new(mem_ctx, ldb, part_str);
    1303          16 :                 if (p == NULL) {
    1304           0 :                         PyErr_Format(PyExc_RuntimeError, "Failed to parse DN %s", part_str);
    1305           0 :                         TALLOC_FREE(mem_ctx);
    1306           0 :                         return NULL;
    1307             :                 }
    1308          16 :                 node = talloc_zero(mem_ctx, struct dsdb_ldb_dn_list_node);
    1309          16 :                 node->dn = p;
    1310             : 
    1311          16 :                 DLIST_ADD_END(part, node);
    1312             :         }
    1313             : 
    1314           4 :         status = dsdb_garbage_collect_tombstones(mem_ctx, ldb,
    1315             :                                                  part, current_time,
    1316             :                                                  tombstone_lifetime,
    1317             :                                                  &num_objects_removed,
    1318             :                                                  &num_links_removed,
    1319             :                                                  &error_string);
    1320             : 
    1321           4 :         if (!NT_STATUS_IS_OK(status)) {
    1322           0 :                 if (error_string) {
    1323           0 :                         PyErr_Format(PyExc_RuntimeError, "%s", error_string);
    1324             :                 } else {
    1325           0 :                         PyErr_SetNTSTATUS(status);
    1326             :                 }
    1327           0 :                 TALLOC_FREE(mem_ctx);
    1328           0 :                 return NULL;
    1329             :         }
    1330             : 
    1331           4 :         TALLOC_FREE(mem_ctx);
    1332             : 
    1333           4 :         return Py_BuildValue("(II)", num_objects_removed,
    1334             :                             num_links_removed);
    1335             : }
    1336             : #endif
    1337             : 
    1338         588 : static PyObject *py_dsdb_load_udv_v2(PyObject *self, PyObject *args)
    1339             : {
    1340             :         uint32_t count;
    1341             :         int ret, i;
    1342             :         bool ok;
    1343         588 :         PyObject *py_ldb = NULL, *py_dn = NULL, *pylist = NULL;
    1344         588 :         struct ldb_context *samdb = NULL;
    1345         588 :         struct ldb_dn *dn = NULL;
    1346         588 :         struct drsuapi_DsReplicaCursor2 *cursors = NULL;
    1347         588 :         TALLOC_CTX *tmp_ctx = NULL;
    1348             : 
    1349         588 :         if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_dn)) {
    1350           0 :                 return NULL;
    1351             :         }
    1352             : 
    1353         588 :         PyErr_LDB_OR_RAISE(py_ldb, samdb);
    1354             : 
    1355         588 :         tmp_ctx = talloc_new(samdb);
    1356         588 :         if (tmp_ctx == NULL) {
    1357           0 :                 return PyErr_NoMemory();
    1358             :         }
    1359             : 
    1360         588 :         ok = pyldb_Object_AsDn(tmp_ctx, py_dn, samdb, &dn);
    1361         588 :         if (!ok) {
    1362           0 :                 TALLOC_FREE(tmp_ctx);
    1363           0 :                 return NULL;
    1364             :         }
    1365             : 
    1366         588 :         ret = dsdb_load_udv_v2(samdb, dn, tmp_ctx, &cursors, &count);
    1367         588 :         if (ret != LDB_SUCCESS) {
    1368           0 :                 TALLOC_FREE(tmp_ctx);
    1369           0 :                 PyErr_SetString(PyExc_RuntimeError,
    1370             :                                 "Failed to load udv from ldb");
    1371           0 :                 return NULL;
    1372             :         }
    1373             : 
    1374         588 :         pylist = PyList_New(count);
    1375         588 :         if (pylist == NULL) {
    1376           0 :                 TALLOC_FREE(tmp_ctx);
    1377           0 :                 return PyErr_NoMemory();
    1378             :         }
    1379             : 
    1380        1566 :         for (i = 0; i < count; i++) {
    1381             :                 PyObject *py_cursor;
    1382             :                 struct drsuapi_DsReplicaCursor2 *cursor;
    1383         978 :                 cursor = talloc(tmp_ctx, struct drsuapi_DsReplicaCursor2);
    1384         978 :                 if (cursor == NULL) {
    1385           0 :                         TALLOC_FREE(tmp_ctx);
    1386           0 :                         return PyErr_NoMemory();
    1387             :                 }
    1388         978 :                 *cursor = cursors[i];
    1389             : 
    1390         978 :                 py_cursor = py_return_ndr_struct("samba.dcerpc.drsuapi",
    1391             :                                                  "DsReplicaCursor2",
    1392             :                                                  cursor, cursor);
    1393         978 :                 if (py_cursor == NULL) {
    1394           0 :                         TALLOC_FREE(tmp_ctx);
    1395           0 :                         return PyErr_NoMemory();
    1396             :                 }
    1397             : 
    1398         978 :                 PyList_SetItem(pylist, i, py_cursor);
    1399             :         }
    1400             : 
    1401         588 :         TALLOC_FREE(tmp_ctx);
    1402         588 :         return pylist;
    1403             : }
    1404             : 
    1405          65 : static PyObject *py_dsdb_user_account_control_flag_bit_to_string(PyObject *self, PyObject *args)
    1406             : {
    1407             :         const char *str;
    1408             :         long long uf;
    1409          65 :         if (!PyArg_ParseTuple(args, "L", &uf)) {
    1410           0 :                 return NULL;
    1411             :         }
    1412             : 
    1413          64 :         if (uf > UINT32_MAX) {
    1414           1 :                 return PyErr_Format(PyExc_OverflowError, "No UF_ flags are over UINT32_MAX");
    1415             :         }
    1416          63 :         if (uf < 0) {
    1417           0 :                 return PyErr_Format(PyExc_KeyError, "No UF_ flags are less then zero");
    1418             :         }
    1419             : 
    1420          63 :         str = dsdb_user_account_control_flag_bit_to_string(uf);
    1421          63 :         if (str == NULL) {
    1422           5 :                 return PyErr_Format(PyExc_KeyError,
    1423             :                                     "No such UF_ flag 0x%08x",
    1424             :                                     (unsigned int)uf);
    1425             :         }
    1426          58 :         return PyUnicode_FromString(str);
    1427             : }
    1428             : 
    1429             : static PyMethodDef py_dsdb_methods[] = {
    1430             :         { "_samdb_server_site_name", (PyCFunction)py_samdb_server_site_name,
    1431             :                 METH_VARARGS, "Get the server site name as a string"},
    1432             :         { "_dsdb_convert_schema_to_openldap",
    1433             :                 (PyCFunction)py_dsdb_convert_schema_to_openldap, METH_VARARGS, 
    1434             :                 "dsdb_convert_schema_to_openldap(ldb, target_str, mapping) -> str\n"
    1435             :                 "Create an OpenLDAP schema from a schema." },
    1436             :         { "_samdb_set_domain_sid", (PyCFunction)py_samdb_set_domain_sid,
    1437             :                 METH_VARARGS,
    1438             :                 "samdb_set_domain_sid(samdb, sid)\n"
    1439             :                 "Set SID of domain to use." },
    1440             :         { "_samdb_get_domain_sid", (PyCFunction)py_samdb_get_domain_sid,
    1441             :                 METH_VARARGS,
    1442             :                 "samdb_get_domain_sid(samdb)\n"
    1443             :                 "Get SID of domain in use." },
    1444             :         { "_samdb_ntds_invocation_id", (PyCFunction)py_samdb_ntds_invocation_id,
    1445             :                 METH_VARARGS, "get the NTDS invocation ID GUID as a string"},
    1446             :         { "_samdb_set_ntds_settings_dn", (PyCFunction)py_samdb_set_ntds_settings_dn,
    1447             :                 METH_VARARGS,
    1448             :                 "samdb_set_ntds_settings_dn(samdb, ntds_settings_dn)\n"
    1449             :                 "Set NTDS Settings DN for this LDB (allows it to be set before the DB fully exists)." },
    1450             :         { "_dsdb_get_oid_from_attid", (PyCFunction)py_dsdb_get_oid_from_attid,
    1451             :                 METH_VARARGS, NULL },
    1452             :         { "_dsdb_get_attid_from_lDAPDisplayName", (PyCFunction)py_dsdb_get_attid_from_lDAPDisplayName,
    1453             :                 METH_VARARGS, NULL },
    1454             :         { "_dsdb_get_syntax_oid_from_lDAPDisplayName", (PyCFunction)py_dsdb_get_syntax_oid_from_lDAPDisplayName,
    1455             :                 METH_VARARGS, NULL },
    1456             :         { "_dsdb_get_systemFlags_from_lDAPDisplayName", (PyCFunction)py_dsdb_get_systemFlags_from_lDAPDisplayName,
    1457             :                 METH_VARARGS, NULL },
    1458             :         { "_dsdb_get_linkId_from_lDAPDisplayName", (PyCFunction)py_dsdb_get_linkId_from_lDAPDisplayName,
    1459             :                 METH_VARARGS, NULL },
    1460             :         { "_dsdb_get_lDAPDisplayName_by_attid", (PyCFunction)py_dsdb_get_lDAPDisplayName_by_attid,
    1461             :                 METH_VARARGS, NULL },
    1462             :         { "_dsdb_get_backlink_from_lDAPDisplayName", (PyCFunction)py_dsdb_get_backlink_from_lDAPDisplayName,
    1463             :                 METH_VARARGS, NULL },
    1464             :         { "_dsdb_set_ntds_invocation_id",
    1465             :                 (PyCFunction)py_dsdb_set_ntds_invocation_id, METH_VARARGS,
    1466             :                 NULL },
    1467             :         { "_samdb_ntds_objectGUID", (PyCFunction)py_samdb_ntds_objectGUID,
    1468             :                 METH_VARARGS, "get the NTDS objectGUID as a string"},
    1469             :         { "_dsdb_set_global_schema", (PyCFunction)py_dsdb_set_global_schema,
    1470             :                 METH_VARARGS, NULL },
    1471             :         { "_dsdb_load_partition_usn", (PyCFunction)py_dsdb_load_partition_usn,
    1472             :                 METH_VARARGS,
    1473             :                 "get uSNHighest and uSNUrgent from the partition @REPLCHANGED"},
    1474             :         { "_dsdb_set_am_rodc",
    1475             :                 (PyCFunction)py_dsdb_set_am_rodc, METH_VARARGS,
    1476             :                 NULL },
    1477             :         { "_am_rodc",
    1478             :                 (PyCFunction)py_dsdb_am_rodc, METH_VARARGS,
    1479             :                 NULL },
    1480             :         { "_am_pdc",
    1481             :                 (PyCFunction)py_dsdb_am_pdc, METH_VARARGS,
    1482             :                 NULL },
    1483             :         { "_dsdb_set_schema_from_ldif", (PyCFunction)py_dsdb_set_schema_from_ldif, METH_VARARGS,
    1484             :                 NULL },
    1485             :         { "_dsdb_set_schema_from_ldb", (PyCFunction)py_dsdb_set_schema_from_ldb, METH_VARARGS,
    1486             :                 NULL },
    1487             :         { "_dsdb_write_prefixes_from_schema_to_ldb", (PyCFunction)py_dsdb_write_prefixes_from_schema_to_ldb, METH_VARARGS,
    1488             :                 NULL },
    1489             :         { "_dsdb_get_partitions_dn", (PyCFunction)py_dsdb_get_partitions_dn, METH_VARARGS, NULL },
    1490             :         { "_dsdb_get_nc_root", (PyCFunction)py_dsdb_get_nc_root, METH_VARARGS, NULL },
    1491             :         { "_dsdb_get_wellknown_dn", (PyCFunction)py_dsdb_get_wellknown_dn, METH_VARARGS, NULL },
    1492             :         { "_dsdb_DsReplicaAttribute", (PyCFunction)py_dsdb_DsReplicaAttribute, METH_VARARGS, NULL },
    1493             :         { "_dsdb_normalise_attributes", (PyCFunction)py_dsdb_normalise_attributes, METH_VARARGS, NULL },
    1494             : #ifdef AD_DC_BUILD_IS_ENABLED
    1495             :         { "_dsdb_garbage_collect_tombstones", (PyCFunction)py_dsdb_garbage_collect_tombstones, METH_VARARGS,
    1496             :                 "_dsdb_kcc_check_deleted(samdb, [dn], current_time, tombstone_lifetime)"
    1497             :                 " -> (num_objects_expunged, num_links_expunged)" },
    1498             :         { "_scavenge_dns_records", (PyCFunction)py_scavenge_dns_records,
    1499             :                 METH_VARARGS, NULL},
    1500             :         { "_dns_delete_tombstones", (PyCFunction)py_dns_delete_tombstones,
    1501             :                 METH_VARARGS, NULL},
    1502             : #endif
    1503             :         { "_dsdb_create_own_rid_set", (PyCFunction)py_dsdb_create_own_rid_set, METH_VARARGS,
    1504             :                 "_dsdb_create_own_rid_set(samdb)"
    1505             :                 " -> None" },
    1506             :         { "_dsdb_allocate_rid", (PyCFunction)py_dsdb_allocate_rid, METH_VARARGS,
    1507             :                 "_dsdb_allocate_rid(samdb)"
    1508             :                 " -> RID" },
    1509             :         { "_dsdb_load_udv_v2", (PyCFunction)py_dsdb_load_udv_v2, METH_VARARGS, NULL },
    1510             :         { "user_account_control_flag_bit_to_string",
    1511             :                 (PyCFunction)py_dsdb_user_account_control_flag_bit_to_string,
    1512             :                 METH_VARARGS,
    1513             :                 "user_account_control_flag_bit_to_string(bit)"
    1514             :                 " -> string name" },
    1515             :         {0}
    1516             : };
    1517             : 
    1518             : static struct PyModuleDef moduledef = {
    1519             :     PyModuleDef_HEAD_INIT,
    1520             :     .m_name = "dsdb",
    1521             :     .m_doc = "Python bindings for the directory service databases.",
    1522             :     .m_size = -1,
    1523             :     .m_methods = py_dsdb_methods,
    1524             : };
    1525             : 
    1526        4880 : MODULE_INIT_FUNC(dsdb)
    1527             : {
    1528             :         PyObject *m;
    1529             : 
    1530        4880 :         m = PyModule_Create(&moduledef);
    1531             : 
    1532        4880 :         if (m == NULL)
    1533           0 :                 return NULL;
    1534             : 
    1535             : #define ADD_DSDB_FLAG(val)  PyModule_AddObject(m, #val, PyLong_FromLong(val))
    1536             : 
    1537             :         /* "userAccountControl" flags */
    1538        4880 :         ADD_DSDB_FLAG(UF_NORMAL_ACCOUNT);
    1539        4880 :         ADD_DSDB_FLAG(UF_TEMP_DUPLICATE_ACCOUNT);
    1540        4880 :         ADD_DSDB_FLAG(UF_SERVER_TRUST_ACCOUNT);
    1541        4880 :         ADD_DSDB_FLAG(UF_WORKSTATION_TRUST_ACCOUNT);
    1542        4880 :         ADD_DSDB_FLAG(UF_INTERDOMAIN_TRUST_ACCOUNT);
    1543        4880 :         ADD_DSDB_FLAG(UF_PASSWD_NOTREQD);
    1544        4880 :         ADD_DSDB_FLAG(UF_ACCOUNTDISABLE);
    1545             : 
    1546        4880 :         ADD_DSDB_FLAG(UF_SCRIPT);
    1547        4880 :         ADD_DSDB_FLAG(UF_ACCOUNTDISABLE);
    1548        4880 :         ADD_DSDB_FLAG(UF_00000004);
    1549        4880 :         ADD_DSDB_FLAG(UF_HOMEDIR_REQUIRED);
    1550        4880 :         ADD_DSDB_FLAG(UF_LOCKOUT);
    1551        4880 :         ADD_DSDB_FLAG(UF_PASSWD_NOTREQD);
    1552        4880 :         ADD_DSDB_FLAG(UF_PASSWD_CANT_CHANGE);
    1553        4880 :         ADD_DSDB_FLAG(UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED);
    1554        4880 :         ADD_DSDB_FLAG(UF_TEMP_DUPLICATE_ACCOUNT);
    1555        4880 :         ADD_DSDB_FLAG(UF_NORMAL_ACCOUNT);
    1556        4880 :         ADD_DSDB_FLAG(UF_00000400);
    1557        4880 :         ADD_DSDB_FLAG(UF_INTERDOMAIN_TRUST_ACCOUNT);
    1558        4880 :         ADD_DSDB_FLAG(UF_WORKSTATION_TRUST_ACCOUNT);
    1559        4880 :         ADD_DSDB_FLAG(UF_SERVER_TRUST_ACCOUNT);
    1560        4880 :         ADD_DSDB_FLAG(UF_00004000);
    1561        4880 :         ADD_DSDB_FLAG(UF_00008000);
    1562        4880 :         ADD_DSDB_FLAG(UF_DONT_EXPIRE_PASSWD);
    1563        4880 :         ADD_DSDB_FLAG(UF_MNS_LOGON_ACCOUNT);
    1564        4880 :         ADD_DSDB_FLAG(UF_SMARTCARD_REQUIRED);
    1565        4880 :         ADD_DSDB_FLAG(UF_TRUSTED_FOR_DELEGATION);
    1566        4880 :         ADD_DSDB_FLAG(UF_NOT_DELEGATED);
    1567        4880 :         ADD_DSDB_FLAG(UF_USE_DES_KEY_ONLY);
    1568        4880 :         ADD_DSDB_FLAG(UF_DONT_REQUIRE_PREAUTH);
    1569        4880 :         ADD_DSDB_FLAG(UF_PASSWORD_EXPIRED);
    1570        4880 :         ADD_DSDB_FLAG(UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION);
    1571        4880 :         ADD_DSDB_FLAG(UF_NO_AUTH_DATA_REQUIRED);
    1572        4880 :         ADD_DSDB_FLAG(UF_PARTIAL_SECRETS_ACCOUNT);
    1573        4880 :         ADD_DSDB_FLAG(UF_USE_AES_KEYS);
    1574             : 
    1575             :         /* groupType flags */
    1576        4880 :         ADD_DSDB_FLAG(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP);
    1577        4880 :         ADD_DSDB_FLAG(GTYPE_SECURITY_GLOBAL_GROUP);
    1578        4880 :         ADD_DSDB_FLAG(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
    1579        4880 :         ADD_DSDB_FLAG(GTYPE_SECURITY_UNIVERSAL_GROUP);
    1580        4880 :         ADD_DSDB_FLAG(GTYPE_DISTRIBUTION_GLOBAL_GROUP);
    1581        4880 :         ADD_DSDB_FLAG(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP);
    1582        4880 :         ADD_DSDB_FLAG(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP);
    1583             : 
    1584             :         /* "sAMAccountType" flags */
    1585        4880 :         ADD_DSDB_FLAG(ATYPE_NORMAL_ACCOUNT);
    1586        4880 :         ADD_DSDB_FLAG(ATYPE_WORKSTATION_TRUST);
    1587        4880 :         ADD_DSDB_FLAG(ATYPE_INTERDOMAIN_TRUST);
    1588        4880 :         ADD_DSDB_FLAG(ATYPE_SECURITY_GLOBAL_GROUP);
    1589        4880 :         ADD_DSDB_FLAG(ATYPE_SECURITY_LOCAL_GROUP);
    1590        4880 :         ADD_DSDB_FLAG(ATYPE_SECURITY_UNIVERSAL_GROUP);
    1591        4880 :         ADD_DSDB_FLAG(ATYPE_DISTRIBUTION_GLOBAL_GROUP);
    1592        4880 :         ADD_DSDB_FLAG(ATYPE_DISTRIBUTION_LOCAL_GROUP);
    1593        4880 :         ADD_DSDB_FLAG(ATYPE_DISTRIBUTION_UNIVERSAL_GROUP);
    1594             : 
    1595             :         /* "domainFunctionality", "forestFunctionality" flags in the rootDSE */
    1596        4880 :         ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2000);
    1597        4880 :         ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2003_MIXED);
    1598        4880 :         ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2003);
    1599        4880 :         ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2008);
    1600        4880 :         ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2008_R2);
    1601        4880 :         ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2012);
    1602        4880 :         ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2012_R2);
    1603        4880 :         ADD_DSDB_FLAG(DS_DOMAIN_FUNCTION_2016);
    1604             : 
    1605             :         /* nc replica flags */
    1606        4880 :         ADD_DSDB_FLAG(INSTANCE_TYPE_IS_NC_HEAD);
    1607        4880 :         ADD_DSDB_FLAG(INSTANCE_TYPE_UNINSTANT);
    1608        4880 :         ADD_DSDB_FLAG(INSTANCE_TYPE_WRITE);
    1609        4880 :         ADD_DSDB_FLAG(INSTANCE_TYPE_NC_ABOVE);
    1610        4880 :         ADD_DSDB_FLAG(INSTANCE_TYPE_NC_COMING);
    1611        4880 :         ADD_DSDB_FLAG(INSTANCE_TYPE_NC_GOING);
    1612             : 
    1613             :         /* "systemFlags" */
    1614        4880 :         ADD_DSDB_FLAG(SYSTEM_FLAG_CR_NTDS_NC);
    1615        4880 :         ADD_DSDB_FLAG(SYSTEM_FLAG_CR_NTDS_DOMAIN);
    1616        4880 :         ADD_DSDB_FLAG(SYSTEM_FLAG_CR_NTDS_NOT_GC_REPLICATED);
    1617        4880 :         ADD_DSDB_FLAG(SYSTEM_FLAG_SCHEMA_BASE_OBJECT);
    1618        4880 :         ADD_DSDB_FLAG(SYSTEM_FLAG_ATTR_IS_RDN);
    1619        4880 :         ADD_DSDB_FLAG(SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
    1620        4880 :         ADD_DSDB_FLAG(SYSTEM_FLAG_DOMAIN_DISALLOW_MOVE);
    1621        4880 :         ADD_DSDB_FLAG(SYSTEM_FLAG_DOMAIN_DISALLOW_RENAME);
    1622        4880 :         ADD_DSDB_FLAG(SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE);
    1623        4880 :         ADD_DSDB_FLAG(SYSTEM_FLAG_CONFIG_ALLOW_MOVE);
    1624        4880 :         ADD_DSDB_FLAG(SYSTEM_FLAG_CONFIG_ALLOW_RENAME);
    1625        4880 :         ADD_DSDB_FLAG(SYSTEM_FLAG_DISALLOW_DELETE);
    1626             : 
    1627             :         /* Kerberos encryption type constants */
    1628        4880 :         ADD_DSDB_FLAG(ENC_ALL_TYPES);
    1629        4880 :         ADD_DSDB_FLAG(ENC_CRC32);
    1630        4880 :         ADD_DSDB_FLAG(ENC_RSA_MD5);
    1631        4880 :         ADD_DSDB_FLAG(ENC_RC4_HMAC_MD5);
    1632        4880 :         ADD_DSDB_FLAG(ENC_HMAC_SHA1_96_AES128);
    1633        4880 :         ADD_DSDB_FLAG(ENC_HMAC_SHA1_96_AES256);
    1634             : 
    1635        4880 :         ADD_DSDB_FLAG(SEARCH_FLAG_ATTINDEX);
    1636        4880 :         ADD_DSDB_FLAG(SEARCH_FLAG_PDNTATTINDEX);
    1637        4880 :         ADD_DSDB_FLAG(SEARCH_FLAG_ANR);
    1638        4880 :         ADD_DSDB_FLAG(SEARCH_FLAG_PRESERVEONDELETE);
    1639        4880 :         ADD_DSDB_FLAG(SEARCH_FLAG_COPY);
    1640        4880 :         ADD_DSDB_FLAG(SEARCH_FLAG_TUPLEINDEX);
    1641        4880 :         ADD_DSDB_FLAG(SEARCH_FLAG_SUBTREEATTRINDEX);
    1642        4880 :         ADD_DSDB_FLAG(SEARCH_FLAG_CONFIDENTIAL);
    1643        4880 :         ADD_DSDB_FLAG(SEARCH_FLAG_NEVERVALUEAUDIT);
    1644        4880 :         ADD_DSDB_FLAG(SEARCH_FLAG_RODC_ATTRIBUTE);
    1645             : 
    1646        4880 :         ADD_DSDB_FLAG(DS_FLAG_ATTR_NOT_REPLICATED);
    1647        4880 :         ADD_DSDB_FLAG(DS_FLAG_ATTR_REQ_PARTIAL_SET_MEMBER);
    1648        4880 :         ADD_DSDB_FLAG(DS_FLAG_ATTR_IS_CONSTRUCTED);
    1649             : 
    1650        4880 :         ADD_DSDB_FLAG(DS_NTDSSETTINGS_OPT_IS_AUTO_TOPOLOGY_DISABLED);
    1651        4880 :         ADD_DSDB_FLAG(DS_NTDSSETTINGS_OPT_IS_TOPL_CLEANUP_DISABLED);
    1652        4880 :         ADD_DSDB_FLAG(DS_NTDSSETTINGS_OPT_IS_TOPL_MIN_HOPS_DISABLED);
    1653        4880 :         ADD_DSDB_FLAG(DS_NTDSSETTINGS_OPT_IS_TOPL_DETECT_STALE_DISABLED);
    1654        4880 :         ADD_DSDB_FLAG(DS_NTDSSETTINGS_OPT_IS_INTER_SITE_AUTO_TOPOLOGY_DISABLED);
    1655        4880 :         ADD_DSDB_FLAG(DS_NTDSSETTINGS_OPT_IS_GROUP_CACHING_ENABLED);
    1656        4880 :         ADD_DSDB_FLAG(DS_NTDSSETTINGS_OPT_FORCE_KCC_WHISTLER_BEHAVIOR);
    1657        4880 :         ADD_DSDB_FLAG(DS_NTDSSETTINGS_OPT_IS_RAND_BH_SELECTION_DISABLED);
    1658        4880 :         ADD_DSDB_FLAG(DS_NTDSSETTINGS_OPT_IS_SCHEDULE_HASHING_ENABLED);
    1659        4880 :         ADD_DSDB_FLAG(DS_NTDSSETTINGS_OPT_IS_REDUNDANT_SERVER_TOPOLOGY_ENABLED);
    1660             : 
    1661        4880 :         ADD_DSDB_FLAG(DS_NTDSDSA_OPT_IS_GC);
    1662        4880 :         ADD_DSDB_FLAG(DS_NTDSDSA_OPT_DISABLE_INBOUND_REPL);
    1663        4880 :         ADD_DSDB_FLAG(DS_NTDSDSA_OPT_DISABLE_OUTBOUND_REPL);
    1664        4880 :         ADD_DSDB_FLAG(DS_NTDSDSA_OPT_DISABLE_NTDSCONN_XLATE);
    1665        4880 :         ADD_DSDB_FLAG(DS_NTDSDSA_OPT_DISABLE_SPN_REGISTRATION);
    1666             : 
    1667        4880 :         ADD_DSDB_FLAG(NTDSCONN_KCC_GC_TOPOLOGY);
    1668        4880 :         ADD_DSDB_FLAG(NTDSCONN_KCC_RING_TOPOLOGY);
    1669        4880 :         ADD_DSDB_FLAG(NTDSCONN_KCC_MINIMIZE_HOPS_TOPOLOGY);
    1670        4880 :         ADD_DSDB_FLAG(NTDSCONN_KCC_STALE_SERVERS_TOPOLOGY);
    1671        4880 :         ADD_DSDB_FLAG(NTDSCONN_KCC_OSCILLATING_CONNECTION_TOPOLOGY);
    1672        4880 :         ADD_DSDB_FLAG(NTDSCONN_KCC_INTERSITE_GC_TOPOLOGY);
    1673        4880 :         ADD_DSDB_FLAG(NTDSCONN_KCC_INTERSITE_TOPOLOGY);
    1674        4880 :         ADD_DSDB_FLAG(NTDSCONN_KCC_SERVER_FAILOVER_TOPOLOGY);
    1675        4880 :         ADD_DSDB_FLAG(NTDSCONN_KCC_SITE_FAILOVER_TOPOLOGY);
    1676        4880 :         ADD_DSDB_FLAG(NTDSCONN_KCC_REDUNDANT_SERVER_TOPOLOGY);
    1677             : 
    1678        4880 :         ADD_DSDB_FLAG(NTDSCONN_OPT_IS_GENERATED);
    1679        4880 :         ADD_DSDB_FLAG(NTDSCONN_OPT_TWOWAY_SYNC);
    1680        4880 :         ADD_DSDB_FLAG(NTDSCONN_OPT_OVERRIDE_NOTIFY_DEFAULT);
    1681        4880 :         ADD_DSDB_FLAG(NTDSCONN_OPT_USE_NOTIFY);
    1682        4880 :         ADD_DSDB_FLAG(NTDSCONN_OPT_DISABLE_INTERSITE_COMPRESSION);
    1683        4880 :         ADD_DSDB_FLAG(NTDSCONN_OPT_USER_OWNED_SCHEDULE);
    1684        4880 :         ADD_DSDB_FLAG(NTDSCONN_OPT_RODC_TOPOLOGY);
    1685             : 
    1686             :         /* Site Link Object options */
    1687        4880 :         ADD_DSDB_FLAG(NTDSSITELINK_OPT_USE_NOTIFY);
    1688        4880 :         ADD_DSDB_FLAG(NTDSSITELINK_OPT_TWOWAY_SYNC);
    1689        4880 :         ADD_DSDB_FLAG(NTDSSITELINK_OPT_DISABLE_COMPRESSION);
    1690             : 
    1691             :         /* GPO policy flags */
    1692        4880 :         ADD_DSDB_FLAG(GPLINK_OPT_DISABLE);
    1693        4880 :         ADD_DSDB_FLAG(GPLINK_OPT_ENFORCE);
    1694        4880 :         ADD_DSDB_FLAG(GPO_FLAG_USER_DISABLE);
    1695        4880 :         ADD_DSDB_FLAG(GPO_FLAG_MACHINE_DISABLE);
    1696        4880 :         ADD_DSDB_FLAG(GPO_INHERIT);
    1697        4880 :         ADD_DSDB_FLAG(GPO_BLOCK_INHERITANCE);
    1698             : 
    1699             : #define ADD_DSDB_STRING(val)  PyModule_AddObject(m, #val, PyUnicode_FromString(val))
    1700             : 
    1701        4880 :         ADD_DSDB_STRING(DSDB_SYNTAX_BINARY_DN);
    1702        4880 :         ADD_DSDB_STRING(DSDB_SYNTAX_STRING_DN);
    1703        4880 :         ADD_DSDB_STRING(DSDB_SYNTAX_OR_NAME);
    1704        4880 :         ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK);
    1705        4880 :         ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA);
    1706        4880 :         ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_FIX_DUPLICATE_LINKS);
    1707        4880 :         ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME);
    1708        4880 :         ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID);
    1709        4880 :         ADD_DSDB_STRING(DSDB_CONTROL_REPLMD_VANISH_LINKS);
    1710        4880 :         ADD_DSDB_STRING(DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID);
    1711        4880 :         ADD_DSDB_STRING(DSDB_CONTROL_SKIP_DUPLICATES_CHECK_OID);
    1712        4880 :         ADD_DSDB_STRING(DSDB_CONTROL_BYPASS_PASSWORD_HASH_OID);
    1713        4880 :         ADD_DSDB_STRING(DSDB_CONTROL_INVALID_NOT_IMPLEMENTED);
    1714             : 
    1715        4880 :         ADD_DSDB_STRING(DS_GUID_COMPUTERS_CONTAINER);
    1716        4880 :         ADD_DSDB_STRING(DS_GUID_DELETED_OBJECTS_CONTAINER);
    1717        4880 :         ADD_DSDB_STRING(DS_GUID_DOMAIN_CONTROLLERS_CONTAINER);
    1718        4880 :         ADD_DSDB_STRING(DS_GUID_FOREIGNSECURITYPRINCIPALS_CONTAINER);
    1719        4880 :         ADD_DSDB_STRING(DS_GUID_INFRASTRUCTURE_CONTAINER);
    1720        4880 :         ADD_DSDB_STRING(DS_GUID_LOSTANDFOUND_CONTAINER);
    1721        4880 :         ADD_DSDB_STRING(DS_GUID_MICROSOFT_PROGRAM_DATA_CONTAINER);
    1722        4880 :         ADD_DSDB_STRING(DS_GUID_NTDS_QUOTAS_CONTAINER);
    1723        4880 :         ADD_DSDB_STRING(DS_GUID_PROGRAM_DATA_CONTAINER);
    1724        4880 :         ADD_DSDB_STRING(DS_GUID_SYSTEMS_CONTAINER);
    1725        4880 :         ADD_DSDB_STRING(DS_GUID_USERS_CONTAINER);
    1726             : 
    1727        4880 :         return m;
    1728             : }

Generated by: LCOV version 1.13