python/drs: Ensure to pass in the local invocationID during the domain join
authorAndrew Bartlett <abartlet@samba.org>
Wed, 18 Sep 2013 21:27:26 +0000 (14:27 -0700)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 19 Sep 2013 19:25:41 +0000 (12:25 -0700)
This ensures (and asserts) that we never write an all-zero GUID as an invocationID
to the database in replPropertyMetaData.

Andrew Bartlett

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
python/samba/drs_utils.py
python/samba/join.py
python/samba/netcmd/drs.py
source4/dsdb/common/util.c
source4/dsdb/pydsdb.c
source4/libnet/py_net.c

index 6e2cfea9ab2385a7139822748e48ccf87234da79..49837492b7dcc6c19f2f5adf0f348079072ff6c0 100644 (file)
@@ -147,12 +147,16 @@ def drs_DsBind(drs):
 class drs_Replicate(object):
     '''DRS replication calls'''
 
-    def __init__(self, binding_string, lp, creds, samdb):
+    def __init__(self, binding_string, lp, creds, samdb, invocation_id):
         self.drs = drsuapi.drsuapi(binding_string, lp, creds)
         (self.drs_handle, self.supported_extensions) = drs_DsBind(self.drs)
         self.net = Net(creds=creds, lp=lp)
         self.samdb = samdb
-        self.replication_state = self.net.replicate_init(self.samdb, lp, self.drs)
+        if not isinstance(invocation_id, misc.GUID):
+            raise RuntimeError("Must supply GUID for invocation_id")
+        if invocation_id == misc.GUID("00000000-0000-0000-0000-000000000000"):
+            raise RuntimeError("Must not set GUID 00000000-0000-0000-0000-000000000000 as invocation_id")
+        self.replication_state = self.net.replicate_init(self.samdb, lp, self.drs, invocation_id)
 
     def drs_get_rodc_partial_attribute_set(self):
         '''get a list of attributes for RODC replication'''
index 15db67fbb4a960c9e5c9f5ad2633667e8c909397..2379d5f214d6ccdff6f609afac26668134a42852 100644 (file)
@@ -799,7 +799,7 @@ class dc_join(object):
                 binding_options += ",print"
             repl = drs_utils.drs_Replicate(
                 "ncacn_ip_tcp:%s[%s]" % (ctx.server, binding_options),
-                ctx.lp, repl_creds, ctx.local_samdb)
+                ctx.lp, repl_creds, ctx.local_samdb, ctx.invocation_id)
 
             repl.replicate(ctx.schema_dn, source_dsa_invocation_id,
                     destination_dsa_guid, schema=True, rodc=ctx.RODC,
index de78ac71c783f064aaea4c2f73ef6f21afc67d43..36dc48e2c234ed5301457172e216e125624f2d21 100644 (file)
@@ -258,11 +258,13 @@ def drs_local_replicate(self, SOURCE_DC, NC):
 
 
     source_dsa_invocation_id = misc.GUID(self.samdb.get_invocation_id())
+    dest_dsa_invocation_id = misc.GUID(self.local_samdb.get_invocation_id())
     destination_dsa_guid = self.ntds_guid
 
     self.samdb.transaction_start()
     repl = drs_utils.drs_Replicate("ncacn_ip_tcp:%s[seal]" % self.server, self.lp,
-                                   self.creds, self.local_samdb)
+                                   self.creds, self.local_samdb, dest_dsa_invocation_id)
+
     try:
         repl.replicate(NC, source_dsa_invocation_id, destination_dsa_guid)
     except Exception, e:
index 7a243c3d3769bae622de43ce1385b00a0cd56788..55bd73e424996043b84228146918c2bd43ebe156 100644 (file)
@@ -1302,6 +1302,7 @@ const struct GUID *samdb_ntds_invocation_id(struct ldb_context *ldb)
        /* see if we have a cached copy */
        invocation_id = (struct GUID *)ldb_get_opaque(ldb, "cache.invocation_id");
        if (invocation_id) {
+               SMB_ASSERT(!GUID_all_zero(invocation_id));
                return invocation_id;
        }
 
@@ -1362,6 +1363,7 @@ bool samdb_set_ntds_invocation_id(struct ldb_context *ldb, const struct GUID *in
                goto failed;
        }
 
+       SMB_ASSERT(!GUID_all_zero(invocation_id_in));
        *invocation_id_new = *invocation_id_in;
 
        /* cache the domain_sid in the ldb */
index 99e239e60c80560a2f673f0a29fe6309fb8a453e..c9e80c2f1bd3e54e244914aa19b191641c95e830 100644 (file)
@@ -727,6 +727,11 @@ static PyObject *py_dsdb_set_ntds_invocation_id(PyObject *self, PyObject *args)
        PyErr_LDB_OR_RAISE(py_ldb, ldb);
        GUID_from_string(PyString_AsString(py_guid), &guid);
 
+       if (GUID_all_zero(&guid)) {
+               PyErr_SetString(PyExc_RuntimeError, "set_ntds_invocation_id rejected due to all-zero invocation ID");
+               return NULL;
+       }
+
        ret = samdb_set_ntds_invocation_id(ldb, &guid);
        if (!ret) {
                PyErr_SetString(PyExc_RuntimeError, "set_ntds_invocation_id failed");
index acb0a3775912549759711010f9d33b1553a59238..7981aad02257e8e876758121542e07c16f0723ec 100644 (file)
@@ -22,6 +22,7 @@
 #include <Python.h>
 #include "includes.h"
 #include <pyldb.h>
+#include <pytalloc.h>
 #include "libnet.h"
 #include "auth/credentials/pycredentials.h"
 #include "libcli/security/security.h"
@@ -33,6 +34,7 @@
 #include "libcli/finddc.h"
 #include "dsdb/samdb/samdb.h"
 #include "py_net.h"
+#include "librpc/rpc/pyrpc_util.h"
 
 void initnet(void);
 
@@ -363,16 +365,17 @@ struct replicate_state {
  */
 static PyObject *py_net_replicate_init(py_net_Object *self, PyObject *args, PyObject *kwargs)
 {
-       const char *kwnames[] = { "samdb", "lp", "drspipe", NULL };
-       PyObject *py_ldb, *py_lp, *py_drspipe;
+       const char *kwnames[] = { "samdb", "lp", "drspipe", "invocation_id", NULL };
+       PyObject *py_ldb, *py_lp, *py_drspipe, *py_invocation_id;
        struct ldb_context *samdb;
        struct loadparm_context *lp;
        struct replicate_state *s;
        NTSTATUS status;
 
-       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOO",
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOOO",
                                         discard_const_p(char *, kwnames),
-                                        &py_ldb, &py_lp, &py_drspipe)) {
+                                        &py_ldb, &py_lp, &py_drspipe,
+                                        &py_invocation_id)) {
                return NULL;
        }
 
@@ -392,6 +395,12 @@ static PyObject *py_net_replicate_init(py_net_Object *self, PyObject *args, PyOb
                talloc_free(s);
                return NULL;
        }
+       if (!py_check_dcerpc_type(py_invocation_id, "samba.dcerpc.misc", "GUID")) {
+               
+               talloc_free(s);
+               return NULL;
+       }
+       s->dest_dsa.invocation_id = *pytalloc_get_type(py_invocation_id, struct GUID);
 
        s->drs_pipe = (dcerpc_InterfaceObject *)(py_drspipe);