[SCM] Samba Shared Repository - branch master updated

Garming Sam garming at samba.org
Fri Nov 4 07:38:03 UTC 2016


The branch, master has been updated
       via  815658d samba_tool/fsmo: Allocate RID Set when seizing RID manager
       via  2a49c74 python-libnet: Use new NTSTATUSError, WERRORError and DsExtendedError exceptions
       via  e51256c python: Add DsExtendedError Exception
       via  e737171 pyerrors: Add PyErr_Set{WERROR,HRESULT,NTSTATUS}_and_string()
       via  c8505c5 python: create NTSTATUSError, HRESULTError and WERRORError
       via  f72da5b dsdb: Catch errors in extended operations (like allocating a RID Set)
       via  46fefb2 dsdb: Rework DSDB code to use WERROR
       via  fe90dad dsdb: Create RID Set as SYSTEM
       via  09537a6 dbcheck: Correctly initialise keep_transaction in missing_parent test
       via  7fd5be5 dbcheck: confirm RID Set presence and consistency
       via  035df7a dsdb: Add python hooks to allocate a RID set and allocate a RID pool
       via  1b40bb6 tests/ridalloc_exop: Add a new suite of tests for RID allocation
      from  9c6f0dc ctdb-scripts: Fix calculation of CTDB_BASE

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 815658d2db46e4accdd35f5925585ec1f1c3d74f
Author: Garming Sam <garming at catalyst.net.nz>
Date:   Tue Nov 1 16:29:53 2016 +1300

    samba_tool/fsmo: Allocate RID Set when seizing RID manager
    
    Seizing the role without allocating a RID set for itself is likely prone
    to cause issues.
    
    Pair-programmed-with: Clive Ferreira <cliveferreira at catalyst.net.nz>
    
    Signed-off-by: Clive Ferreira <cliveferreira at catalyst.net.nz>
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=9954
    
    Autobuild-User(master): Garming Sam <garming at samba.org>
    Autobuild-Date(master): Fri Nov  4 08:37:05 CET 2016 on sn-devel-144

commit 2a49c7451949d42e5a4d6fce3ce607f05f9e7b71
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Nov 1 12:38:48 2016 +1300

    python-libnet: Use new NTSTATUSError, WERRORError and DsExtendedError exceptions
    
    This will allow callers to catch specific errors rather than RuntimeException
    
    As this slightly changes the exception, the timecmd test must be updated.
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12398

commit e51256c7d58040eeee02fc189b55afbc58379f81
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Nov 1 16:09:20 2016 +1300

    python: Add DsExtendedError Exception
    
    This will be used for checking errors during a GetNCChanges EXOP like
    RID Set allocation.
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12398

commit e737171f6ef172de559b41d54989eca0d7663b4e
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Nov 1 16:03:09 2016 +1300

    pyerrors: Add PyErr_Set{WERROR,HRESULT,NTSTATUS}_and_string()
    
    This varient allows control of the text explaination string
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12398

commit c8505c53da3e21f31454f121efd5961d95349a38
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Nov 1 15:23:58 2016 +1300

    python: create NTSTATUSError, HRESULTError and WERRORError
    
    The advantage of these over the previous use of just RuntimeError is that we can
    catch just the errors we want, without having to catch all possible RuntimeError
    cases and assume they decode to a tuple
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12398

commit f72da5ba51ae8bf9f3f54bed36b4572cd1b57adb
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Mon Oct 31 16:25:51 2016 +1300

    dsdb: Catch errors in extended operations (like allocating a RID Set)
    
    There are cases where allocating a RID Set can reasonably fail.  Catch those nicely.
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12398

commit 46fefb251f61b274cb687f6d1cb0a0a97fb36b44
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Mon Oct 31 16:19:37 2016 +1300

    dsdb: Rework DSDB code to use WERROR
    
    The WERROR codes are more descriptive for DSDB issues, and almost all the code was
    converting from WERROR to NTSTATUS.  This will allow us to better catch specific
    errors like WERR_DS_DRA_MISSING_PARENT
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=12398

commit fe90dadd2cd13c20484c06318724c592e5cf298e
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Mon Oct 31 10:41:39 2016 +1300

    dsdb: Create RID Set as SYSTEM
    
    We do not want random users with add-user rights to own the new RID Set for this
    server, and the ridSet class is thankfully system-only.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=9954
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>

