[SCM] Samba Shared Repository - branch master updated

Andrew Tridgell tridge at samba.org
Tue Aug 24 16:41:56 MDT 2010


The branch, master has been updated
       via  f42af4e... s4-dsdb: make more of the UF_* flags available on pydsdb
       via  64bf637... s4-rodc: broke up RODC join into separate functions
       via  e3c0409... s4-rodc: added REPL_SECRET exop replication of accounts
       via  4ab1a48... s4-dsdb: add more DS flags to the dsdb module
       via  8438da9... s4-dsdb: added get_attid_from_lDAPDisplayName() on samdb
       via  495bd18... s4-rodc: next step in RODC join code
       via  4cacdf0... s4-pynet: added replicate_init() and replicate_chunk() calls
       via  631c5f1... s4-libnet: added libnet_vampire_replicate_init()
       via  e5a5ca0... idl-nbt: fixed typo
      from  d3a0ff3... s3: Make char_flags and base_reverse const arrays

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


- Log -----------------------------------------------------------------
commit f42af4ea6810c65a37eec08e08acb5d831457bca
Author: Andrew Tridgell <tridge at samba.org>
Date:   Tue Aug 24 23:37:57 2010 +1000

    s4-dsdb: make more of the UF_* flags available on pydsdb
    
    this really should be moved to IDL

commit 64bf637edfc0dbc4a1856aee894ecb2e37c54d93
Author: Andrew Tridgell <tridge at samba.org>
Date:   Tue Aug 24 23:37:25 2010 +1000

    s4-rodc: broke up RODC join into separate functions
    
    this also removes some of the magic constants

commit e3c0409c7a22d8412a74436aa5733bc527730b5a
Author: Andrew Tridgell <tridge at samba.org>
Date:   Tue Aug 24 22:10:46 2010 +1000

    s4-rodc: added REPL_SECRET exop replication of accounts
    
    During a RODC join, we need to fetch the secrets for the machine
    account and krbtgt account using GetNCChanges
    DRSUAPI_EXOP_REPL_SECRET calls
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

commit 4ab1a489c74079644c1fce5df1ced5a0bbbc9f39
Author: Andrew Tridgell <tridge at samba.org>
Date:   Tue Aug 24 22:09:18 2010 +1000

    s4-dsdb: add more DS flags to the dsdb module
    
    These are from libds/common/flags.h
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

commit 8438da96ba632671327506423239169402917c51
Author: Andrew Tridgell <tridge at samba.org>
Date:   Tue Aug 24 22:08:27 2010 +1000

    s4-dsdb: added get_attid_from_lDAPDisplayName() on samdb
    
    This can be used to form the partial_attribute_set list for
    GetNCChanges
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

commit 495bd182f5e26cbcb721ab8209f8acad4d612726
Author: Andrew Tridgell <tridge at samba.org>
Date:   Tue Aug 24 15:42:54 2010 +1000

    s4-rodc: next step in RODC join code
    
    a RODC net join can now replicate the schame, config and base
    partitions, by calling the net.replicate*() python hooks, and driving
    the GetNCChanges calls from python
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

commit 4cacdf00020c808ae8e3ef59378da682ce346133
Author: Andrew Tridgell <tridge at samba.org>
Date:   Tue Aug 24 15:41:40 2010 +1000

    s4-pynet: added replicate_init() and replicate_chunk() calls
    
    these calls allow python code to pass chunks from DRS replication
    calls into the code that applies the chunks to a database
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

commit 631c5f1fd5e77a6d380df3bc83dc166d902315af
Author: Andrew Tridgell <tridge at samba.org>
Date:   Tue Aug 24 15:40:42 2010 +1000

    s4-libnet: added libnet_vampire_replicate_init()
    
    this is used to setup for later calls to the replicate chunk functions
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

commit e5a5ca028e645d2852a2a063730d4f51a3ee84b1
Author: Andrew Tridgell <tridge at samba.org>
Date:   Mon Aug 23 18:59:47 2010 +1000

    idl-nbt: fixed typo

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

