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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>

commit 4ab1a489c74079644c1fce5df1ced5a0bbbc9f39
Author: Andrew Tridgell <[email protected]>
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 <[email protected]>

commit 8438da96ba632671327506423239169402917c51
Author: Andrew Tridgell <[email protected]>
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 <[email protected]>

commit 495bd182f5e26cbcb721ab8209f8acad4d612726
Author: Andrew Tridgell <[email protected]>
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 <[email protected]>

commit 4cacdf00020c808ae8e3ef59378da682ce346133
Author: Andrew Tridgell <[email protected]>
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 <[email protected]>

commit 631c5f1fd5e77a6d380df3bc83dc166d902315af
Author: Andrew Tridgell <[email protected]>
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 <[email protected]>

commit e5a5ca028e645d2852a2a063730d4f51a3ee84b1
Author: Andrew Tridgell <[email protected]>
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

Reply via email to