commit 09537a67b0e761c834fb7c14d7e8d55e07fc5156
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Nov 3 13:30:56 2016 +1300

    dbcheck: Correctly initialise keep_transaction in missing_parent test
    
    Otherwise there is no point to this variable, we are trying to work out
    if the subsequent modify succeded
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=9954

commit 7fd5be535ade5ed119d869c8f215aa605aba2125
Author: Clive Ferreira <cliveferreira at catalyst.net.nz>
Date:   Thu Oct 27 17:28:01 2016 +1300

    dbcheck: confirm RID Set presence and consistency
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=9954

commit 035df7adbe9cc119324275275c2605433f6c4292
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Oct 28 16:08:57 2016 +1300

    dsdb: Add python hooks to allocate a RID set and allocate a RID pool
    
    This will help us to correct errors during dbcheck
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=9954

commit 1b40bb69d101b767ee453c96234cc6d573142ab3
Author: Garming Sam <garming at catalyst.net.nz>
Date:   Mon Oct 31 15:24:49 2016 +1300

    tests/ridalloc_exop: Add a new suite of tests for RID allocation
    
    This moves some tests from getnc_exop.py regarding RID sets as well as
    adding new tests for actions on join.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=9954
    
    Pair-programmed-with: Clive Ferreira <cliveferreira at catalyst.net.nz>
    
    Signed-off-by: Andrew Bartlett <abartlet at samaba.org>
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Signed-off-by: Clive Ferreira <cliveferreira at catalyst.net.nz>
    
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 python/pyglue.c                             |  28 ++
 python/samba/__init__.py                    |   5 +
 python/samba/dbchecker.py                   | 134 +++++-
 python/samba/netcmd/fsmo.py                 |  29 +-
 python/samba/samdb.py                       |   8 +
 python/samba/tests/samba_tool/timecmd.py    |   2 +-
 selftest/knownfail                          |   4 +
 source4/dsdb/pydsdb.c                       |  74 +++
 source4/dsdb/samdb/ldb_modules/ridalloc.c   |  20 +-
 source4/dsdb/samdb/ldb_modules/samldb.c     |  51 ++
 source4/dsdb/samdb/samdb.h                  |  10 +
 source4/libcli/util/pyerrors.h              |  30 +-
 source4/libnet/libnet_become_dc.c           |   8 +-
 source4/libnet/libnet_become_dc.h           |  16 +-
 source4/libnet/libnet_vampire.c             | 125 ++---
 source4/libnet/py_net.c                     | 143 +++++-
 source4/selftest/tests.py                   |  11 +-
 source4/setup/schema_samba4.ldif            |   2 +
 source4/torture/drs/python/getnc_exop.py    | 161 -------
 source4/torture/drs/python/ridalloc_exop.py | 714 ++++++++++++++++++++++++++++
 20 files changed, 1316 insertions(+), 259 deletions(-)
 create mode 100644 source4/torture/drs/python/ridalloc_exop.py


Changeset truncated at 500 lines:

diff --git a/python/pyglue.c b/python/pyglue.c
index 81244a2..dbe7eb4 100644
--- a/python/pyglue.c
+++ b/python/pyglue.c
@@ -24,6 +24,10 @@
 #include "lib/socket/netif.h"
 
 void init_glue(void);
+static PyObject *PyExc_NTSTATUSError;
+static PyObject *PyExc_WERRORError;
+static PyObject *PyExc_HRESULTError;
+static PyObject *PyExc_DsExtendedError;
 
 static PyObject *py_generate_random_str(PyObject *self, PyObject *args)
 {
@@ -294,5 +298,29 @@ void init_glue(void)
 
 	PyModule_AddObject(m, "version",
 					   PyString_FromString(SAMBA_VERSION_STRING));
+	PyExc_NTSTATUSError = PyErr_NewException(discard_const_p(char, "samba.NTSTATUSError"), PyExc_RuntimeError, NULL);
+	if (PyExc_NTSTATUSError != NULL) {
+		Py_INCREF(PyExc_NTSTATUSError);
+		PyModule_AddObject(m, "NTSTATUSError", PyExc_NTSTATUSError);
+	}
+
+	PyExc_WERRORError = PyErr_NewException(discard_const_p(char, "samba.WERRORError"), PyExc_RuntimeError, NULL);
+	if (PyExc_WERRORError != NULL) {
+		Py_INCREF(PyExc_WERRORError);
+		PyModule_AddObject(m, "WERRORError", PyExc_WERRORError);
+	}
+
+	PyExc_HRESULTError = PyErr_NewException(discard_const_p(char, "samba.HRESULTError"), PyExc_RuntimeError, NULL);
+	if (PyExc_HRESULTError != NULL) {
+		Py_INCREF(PyExc_HRESULTError);
+		PyModule_AddObject(m, "HRESULTError", PyExc_HRESULTError);
+	}
+
+	PyExc_DsExtendedError = PyErr_NewException(discard_const_p(char, "samba.DsExtendedError"), PyExc_RuntimeError, NULL);
+	if (PyExc_DsExtendedError != NULL) {
+		Py_INCREF(PyExc_DsExtendedError);
+		PyModule_AddObject(m, "DsExtendedError", PyExc_DsExtendedError);
+	}
+
 }
 