Summary of changes:
 librpc/idl/nbt.idl                      |    2 +-
 source4/dsdb/pydsdb.c                   |   89 +++++
 source4/libnet/libnet_vampire.c         |   17 +
 source4/libnet/py_net.c                 |  169 ++++++++--
 source4/scripting/python/samba/join.py  |  531 ++++++++++++++++++++-----------
 source4/scripting/python/samba/samdb.py |    3 +
 6 files changed, 583 insertions(+), 228 deletions(-)


Changeset truncated at 500 lines:

diff --git a/librpc/idl/nbt.idl b/librpc/idl/nbt.idl
index 897abb2..caf6da9 100644
--- a/librpc/idl/nbt.idl
+++ b/librpc/idl/nbt.idl
@@ -369,7 +369,7 @@ interface nbt
 		NETLOGON_NT_VERSION_5EX			= 0x00000004,
 		NETLOGON_NT_VERSION_5EX_WITH_IP		= 0x00000008,
 		NETLOGON_NT_VERSION_WITH_CLOSEST_SITE	= 0x00000010,
-		NETLOGON_NT_VERSION_AVIOD_NT4EMUL	= 0x01000000,
+		NETLOGON_NT_VERSION_AVOID_NT4EMUL	= 0x01000000,
 		NETLOGON_NT_VERSION_PDC			= 0x10000000,
 		NETLOGON_NT_VERSION_IP			= 0x20000000,
 		NETLOGON_NT_VERSION_LOCAL		= 0x40000000,
diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c
index 1967b33..ecf89b1 100644
--- a/source4/dsdb/pydsdb.c
+++ b/source4/dsdb/pydsdb.c
@@ -258,6 +258,50 @@ static PyObject *py_dsdb_get_oid_from_attid(PyObject *self, PyObject *args)
 	return ret;
 }
 
