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