diff --git a/python/samba/__init__.py b/python/samba/__init__.py
index 7cfbc4c..5f91531 100644
--- a/python/samba/__init__.py
+++ b/python/samba/__init__.py
@@ -399,3 +399,8 @@ generate_random_password = _glue.generate_random_password
 strcasecmp_m = _glue.strcasecmp_m
 strstr_m = _glue.strstr_m
 is_ntvfs_fileserver_built = _glue.is_ntvfs_fileserver_built
+
+NTSTATUSError = _glue.NTSTATUSError
+HRESULTError = _glue.HRESULTError
+WERRORError = _glue.WERRORError
+DsExtendedError = _glue.DsExtendedError
diff --git a/python/samba/dbchecker.py b/python/samba/dbchecker.py
index 9b0784b..294c320 100644
--- a/python/samba/dbchecker.py
+++ b/python/samba/dbchecker.py
@@ -32,6 +32,7 @@ from samba.dcerpc import security
 from samba.descriptor import get_wellknown_sds, get_diff_sds
 from samba.auth import system_session, admin_session
 from samba.netcmd import CommandError
+from samba.netcmd.fsmo import get_fsmo_roleowner
 
 
 class dbcheck(object):
@@ -79,6 +80,7 @@ class dbcheck(object):
         self.fix_base64_userparameters = False
         self.fix_utf8_userparameters = False
         self.fix_doubled_userparameters = False
+        self.fix_sid_rid_set_conflict = False
         self.reset_well_known_acls = reset_well_known_acls
         self.reset_all_well_known_acls = False
         self.in_transaction = in_transaction
@@ -92,6 +94,7 @@ class dbcheck(object):
         self.fix_all_missing_objectclass = False
         self.fix_missing_deleted_objects = False
         self.fix_replica_locations = False
+        self.fix_missing_rid_set_master = False
 
         self.dn_set = set()
         self.link_id_cache = {}
@@ -157,6 +160,27 @@ class dbcheck(object):
         if len(forest) == 1:
             self.dns_partitions.append((ldb.Dn(self.samdb, domaindns_zone), forest[0]))
 
+        fsmo_dn = ldb.Dn(self.samdb, "CN=RID Manager$,CN=System," + self.samdb.domain_dn())
+        rid_master = get_fsmo_roleowner(self.samdb, fsmo_dn, "rid")
+        if ldb.Dn(self.samdb, self.samdb.get_dsServiceName()) == rid_master:
+            self.is_rid_master = True
+        else:
+            self.is_rid_master = False
+
+        # To get your rid set
+        # 1. Get server name
+        res = self.samdb.search(base=ldb.Dn(self.samdb, self.samdb.get_serverName()),
+                                scope=ldb.SCOPE_BASE, attrs=["serverReference"])
+        # 2. Get server reference
+        self.server_ref_dn = ldb.Dn(self.samdb, res[0]['serverReference'][0])
+
+        # 3. Get RID Set
+        res = self.samdb.search(base=self.server_ref_dn,
+                                scope=ldb.SCOPE_BASE, attrs=['rIDSetReferences'])
+        if "rIDSetReferences" in res[0]:
+            self.rid_set_dn = ldb.Dn(self.samdb, res[0]['rIDSetReferences'][0])
+        else:
+            self.rid_set_dn = None
 
     def check_database(self, DN=None, scope=ldb.SCOPE_SUBTREE, controls=[], attrs=['*']):
         '''perform a database check, returning the number of errors found'''