+
+static PyObject *py_dsdb_get_attid_from_lDAPDisplayName(PyObject *self, PyObject *args)
+{
+	PyObject *py_ldb, *is_schema_nc;
+	struct ldb_context *ldb;
+	struct dsdb_schema *schema;
+	const char *ldap_display_name;
+	bool schema_nc = false;
+	const struct dsdb_attribute *a;
+	uint32_t attid;
+
+	if (!PyArg_ParseTuple(args, "OsO", &py_ldb, &ldap_display_name, &is_schema_nc))
+		return NULL;
+
+	PyErr_LDB_OR_RAISE(py_ldb, ldb);
+
+	if (is_schema_nc) {
+		if (!PyBool_Check(is_schema_nc)) {
+			PyErr_SetString(PyExc_TypeError, "Expected boolean is_schema_nc");
+			return NULL;
+		}
+		if (is_schema_nc == Py_True) {
+			schema_nc = true;
+		}
+	}
+
+	schema = dsdb_get_schema(ldb, NULL);
+
+	if (!schema) {
+		PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb");
+		return NULL;
+	}
+
+	a = dsdb_attribute_by_lDAPDisplayName(schema, ldap_display_name);
+	if (a == NULL) {
+		PyErr_Format(PyExc_RuntimeError, "Failed to find attribute '%s'", ldap_display_name);
+		return NULL;
+	}
+
+	attid = dsdb_attribute_get_attid(a, schema_nc);
+
+	return PyLong_FromUnsignedLong(attid);
+}
+
 static PyObject *py_dsdb_set_ntds_invocation_id(PyObject *self, PyObject *args)
 {
 	PyObject *py_ldb, *py_guid;
@@ -485,6 +529,8 @@ static PyMethodDef py_dsdb_methods[] = {
 		"Set NTDS Settings DN for this LDB (allows it to be set before the DB fully exists)." },
 	{ "_dsdb_get_oid_from_attid", (PyCFunction)py_dsdb_get_oid_from_attid,
 		METH_VARARGS, NULL },
+	{ "_dsdb_get_attid_from_lDAPDisplayName", (PyCFunction)py_dsdb_get_attid_from_lDAPDisplayName,
+		METH_VARARGS, NULL },
 	{ "_dsdb_set_ntds_invocation_id",
 		(PyCFunction)py_dsdb_set_ntds_invocation_id, METH_VARARGS,
 		NULL },
@@ -532,6 +578,34 @@ void initdsdb(void)
 	PyModule_AddObject(m, "UF_ACCOUNTDISABLE",
 					   PyInt_FromLong(UF_ACCOUNTDISABLE));
 
+	PyModule_AddObject(m, "UF_SCRIPT", PyInt_FromLong(UF_SCRIPT));
+	PyModule_AddObject(m, "UF_ACCOUNTDISABLE", PyInt_FromLong(UF_ACCOUNTDISABLE));
+	PyModule_AddObject(m, "UF_00000004", PyInt_FromLong(UF_00000004));
+	PyModule_AddObject(m, "UF_HOMEDIR_REQUIRED", PyInt_FromLong(UF_HOMEDIR_REQUIRED));
+	PyModule_AddObject(m, "UF_LOCKOUT", PyInt_FromLong(UF_LOCKOUT));
+	PyModule_AddObject(m, "UF_PASSWD_NOTREQD", PyInt_FromLong(UF_PASSWD_NOTREQD));
+	PyModule_AddObject(m, "UF_PASSWD_CANT_CHANGE", PyInt_FromLong(UF_PASSWD_CANT_CHANGE));
+	PyModule_AddObject(m, "UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED", PyInt_FromLong(UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED));
+	PyModule_AddObject(m, "UF_TEMP_DUPLICATE_ACCOUNT", PyInt_FromLong(UF_TEMP_DUPLICATE_ACCOUNT));
+	PyModule_AddObject(m, "UF_NORMAL_ACCOUNT", PyInt_FromLong(UF_NORMAL_ACCOUNT));
+	PyModule_AddObject(m, "UF_00000400", PyInt_FromLong(UF_00000400));
+	PyModule_AddObject(m, "UF_INTERDOMAIN_TRUST_ACCOUNT", PyInt_FromLong(UF_INTERDOMAIN_TRUST_ACCOUNT));
+	PyModule_AddObject(m, "UF_WORKSTATION_TRUST_ACCOUNT", PyInt_FromLong(UF_WORKSTATION_TRUST_ACCOUNT));
+	PyModule_AddObject(m, "UF_SERVER_TRUST_ACCOUNT", PyInt_FromLong(UF_SERVER_TRUST_ACCOUNT));
+	PyModule_AddObject(m, "UF_00004000", PyInt_FromLong(UF_00004000));
+	PyModule_AddObject(m, "UF_00008000", PyInt_FromLong(UF_00008000));
+	PyModule_AddObject(m, "UF_DONT_EXPIRE_PASSWD", PyInt_FromLong(UF_DONT_EXPIRE_PASSWD));
+	PyModule_AddObject(m, "UF_MNS_LOGON_ACCOUNT", PyInt_FromLong(UF_MNS_LOGON_ACCOUNT));
+	PyModule_AddObject(m, "UF_SMARTCARD_REQUIRED", PyInt_FromLong(UF_SMARTCARD_REQUIRED));
+	PyModule_AddObject(m, "UF_TRUSTED_FOR_DELEGATION", PyInt_FromLong(UF_TRUSTED_FOR_DELEGATION));
+	PyModule_AddObject(m, "UF_NOT_DELEGATED", PyInt_FromLong(UF_NOT_DELEGATED));
+	PyModule_AddObject(m, "UF_USE_DES_KEY_ONLY", PyInt_FromLong(UF_USE_DES_KEY_ONLY));
+	PyModule_AddObject(m, "UF_DONT_REQUIRE_PREAUTH", PyInt_FromLong(UF_DONT_REQUIRE_PREAUTH));
+	PyModule_AddObject(m, "UF_PASSWORD_EXPIRED", PyInt_FromLong(UF_PASSWORD_EXPIRED));
+	PyModule_AddObject(m, "UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION", PyInt_FromLong(UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION));
+	PyModule_AddObject(m, "UF_NO_AUTH_DATA_REQUIRED", PyInt_FromLong(UF_NO_AUTH_DATA_REQUIRED));
+	PyModule_AddObject(m, "UF_PARTIAL_SECRETS_ACCOUNT", PyInt_FromLong(UF_PARTIAL_SECRETS_ACCOUNT));
+
 	/* "groupType" flags */
 	PyModule_AddObject(m, "GTYPE_SECURITY_BUILTIN_LOCAL_GROUP",
 					   PyInt_FromLong(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP));
@@ -619,4 +693,19 @@ void initdsdb(void)
 			   PyInt_FromLong(ENC_HMAC_SHA1_96_AES128));
 	PyModule_AddObject(m, "ENC_HMAC_SHA1_96_AES256",
 			   PyInt_FromLong(ENC_HMAC_SHA1_96_AES256));
+
+	PyModule_AddObject(m, "SEARCH_FLAG_ATTINDEX", PyInt_FromLong(SEARCH_FLAG_ATTINDEX));
+	PyModule_AddObject(m, "SEARCH_FLAG_PDNTATTINDEX", PyInt_FromLong(SEARCH_FLAG_PDNTATTINDEX));
+	PyModule_AddObject(m, "SEARCH_FLAG_ANR", PyInt_FromLong(SEARCH_FLAG_ANR));
+	PyModule_AddObject(m, "SEARCH_FLAG_PRESERVEONDELETE", PyInt_FromLong(SEARCH_FLAG_PRESERVEONDELETE));
+	PyModule_AddObject(m, "SEARCH_FLAG_COPY", PyInt_FromLong(SEARCH_FLAG_COPY));
+	PyModule_AddObject(m, "SEARCH_FLAG_TUPLEINDEX", PyInt_FromLong(SEARCH_FLAG_TUPLEINDEX));
+	PyModule_AddObject(m, "SEARCH_FLAG_SUBTREEATTRINDEX", PyInt_FromLong(SEARCH_FLAG_SUBTREEATTRINDEX));
+	PyModule_AddObject(m, "SEARCH_FLAG_CONFIDENTIAL", PyInt_FromLong(SEARCH_FLAG_CONFIDENTIAL));
+	PyModule_AddObject(m, "SEARCH_FLAG_NEVERVALUEAUDIT", PyInt_FromLong(SEARCH_FLAG_NEVERVALUEAUDIT));
+	PyModule_AddObject(m, "SEARCH_FLAG_RODC_ATTRIBUTE", PyInt_FromLong(SEARCH_FLAG_RODC_ATTRIBUTE));
+
+	PyModule_AddObject(m, "DS_FLAG_ATTR_NOT_REPLICATED", PyInt_FromLong(DS_FLAG_ATTR_NOT_REPLICATED));
+	PyModule_AddObject(m, "DS_FLAG_ATTR_REQ_PARTIAL_SET_MEMBER", PyInt_FromLong(DS_FLAG_ATTR_REQ_PARTIAL_SET_MEMBER));
+	PyModule_AddObject(m, "DS_FLAG_ATTR_IS_CONSTRUCTED", PyInt_FromLong(DS_FLAG_ATTR_IS_CONSTRUCTED));
 }
diff --git a/source4/libnet/libnet_vampire.c b/source4/libnet/libnet_vampire.c
index 1847890..955aa32 100644
--- a/source4/libnet/libnet_vampire.c
+++ b/source4/libnet/libnet_vampire.c
@@ -92,6 +92,23 @@ struct libnet_vampire_cb_state {
 	const char *server_dn_str;
 };
 