@@ -658,7 +682,7 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base)))
             self.report('Not moving object %s into LostAndFound' % (obj.dn))
             return
 
-        keep_transaction = True
+        keep_transaction = False
         self.samdb.transaction_start()
         try:
             nc_root = self.samdb.get_nc_root(obj.dn);
@@ -1847,6 +1871,114 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base)))
                     self.err_replica_locations(obj, msg.dn, location)
                     error_count += 1
 
+        if dn == self.server_ref_dn:
+            # Check we have a valid RID Set
+            if "*" in attrs or "rIDSetReferences" in attrs:
+                if "rIDSetReferences" not in obj:
+                    # NO RID SET reference
+                    # We are RID master, allocate it.
+                    error_count += 1
+
+                    if self.is_rid_master:
+                        # Allocate a RID Set
+                        if self.confirm_all('Allocate the missing RID set for RID master?',
+                                            'fix_missing_rid_set_master'):
+
+                            # We don't have auto-transaction logic on
+                            # extended operations, so we have to do it
+                            # here.
+
+                            self.samdb.transaction_start()
+
+                            try:
+                                self.samdb.create_own_rid_set()
+
+                            except:
+                                self.samdb.transaction_cancel()
+                                raise
+
+                            self.samdb.transaction_commit()
+
+
+                    elif not self.samdb.am_rodc():
+                        self.report("No RID Set found for this server: %s, and we are not the RID Master (so can not self-allocate)" % dn)
+
+
+        # Check some details of our own RID Set
+        if dn == self.rid_set_dn:
+            res = self.samdb.search(base=self.rid_set_dn, scope=ldb.SCOPE_BASE,
+                                    attrs=["rIDAllocationPool",
+                                           "rIDPreviousAllocationPool",
+                                           "rIDUsedPool",
+                                           "rIDNextRID"])
+            if "rIDAllocationPool" not in res[0]:
+                self.report("No rIDAllocationPool found in %s" % dn)
+                error_count += 1
+            else:
+                next_pool = int(res[0]["rIDAllocationPool"][0])
+
+                high = (0xFFFFFFFF00000000 & next_pool) >> 32
+                low = 0x00000000FFFFFFFF & next_pool
+
+                if high <= low:
+                    self.report("Invalid RID set %d-%s, %d > %d!" % (low, high, low, high))
+                    error_count += 1
+
+                if "rIDNextRID" in res[0]:
+                    next_free_rid = int(res[0]["rIDNextRID"][0])
+                else:
+                    next_free_rid = 0
+
+                if next_free_rid == 0:
+                    next_free_rid = low
+                else:
+                    next_free_rid += 1
+
+                # Check the remainder of this pool for conflicts.  If
+                # ridalloc_allocate_rid() moves to a new pool, this
+                # will be above high, so we will stop.
+                while next_free_rid <= high:
+                    sid = "%s-%d" % (self.samdb.get_domain_sid(), next_free_rid)
+                    try:
+                        res = self.samdb.search(base="<SID=%s>" % sid, scope=ldb.SCOPE_BASE,
+                                                attrs=[])
+                    except ldb.LdbError, (enum, estr):
+                        if enum != ldb.ERR_NO_SUCH_OBJECT:
+                            raise
+                        res = None
+                    if res is not None:
+                        self.report("SID %s for %s conflicts with our current RID set in %s" % (sid, res[0].dn, dn))
+                        error_count += 1
+
+                        if self.confirm_all('Fix conflict between SID %s and RID pool in %s by allocating a new RID?'
+                                            % (sid, dn),
+                                            'fix_sid_rid_set_conflict'):
+                            self.samdb.transaction_start()
+
+                            # This will burn RIDs, which will move
+                            # past the conflict.  We then check again
+                            # to see if the new RID conflicts, until
+                            # the end of the current pool.  We don't
+                            # look at the next pool to avoid burning
+                            # all RIDs in one go in some strange
+                            # failure case.
+                            try:
+                                while True:
+                                    allocated_rid = self.samdb.allocate_rid()
+                                    if allocated_rid >= next_free_rid:
+                                        next_free_rid = allocated_rid + 1
+                                        break
+                            except:
+                                self.samdb.transaction_cancel()
+                                raise
+
+                            self.samdb.transaction_commit()
+                        else:
+                            break
+                    else:
+                        next_free_rid += 1
+
+
         return error_count
 
     ################################################################