+/* initialise a state structure ready for replication of chunks */
+void *libnet_vampire_replicate_init(TALLOC_CTX *mem_ctx,
+				    struct ldb_context *samdb,
+				    struct loadparm_context *lp_ctx)
+{
+	struct libnet_vampire_cb_state *s = talloc_zero(mem_ctx, struct libnet_vampire_cb_state);
+	if (!s) {
+		return NULL;
+	}
+
+	s->ldb              = samdb;
+	s->lp_ctx           = lp_ctx;
+	s->provision_schema = dsdb_get_schema(s->ldb, s);
+
+	return s;
+}
+
 /* Caller is expected to keep supplied pointers around for the lifetime of the structure */
 void *libnet_vampire_cb_state_init(TALLOC_CTX *mem_ctx,
 				   struct loadparm_context *lp_ctx, struct tevent_context *event_ctx,
diff --git a/source4/libnet/py_net.c b/source4/libnet/py_net.c
index d4a4670..0b1eb7b 100644
--- a/source4/libnet/py_net.c
+++ b/source4/libnet/py_net.c
@@ -26,6 +26,9 @@
 #include "lib/events/events.h"
 #include "param/param.h"
 #include "param/pyparam.h"
+#include "lib/ldb/pyldb.h"
+#include "auth/gensec/gensec.h"
+#include "librpc/rpc/pyrpc.h"
 
 typedef struct {
 	PyObject_HEAD
@@ -306,58 +309,150 @@ static PyObject *py_net_vampire(py_net_Object *self, PyObject *args, PyObject *k
 	return ret;
 }
 
+struct replicate_state {
+	void *vampire_state;
+	dcerpc_InterfaceObject *drs_pipe;
+	struct libnet_BecomeDC_StoreChunk chunk;
+	DATA_BLOB gensec_skey;
+	struct libnet_BecomeDC_Partition partition;
+	struct libnet_BecomeDC_Forest forest;
+	struct libnet_BecomeDC_DestDSA dest_dsa;
+};
 
-static PyObject *py_net_replicate(py_net_Object *self, PyObject *args, PyObject *kwargs)
+/*
+  setup for replicate_chunk() calls
+ */
+static PyObject *py_net_replicate_init(py_net_Object *self, PyObject *args, PyObject *kwargs)
 {
-	const char *kwnames[] = { "domain", "netbios_name",
-				  "domain_sid", "realm", "server", "join_password",
-				  "kvno", "target_dir", NULL };
+	const char *kwnames[] = { "samdb", "lp", "drspipe", NULL };
+	PyObject *py_ldb, *py_lp, *py_drspipe;
+	struct ldb_context *samdb;
+	struct loadparm_context *lp;
+	struct replicate_state *s;
 	NTSTATUS status;
-	TALLOC_CTX *mem_ctx;
-	struct libnet_Replicate r;
-	unsigned kvno;
-	const char *sidstr;
 
-	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ssssssI|z",
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOO",
 					 discard_const_p(char *, kwnames),
-	                                 &r.in.domain_name,
-					 &r.in.netbios_name,
-					 &sidstr,
-					 &r.in.realm,
-					 &r.in.server,
-					 &r.in.join_password,
-					 &kvno,
-					 &r.in.targetdir)) {
+	                                 &py_ldb, &py_lp, &py_drspipe)) {
 		return NULL;
 	}
 
-	r.out.error_string = NULL;
+	s = talloc_zero(NULL, struct replicate_state);
+	if (!s) return NULL;
 
-	mem_ctx = talloc_new(NULL);
-	if (mem_ctx == NULL) {
-		PyErr_NoMemory();
+	lp = lpcfg_from_py_object(s, py_lp);
+	if (lp == NULL) {
+		PyErr_SetString(PyExc_TypeError, "Expected lp object");
+		talloc_free(s);
 		return NULL;
 	}
 
-	r.in.kvno       = kvno;
-	r.in.domain_sid = dom_sid_parse_talloc(mem_ctx, sidstr);
-
-	if (!r.in.domain_sid) {
-		PyErr_Format(PyExc_RuntimeError, "Bad domain_sid %s", sidstr);
-		talloc_free(mem_ctx);
+	samdb = PyLdb_AsLdbContext(py_ldb);
+	if (samdb == NULL) {
+		PyErr_SetString(PyExc_TypeError, "Expected ldb object");
+		talloc_free(s);
 		return NULL;
 	}
 
-	status = libnet_Replicate(self->libnet_ctx, mem_ctx, &r);
+	s->drs_pipe = (dcerpc_InterfaceObject *)(py_drspipe);
 
+	s->vampire_state = libnet_vampire_replicate_init(s, samdb, lp);
+	if (s->vampire_state == NULL) {
+		PyErr_SetString(PyExc_TypeError, "Failed to initialise vampire_state");
+		talloc_free(s);
+		return NULL;
+	}
+
+	status = gensec_session_key(s->drs_pipe->pipe->conn->security_state.generic_state,
+				    &s->gensec_skey);
 	if (!NT_STATUS_IS_OK(status)) {
-		PyErr_SetString(PyExc_RuntimeError,
-		                r.out.error_string ? r.out.error_string : nt_errstr(status));
-		talloc_free(mem_ctx);
+		PyErr_Format(PyExc_RuntimeError, "Unable to get session key from drspipe: %s",
+			     nt_errstr(status));
+		talloc_free(s);
 		return NULL;
 	}
 
-	talloc_free(mem_ctx);
+	s->chunk.gensec_skey = &s->gensec_skey;
+	s->chunk.partition = &s->partition;
+	s->chunk.forest = &s->forest;
+	s->chunk.dest_dsa = &s->dest_dsa;
+
+	return PyCObject_FromTallocPtr(s);
+}
+
+
+/*
+  process one replication chunk
+ */
+static PyObject *py_net_replicate_chunk(py_net_Object *self, PyObject *args, PyObject *kwargs)
+{
+	const char *kwnames[] = { "state", "level", "ctr", "schema", NULL };
+	PyObject *py_state, *py_ctr, *py_schema;
+	struct replicate_state *s;
+	unsigned level;
+	NTSTATUS (*chunk_handler)(void *private_data, const struct libnet_BecomeDC_StoreChunk *c);
+	NTSTATUS status;
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OIO|O",
+					 discard_const_p(char *, kwnames),
+	                                 &py_state, &level, &py_ctr, &py_schema)) {
+		return NULL;
+	}
+
+	s = talloc_get_type(PyCObject_AsVoidPtr(py_state), struct replicate_state);
+	if (!s) {
+		PyErr_SetString(PyExc_TypeError, "Expected replication_state");
+		return NULL;
+	}
+
+	switch (level) {
+	case 1:
+		if (strcmp("drsuapi.DsGetNCChangesCtr1", Py_TYPE(py_ctr)->tp_name) != 0) {
+			PyErr_SetString(PyExc_TypeError, "Expected DsGetNCChangesCtr1 type for ctr");
+			return NULL;
+		}
+		s->chunk.ctr1                         = py_talloc_get_ptr(py_ctr);
+		s->partition.nc                       = *s->chunk.ctr1->naming_context;
+		s->partition.more_data                = s->chunk.ctr1->more_data;
+		s->partition.source_dsa_guid          = s->chunk.ctr1->source_dsa_guid;
+		s->partition.source_dsa_invocation_id = s->chunk.ctr1->source_dsa_invocation_id;
+		s->partition.highwatermark            = s->chunk.ctr1->new_highwatermark;
+		break;
+	case 6:
+		if (strcmp("drsuapi.DsGetNCChangesCtr6", Py_TYPE(py_ctr)->tp_name) != 0) {
+			PyErr_SetString(PyExc_TypeError, "Expected DsGetNCChangesCtr6 type for ctr");
+			return NULL;
+		}
+		s->chunk.ctr6                         = py_talloc_get_ptr(py_ctr);
+		s->partition.nc                       = *s->chunk.ctr6->naming_context;
+		s->partition.more_data                = s->chunk.ctr6->more_data;
+		s->partition.source_dsa_guid          = s->chunk.ctr6->source_dsa_guid;
+		s->partition.source_dsa_invocation_id = s->chunk.ctr6->source_dsa_invocation_id;
+		s->partition.highwatermark            = s->chunk.ctr6->new_highwatermark;
+		break;
+	default:
+		PyErr_Format(PyExc_TypeError, "Bad level %u in replicate_chunk", level);
+		return NULL;
+	}
+
+	chunk_handler = libnet_vampire_cb_store_chunk;
+	if (py_schema) {
+		if (!PyBool_Check(py_schema)) {
+			PyErr_SetString(PyExc_TypeError, "Expected boolean schema");
+			return NULL;
+		}
+		if (py_schema == Py_True) {
+			chunk_handler = libnet_vampire_cb_schema_chunk;
+		}
+	}
+
+	s->chunk.ctr_level = level;
+
+	status = chunk_handler(s->vampire_state, &s->chunk);
+	if (!NT_STATUS_IS_OK(status)) {
+		PyErr_Format(PyExc_TypeError, "Failed to process chunk: %s", nt_errstr(status));
+		return NULL;
+	}
 
 	return Py_None;
 }