diff --git a/python/samba/netcmd/fsmo.py b/python/samba/netcmd/fsmo.py
index 1351654..62b3e43 100644
--- a/python/samba/netcmd/fsmo.py
+++ b/python/samba/netcmd/fsmo.py
@@ -295,12 +295,37 @@ You must provide an Admin user and password."""),
             m["fSMORoleOwner"]= ldb.MessageElement(
                 serviceName, ldb.FLAG_MOD_REPLACE,
                 "fSMORoleOwner")
+
+            samdb.transaction_start()
             try:
                 samdb.modify(m)
+                if role == "rid":
+                    # We may need to allocate the initial RID Set
+                    samdb.create_own_rid_set()
+
             except LdbError, (num, msg):
-                raise CommandError("Failed to seize '%s' role: %s" %
-                                   (role, msg))
+                if role == "rid" and num == ldb.ERR_ENTRY_ALREADY_EXISTS:
+
+                    # Try again without the RID Set allocation
+                    # (normal).  We have to manage the transaction as
+                    # we do not have nested transactions and creating
+                    # a RID set touches multiple objects. :-(
+                    samdb.transaction_cancel()
+                    samdb.transaction_start()
+                    try:
+                        samdb.modify(m)
+                    except LdbError, (num, msg):
+                        samdb.transaction_cancel()
+                        raise CommandError("Failed to seize '%s' role: %s" %
+                                           (role, msg))
+
+                else:
+                    samdb.transaction_cancel()
+                    raise CommandError("Failed to seize '%s' role: %s" %
+                                       (role, msg))
+            samdb.transaction_commit()
             self.outf.write("FSMO seize of '%s' role successful\n" % role)
+
             return True
 
     def seize_dns_role(self, role, samdb, credopts, sambaopts,
diff --git a/python/samba/samdb.py b/python/samba/samdb.py
index 3d7ea3e..eabe363 100644
--- a/python/samba/samdb.py
+++ b/python/samba/samdb.py
@@ -963,3 +963,11 @@ accountExpires: %u
             return dsdb._dsdb_garbage_collect_tombstones(self, dn,
                                                          current_time,
                                                          tombstone_lifetime)
+
+    def create_own_rid_set(self):
+        '''create a RID set for this DSA'''
+        return dsdb._dsdb_create_own_rid_set(self)
+
+    def allocate_rid(self):
+        '''return a new RID from the RID Pool on this DSA'''
+        return dsdb._dsdb_allocate_rid(self)
diff --git a/python/samba/tests/samba_tool/timecmd.py b/python/samba/tests/samba_tool/timecmd.py
index 310f861..68dcb06 100644
--- a/python/samba/tests/samba_tool/timecmd.py
+++ b/python/samba/tests/samba_tool/timecmd.py
@@ -39,5 +39,5 @@ class TimeCmdTestCase(SambaToolCmdTest):
         """Run time against a non-existent server, and make sure it fails"""
         (result, out, err) = self.runcmd("time", "notaserver")
         self.assertEquals(result, -1, "check for result code")
-        self.assertTrue(err.strip().endswith("NT_STATUS_OBJECT_NAME_NOT_FOUND"), "ensure right error string")
+        self.assertNotEqual(err.strip().find("NT_STATUS_OBJECT_NAME_NOT_FOUND"), -1, "ensure right error string")
         self.assertEquals(out, "", "ensure no output returned")
diff --git a/selftest/knownfail b/selftest/knownfail
index 38b5f51..ddfe0ad 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -306,3 +306,7 @@
 ^samba4.rpc.echo.*on.*with.object.echo.sinkdata.*nt4_dc
 ^samba4.rpc.echo.*on.*with.object.echo.addone.*nt4_dc
 ^samba4.rpc.echo.*on.*ncacn_ip_tcp.*with.object.*nt4_dc
+^samba4.drs.ridalloc_exop.python.*ridalloc_exop.DrsReplicaSyncTestCase.test_offline_ridalloc
+^samba4.drs.ridalloc_exop.python.*ridalloc_exop.DrsReplicaSyncTestCase.test_join_time_ridalloc
+^samba4.drs.ridalloc_exop.python.*ridalloc_exop.DrsReplicaSyncTestCase.test_rid_set_dbcheck_after_seize
+^samba4.drs.ridalloc_exop.python.*ridalloc_exop.DrsReplicaSyncTestCase.test_rid_set_dbcheck
\ No newline at end of file
diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c
index e53a245..ab1d0d2 100644
--- a/source4/dsdb/pydsdb.c
+++ b/source4/dsdb/pydsdb.c
@@ -1078,6 +1078,74 @@ static PyObject *py_dsdb_am_pdc(PyObject *self, PyObject *args)
 	return PyBool_FromLong(am_pdc);
 }
 
+/*
+  call DSDB_EXTENDED_CREATE_OWN_RID_SET to get a new RID set for this server
+ */
+static PyObject *py_dsdb_create_own_rid_set(PyObject *self, PyObject *args)
+{
+	PyObject *py_ldb;
+	struct ldb_context *ldb;
+	int ret;
+	struct ldb_result *ext_res;
+
+	if (!PyArg_ParseTuple(args, "O", &py_ldb))
+		return NULL;
+
+	PyErr_LDB_OR_RAISE(py_ldb, ldb);
+
+	/*
+	 * Run DSDB_EXTENDED_CREATE_OWN_RID_SET to get a RID set
+	 */
+
+	ret = ldb_extended(ldb, DSDB_EXTENDED_CREATE_OWN_RID_SET, NULL, &ext_res);
+
+	PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
+
+	TALLOC_FREE(ext_res);
+
+	Py_RETURN_NONE;
+}
+
+/*
+  call DSDB_EXTENDED_ALLOCATE_RID to get a new RID set for this server
+ */
+static PyObject *py_dsdb_allocate_rid(PyObject *self, PyObject *args)
+{
+	PyObject *py_ldb;
+	struct ldb_context *ldb;
+	int ret;
+	uint32_t rid;
+	struct ldb_result *ext_res = NULL;
+	struct dsdb_extended_allocate_rid *rid_return = NULL;
+	if (!PyArg_ParseTuple(args, "O", &py_ldb)) {
+		return NULL;
+	}
+
+	PyErr_LDB_OR_RAISE(py_ldb, ldb);
+
+	rid_return = talloc_zero(ldb, struct dsdb_extended_allocate_rid);
+	if (rid_return == NULL) {
+		return PyErr_NoMemory();
+	}
+
+	/*
+	 * Run DSDB_EXTENDED_ALLOCATE_RID to get a new RID
+	 */
+
+	ret = ldb_extended(ldb, DSDB_EXTENDED_ALLOCATE_RID, rid_return, &ext_res);
+	if (ret != LDB_SUCCESS) {
+		TALLOC_FREE(rid_return);
+		TALLOC_FREE(ext_res);
+		PyErr_LDB_ERROR_IS_ERR_RAISE(py_ldb_get_exception(), ret, ldb);
+	}
+
+	rid = rid_return->rid;
+	TALLOC_FREE(rid_return);
+	TALLOC_FREE(ext_res);
+
+	return PyInt_FromLong(rid);
+}
+
 static PyObject *py_dsdb_garbage_collect_tombstones(PyObject *self, PyObject *args)
 {
 	PyObject *py_ldb, *py_list_dn;
@@ -1245,6 +1313,12 @@ static PyMethodDef py_dsdb_methods[] = {
 	{ "_dsdb_garbage_collect_tombstones", (PyCFunction)py_dsdb_garbage_collect_tombstones, METH_VARARGS,
 		"_dsdb_kcc_check_deleted(samdb, [dn], current_time, tombstone_lifetime)"
 		" -> (num_objects_expunged, num_links_expunged)" },
+	{ "_dsdb_create_own_rid_set", (PyCFunction)py_dsdb_create_own_rid_set, METH_VARARGS,
+		"_dsdb_create_own_rid_set(samdb)"
+		" -> None" },
+	{ "_dsdb_allocate_rid", (PyCFunction)py_dsdb_allocate_rid, METH_VARARGS,
+		"_dsdb_allocate_rid(samdb)"
+		" -> RID" },
 	{ NULL }
 };
 
diff --git a/source4/dsdb/samdb/ldb_modules/ridalloc.c b/source4/dsdb/samdb/ldb_modules/ridalloc.c
index 4c619b7..d3463e6 100644
--- a/source4/dsdb/samdb/ldb_modules/ridalloc.c
+++ b/source4/dsdb/samdb/ldb_modules/ridalloc.c
@@ -347,8 +347,12 @@ static int ridalloc_create_rid_set_ntds(struct ldb_module *module, TALLOC_CTX *m
 
 	/* we need this to go all the way to the top of the module
 	 * stack, as we need all the extra attributes added (including
-	 * complex ones like ntsecuritydescriptor) */
-	ret = dsdb_module_add(module, msg, DSDB_FLAG_TOP_MODULE | DSDB_MODIFY_RELAX, parent);
+	 * complex ones like ntsecuritydescriptor).  We must do this
+	 * as system, otherwise a user might end up owning the RID
+	 * set, and that would be bad... */
+	ret = dsdb_module_add(module, msg,
+			      DSDB_FLAG_TOP_MODULE | DSDB_FLAG_AS_SYSTEM
+			      | DSDB_MODIFY_RELAX, parent);
 	if (ret != LDB_SUCCESS) {
 		ldb_asprintf_errstring(ldb, "Failed to add RID Set %s - %s",
 				       ldb_dn_get_linearized(msg->dn),
@@ -401,8 +405,8 @@ static int ridalloc_create_rid_set_ntds(struct ldb_module *module, TALLOC_CTX *m
 /*
   create a RID Set object for this DC
  */
-static int ridalloc_create_own_rid_set(struct ldb_module *module, TALLOC_CTX *mem_ctx,
-				       struct ldb_dn **dn, struct ldb_request *parent)
+int ridalloc_create_own_rid_set(struct ldb_module *module, TALLOC_CTX *mem_ctx,
+				struct ldb_dn **dn, struct ldb_request *parent)
 {
 	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
 	struct ldb_dn *rid_manager_dn, *fsmo_role_dn;
@@ -466,7 +470,8 @@ static int ridalloc_create_own_rid_set(struct ldb_module *module, TALLOC_CTX *me
   get a new RID pool for ourselves
   also returns the first rid for the new pool
  */
-static int ridalloc_new_own_pool(struct ldb_module *module, uint64_t *new_pool, struct ldb_request *parent)
+
+int ridalloc_new_own_pool(struct ldb_module *module, uint64_t *new_pool, struct ldb_request *parent)
 {
 	TALLOC_CTX *tmp_ctx = talloc_new(module);
 	struct ldb_dn *rid_manager_dn, *fsmo_role_dn;
@@ -685,6 +690,11 @@ int ridalloc_allocate_rid(struct ldb_module *module, uint32_t *rid, struct ldb_r
 
 /*
   called by DSDB_EXTENDED_ALLOCATE_RID_POOL extended operation in samldb
+
+  This is for the DRS server to allocate a RID Pool for another server.
+
+  Called by another server over DRS (which calls this extended
+  operation), it runs on the RID Manager only.
  */
 int ridalloc_allocate_rid_pool_fsmo(struct ldb_module *module, struct dsdb_fsmo_extended_op *exop,
 				    struct ldb_request *parent)
diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index cc101a6..b33cf24 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -3869,12 +3869,63 @@ static int samldb_extended_allocate_rid_pool(struct ldb_module *module, struct l
 	return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
 }
 
+static int samldb_extended_allocate_rid(struct ldb_module *module, struct ldb_request *req)
+{
+	struct ldb_context *ldb = ldb_module_get_ctx(module);
+	struct dsdb_extended_allocate_rid *exop;
+	int ret;
+
+	exop = talloc_get_type(req->op.extended.data,
+			       struct dsdb_extended_allocate_rid);
+	if (!exop) {
+		ldb_set_errstring(ldb,
+				  "samldb_extended_allocate_rid: invalid extended data");
+		return LDB_ERR_PROTOCOL_ERROR;
+	}
+
+	ret = ridalloc_allocate_rid(module, &exop->rid, req);
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+
+	return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
+}
+
+static int samldb_extended_create_own_rid_set(struct ldb_module *module, struct ldb_request *req)
+{
+	struct ldb_context *ldb = ldb_module_get_ctx(module);
+	int ret;


-- 
Samba Shared Repository



More information about the samba-cvs mailing list