@@ -365,8 +460,11 @@ static PyObject *py_net_replicate(py_net_Object *self, PyObject *args, PyObject
 static const char py_net_vampire_doc[] = "vampire(domain, target_dir=None)\n"
 					 "Vampire a domain.";
 
-static const char py_net_replicate_doc[] = "replicate(domain, netbios_name, domain_sid, realm, server, join_password, kvno, target_dir=None)\n"
-					 "Replicate a domain.";
+static const char py_net_replicate_init_doc[] = "replicate_init(samdb, lp, drspipe)\n"
+					 "Setup for replicate_chunk calls.";
+
+static const char py_net_replicate_chunk_doc[] = "replicate_chunk(state, level, ctr, schema)\n"
+					 "Process replication for one chunk";
 
 static PyMethodDef net_obj_methods[] = {
 	{"join", (PyCFunction)py_net_join, METH_VARARGS|METH_KEYWORDS, py_net_join_doc},
@@ -376,7 +474,8 @@ static PyMethodDef net_obj_methods[] = {
 	{"create_user", (PyCFunction)py_net_user_create, METH_VARARGS|METH_KEYWORDS, py_net_create_user_doc},
 	{"delete_user", (PyCFunction)py_net_user_delete, METH_VARARGS|METH_KEYWORDS, py_net_delete_user_doc},
 	{"vampire", (PyCFunction)py_net_vampire, METH_VARARGS|METH_KEYWORDS, py_net_vampire_doc},
-	{"replicate", (PyCFunction)py_net_replicate, METH_VARARGS|METH_KEYWORDS, py_net_replicate_doc},
+	{"replicate_init", (PyCFunction)py_net_replicate_init, METH_VARARGS|METH_KEYWORDS, py_net_replicate_init_doc},
+	{"replicate_chunk", (PyCFunction)py_net_replicate_chunk, METH_VARARGS|METH_KEYWORDS, py_net_replicate_chunk_doc},
 	{ NULL }
 };
 
diff --git a/source4/scripting/python/samba/join.py b/source4/scripting/python/samba/join.py
index 6eda582..12a944d 100644
--- a/source4/scripting/python/samba/join.py
+++ b/source4/scripting/python/samba/join.py
@@ -22,14 +22,21 @@ import samba.getopt as options
 from samba.auth import system_session
 from samba.samdb import SamDB
 from samba import gensec
-import ldb, samba
+import ldb, samba, sys
 from samba.ndr import ndr_pack, ndr_unpack, ndr_print
 from samba.dcerpc import security
 from samba.dcerpc import drsuapi, misc, netlogon
 from samba.credentials import Credentials, DONT_USE_KERBEROS
-from samba.provision import secretsdb_self_join
+from samba.provision import secretsdb_self_join, provision, FILL_DRS, find_setup_dir
+from samba.net import Net
+import logging
 
-def join_rodc(server=None, creds=None, lp=None, site=None, netbios_name=None):
+class join_ctx:
+    '''hold join context variables'''
+    pass
+
+def join_rodc(server=None, creds=None, lp=None, site=None, netbios_name=None,
+              targetdir=None):
     """join as a RODC"""
 
     if server is None:
@@ -42,19 +49,19 @@ def join_rodc(server=None, creds=None, lp=None, site=None, netbios_name=None):
         except:
             pass
 
-    def cleanup_old_join(samdb, acct_dn, server_dn, ntds_dn,
-                         krbtgt_dn, connection_dn, topology_dn):
+    def cleanup_old_join(ctx):
+        '''remove any DNs from a previous join'''
         try:
             # find the krbtgt link
-            res = samdb.search(base=acct_dn, scope=ldb.SCOPE_BASE, attrs=["msDS-krbTgtLink"])
-            del_noerror(samdb, acct_dn)
-            del_noerror(samdb, connection_dn)
-            del_noerror(samdb, krbtgt_dn)
-            del_noerror(samdb, ntds_dn)
-            del_noerror(samdb, server_dn)
-            del_noerror(samdb, topology_dn)
-            new_krbtgt_dn = res[0]["msDS-Krbtgtlink"][0]
-            del_noerror(samdb, new_krbtgt_dn)
+            res = ctx.samdb.search(base=ctx.acct_dn, scope=ldb.SCOPE_BASE, attrs=["msDS-krbTgtLink"])
+            del_noerror(ctx.samdb, ctx.acct_dn)
+            del_noerror(ctx.samdb, ctx.connection_dn)
+            del_noerror(ctx.samdb, ctx.krbtgt_dn)
+            del_noerror(ctx.samdb, ctx.ntds_dn)
+            del_noerror(ctx.samdb, ctx.server_dn)
+            del_noerror(ctx.samdb, ctx.topology_dn)
+            ctx.new_krbtgt_dn = res[0]["msDS-Krbtgtlink"][0]
+            del_noerror(ctx.samdb, ctx.new_krbtgt_dn)
         except:
             pass
 
@@ -71,6 +78,11 @@ def join_rodc(server=None, creds=None, lp=None, site=None, netbios_name=None):
         binsid = res[0]["tokenGroups"][0]
         return samdb.schema_format_value("objectSID", binsid)
 
+    def get_domain_name(samdb):
+        # this should be done via CLDAP
+        res = samdb.search(base=samdb.get_default_basedn(), scope=ldb.SCOPE_BASE, attrs=["name"])
+        return res[0]["name"][0]
+
     def do_DsBind(drs):
         '''make a DsBind call, returning the binding handle'''
         bind_info = drsuapi.DsBindInfoCtr()
@@ -107,183 +119,318 @@ def join_rodc(server=None, creds=None, lp=None, site=None, netbios_name=None):
         (info, handle) = drs.DsBind(misc.GUID(drsuapi.DRSUAPI_DS_BIND_GUID), bind_info)
         return handle
 
-
-    creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL)
-
-    samdb = SamDB(url="ldap://%s" % server,
-                  session_info=system_session(),
-                  credentials=creds, lp=lp)
-
-    myname = netbios_name
-    samname = "%s$" % myname
-    base_dn = str(samdb.get_default_basedn())
-    domsid = samdb.get_domain_sid()
-    dc_ntds_dn = get_dsServiceName(samdb)
-    dc_dnsHostName = get_dnsHostName(samdb)
-    acct_pass = samba.generate_random_password(12, 32)
-    mysid = get_mysid(samdb)
+    def get_rodc_partial_attribute_set(ctx):
+        '''get a list of attributes for RODC replication'''
+        partial_attribute_set = drsuapi.DsPartialAttributeSet()
+        partial_attribute_set.version = 1
+
+        ctx.attids = []
+
+        # the exact list of attids we send is quite critical. Note that
+        # we do ask for the secret attributes, but set set SPECIAL_SECRET_PROCESSING
+        # to zero them out
+        res = ctx.local_samdb.search(base=ctx.schema_dn, scope=ldb.SCOPE_SUBTREE,
+                                     expression="objectClass=attributeSchema",
+                                     attrs=["lDAPDisplayName", "systemFlags",
+                                            "searchFlags"])
+
+        for r in res:
+            ldap_display_name = r["lDAPDisplayName"][0]
+            if "systemFlags" in r:
+                system_flags      = r["systemFlags"][0]
+                if (int(system_flags) & (samba.dsdb.DS_FLAG_ATTR_NOT_REPLICATED |
+                                         samba.dsdb.DS_FLAG_ATTR_IS_CONSTRUCTED)):
+                    continue
+            search_flags = r["searchFlags"][0]
+            if (int(search_flags) & samba.dsdb.SEARCH_FLAG_RODC_ATTRIBUTE):
+                continue
+            attid = ctx.local_samdb.get_attid_from_lDAPDisplayName(ldap_display_name)
+            ctx.attids.append(int(attid))
+


-- 
Samba Shared Repository


More information about the samba-cvs mailing list