#include "lib/ldb/include/ldb_errors.h"
#include "lib/ldb_wrap.h"
#include "dsdb/samdb/samdb.h"
-#include "dsdb/common/flags.h"
+#include "../libds/common/flags.h"
#include "librpc/gen_ndr/ndr_drsuapi_c.h"
#include "libcli/security/security.h"
#include "librpc/gen_ndr/ndr_misc.h"
* name: <new_dc_site_name>
* objectGUID: <object_guid>
* systemFlags: 1107296256 <0x42000000>
- * objectCategory: CN=Site,C=Schema,CN=Configuration,<domain_partition>
+ * objectCategory: CN=Site,CN=Schema,CN=Configuration,<domain_partition>
*/
/***************************************************************
struct libnet_BecomeDC_Callbacks callbacks;
};
+static int32_t get_dc_function_level(struct loadparm_context *lp_ctx)
+{
+ /* per default we are (Windows) 2008 compatible */
+ return lp_parm_int(lp_ctx, NULL, "ads", "dc function level",
+ DS_DC_FUNCTION_2008);
+}
+
+static int32_t get_min_function_level(struct loadparm_context *lp_ctx)
+{
+ /* per default it is (Windows) 2003 Native compatible */
+ return lp_parm_int(lp_ctx, NULL, "ads", "min function level",
+ DS_DOMAIN_FUNCTION_2003);
+}
+
static void becomeDC_recv_cldap(struct tevent_req *req);
static void becomeDC_send_cldap(struct libnet_BecomeDC_state *s)
lp_iconv_convenience(s->libnet->lp_ctx),
s, &s->cldap.io);
talloc_free(req);
- if (!composite_is_ok(c)) return;
-
+ if (!composite_is_ok(c)) {
+ DEBUG(0,("Failed to send, receive or parse CLDAP reply from server %s for our host %s: %s\n",
+ s->cldap.io.in.dest_address,
+ s->cldap.io.in.host,
+ nt_errstr(c->status)));
+ return;
+ }
s->cldap.netlogon = s->cldap.io.out.netlogon.data.nt5_ex;
s->domain.dns_name = s->cldap.netlogon.dns_domain;
ldap->ldb = ldb_wrap_connect(s, s->libnet->event_ctx, s->libnet->lp_ctx, url,
NULL,
s->libnet->cred,
- 0, NULL);
+ 0);
talloc_free(url);
if (ldap->ldb == NULL) {
return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
}
s->forest.crossref_behavior_version = ldb_msg_find_attr_as_uint(r->msgs[0], "msDs-Behavior-Version", 0);
+ if (s->forest.crossref_behavior_version <
+ get_min_function_level(s->libnet->lp_ctx)) {
+ talloc_free(r);
+ DEBUG(0,("The servers function level %u is below 'ads:min function level' of %u\n",
+ s->forest.crossref_behavior_version,
+ get_min_function_level(s->libnet->lp_ctx)));
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+ if (s->forest.crossref_behavior_version >
+ get_dc_function_level(s->libnet->lp_ctx)) {
+ talloc_free(r);
+ DEBUG(0,("The servers function level %u is above 'ads:dc function level' of %u\n",
+ s->forest.crossref_behavior_version,
+ get_dc_function_level(s->libnet->lp_ctx)));
+ return NT_STATUS_NOT_SUPPORTED;
+ }
talloc_free(r);
return NT_STATUS_OK;
}
s->domain.behavior_version = ldb_msg_find_attr_as_uint(r->msgs[0], "msDs-Behavior-Version", 0);
+ if (s->domain.behavior_version <
+ get_min_function_level(s->libnet->lp_ctx)) {
+ talloc_free(r);
+ DEBUG(0,("The servers function level %u is below 'ads:min function level' of %u\n",
+ s->forest.crossref_behavior_version,
+ get_min_function_level(s->libnet->lp_ctx)));
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+ if (s->domain.behavior_version >
+ get_dc_function_level(s->libnet->lp_ctx)) {
+ talloc_free(r);
+ DEBUG(0,("The servers function level %u is above 'ads:dc function level' of %u\n",
+ s->forest.crossref_behavior_version,
+ get_dc_function_level(s->libnet->lp_ctx)));
+ return NT_STATUS_NOT_SUPPORTED;
+ }
talloc_free(r);
return NT_STATUS_OK;
struct ldb_dn *basedn;
struct ldb_dn *ntds_dn;
struct ldb_dn *server_dn;
- static const char *_1_1_attrs[] = {
- "1.1",
- NULL
- };
- static const char *fsmo_attrs[] = {
- "fSMORoleOwner",
- NULL
- };
static const char *dns_attrs[] = {
"dnsHostName",
NULL
NULL
};
- basedn = ldb_dn_new_fmt(s, s->ldap1.ldb, "<WKGUID=2fbac1870ade11d297c400c04fd8d5cd,%s>",
- s->domain.dn_str);
- NT_STATUS_HAVE_NO_MEMORY(basedn);
-
- ret = ldb_search(s->ldap1.ldb, s, &r, basedn, LDB_SCOPE_BASE,
- _1_1_attrs, "(objectClass=*)");
- talloc_free(basedn);
+ ret = dsdb_wellknown_dn(s->ldap1.ldb, s, samdb_base_dn(s->ldap1.ldb),
+ DS_GUID_INFRASTRUCTURE_CONTAINER,
+ &basedn);
if (ret != LDB_SUCCESS) {
return NT_STATUS_LDAP(ret);
- } else if (r->count != 1) {
- talloc_free(r);
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
}
- basedn = talloc_steal(s, r->msgs[0]->dn);
- talloc_free(r);
-
- ret = ldb_search(s->ldap1.ldb, s, &r, basedn, LDB_SCOPE_BASE,
- fsmo_attrs, "(objectClass=*)");
- talloc_free(basedn);
+ ret = samdb_reference_dn(s->ldap1.ldb, s, basedn, "fSMORoleOwner", &ntds_dn);
if (ret != LDB_SUCCESS) {
+ talloc_free(basedn);
return NT_STATUS_LDAP(ret);
- } else if (r->count != 1) {
- talloc_free(r);
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
}
- s->infrastructure_fsmo.ntds_dn_str = samdb_result_string(r->msgs[0], "fSMORoleOwner", NULL);
- if (!s->infrastructure_fsmo.ntds_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
- talloc_steal(s, s->infrastructure_fsmo.ntds_dn_str);
-
- talloc_free(r);
-
- ntds_dn = ldb_dn_new(s, s->ldap1.ldb, s->infrastructure_fsmo.ntds_dn_str);
- NT_STATUS_HAVE_NO_MEMORY(ntds_dn);
+ s->infrastructure_fsmo.ntds_dn_str = ldb_dn_get_linearized(ntds_dn);
+ NT_STATUS_HAVE_NO_MEMORY(s->infrastructure_fsmo.ntds_dn_str);
server_dn = ldb_dn_get_parent(s, ntds_dn);
NT_STATUS_HAVE_NO_MEMORY(server_dn);
NT_STATUS_HAVE_NO_MEMORY(computer_dn);
/*
- * if the server object belongs to another DC in another domain in the forest,
- * we should not touch this object!
+ * if the server object belongs to another DC in another domain
+ * in the forest, we should not touch this object!
*/
if (ldb_dn_compare(computer_dn, server_reference_dn) != 0) {
talloc_free(r);
* Note: Replication only works with Windows 2000 when 'krb5' is
* passed as auth_type here. If NTLMSSP is used, Windows
* 2000 returns garbage in the DsGetNCChanges() response
- * if encrypted password attributes would be in the response.
- * That means the replication of the schema and configuration
- * partition works fine, but it fails for the domain partition.
+ * if encrypted password attributes would be in the
+ * response. That means the replication of the schema and
+ * configuration partition works fine, but it fails for
+ * the domain partition.
*/
if (lp_parm_bool(s->libnet->lp_ctx, NULL, "become_dc",
"force krb5", true))
bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION;
bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE;
bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2;
- if (s->domain.behavior_version == 2) {
+ if (s->domain.behavior_version >= DS_DOMAIN_FUNCTION_2003) {
/* TODO: find out how this is really triggered! */
bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION;
}
s->dest_dsa.invocation_id = GUID_random();
/*
- * if the schema version indicates w2k3, then
- * also send some w2k3 specific attributes
+ * if the schema version indicates w2k3, then also send some w2k3
+ * specific attributes.
*/
if (s->forest.schema_object_version >= 30) {
w2k3 = true;
v = &s->dest_dsa.invocation_id;
- ndr_err = ndr_push_struct_blob(&vd[0], vd, iconv_convenience, v, (ndr_push_flags_fn_t)ndr_push_GUID);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- c->status = ndr_map_error2ntstatus(ndr_err);
- if (!composite_is_ok(c)) return;
- }
+ c->status = GUID_to_ndr_blob(v, vd, &vd[0]);
+ if (!composite_is_ok(c)) return;
vs[0].blob = &vd[0];
vd[0] = data_blob_talloc(vd, NULL, 4);
if (composite_nomem(vd[0].data, c)) return;
- SIVAL(vd[0].data, 0, DS_BEHAVIOR_WIN2008);
+ SIVAL(vd[0].data, 0, get_dc_function_level(s->libnet->lp_ctx));
vs[0].blob = &vd[0];
uint32_t ctr_level = 0;
struct drsuapi_DsGetNCChangesCtr1 *ctr1 = NULL;
struct drsuapi_DsGetNCChangesCtr6 *ctr6 = NULL;
- struct GUID *source_dsa_guid;
- struct GUID *source_dsa_invocation_id;
- struct drsuapi_DsReplicaHighWaterMark *new_highwatermark;
+ struct GUID *source_dsa_guid = NULL;
+ struct GUID *source_dsa_invocation_id = NULL;
+ struct drsuapi_DsReplicaHighWaterMark *new_highwatermark = NULL;
bool more_data = false;
NTSTATUS nt_status;
r->in.req.req1.naming_context = &partition->nc;
r->in.req.req1.dest_dsa_dns_name= ntds_dns_name;
r->in.req.req1.dest_dsa_guid = s->dest_dsa.ntds_guid;
- r->in.req.req1.options = DRSUAPI_DS_REPLICA_UPDATE_ADD_REFERENCE
- | DRSUAPI_DS_REPLICA_UPDATE_DELETE_REFERENCE
- | DRSUAPI_DS_REPLICA_UPDATE_0x00000010;
+ r->in.req.req1.options = DRSUAPI_DRS_ADD_REF | DRSUAPI_DRS_DEL_REF;
+
+ /* I think this is how we mark ourselves as a RODC */
+ if (!lp_parm_bool(s->libnet->lp_ctx, NULL, "repl", "RODC", false)) {
+ r->in.req.req1.options |= DRSUAPI_DRS_WRIT_REP;
+ }
req = dcerpc_drsuapi_DsReplicaUpdateRefs_send(drsuapi->pipe, r, r);
composite_continue_rpc(c, req, recv_fn, s);
static NTSTATUS becomeDC_ldap2_move_computer(struct libnet_BecomeDC_state *s)
{
int ret;
- struct ldb_result *r;
- struct ldb_dn *basedn;
struct ldb_dn *old_dn;
struct ldb_dn *new_dn;
- static const char *_1_1_attrs[] = {
- "1.1",
- NULL
- };
- basedn = ldb_dn_new_fmt(s, s->ldap2.ldb, "<WKGUID=a361b2ffffd211d1aa4b00c04fd7d83a,%s>",
- s->domain.dn_str);
- NT_STATUS_HAVE_NO_MEMORY(basedn);
-
- ret = ldb_search(s->ldap2.ldb, s, &r, basedn, LDB_SCOPE_BASE,
- _1_1_attrs, "(objectClass=*)");
- talloc_free(basedn);
+ ret = dsdb_wellknown_dn(s->ldap2.ldb, s, samdb_base_dn(s->ldap2.ldb),
+ DS_GUID_DOMAIN_CONTROLLERS_CONTAINER,
+ &new_dn);
if (ret != LDB_SUCCESS) {
return NT_STATUS_LDAP(ret);
- } else if (r->count != 1) {
- talloc_free(r);
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
}
- old_dn = ldb_dn_new(r, s->ldap2.ldb, s->dest_dsa.computer_dn_str);
- NT_STATUS_HAVE_NO_MEMORY(old_dn);
-
- new_dn = r->msgs[0]->dn;
-
if (!ldb_dn_add_child_fmt(new_dn, "CN=%s", s->dest_dsa.netbios_name)) {
- talloc_free(r);
+ talloc_free(new_dn);
return NT_STATUS_NO_MEMORY;
}
+ old_dn = ldb_dn_new(new_dn, s->ldap2.ldb, s->dest_dsa.computer_dn_str);
+ NT_STATUS_HAVE_NO_MEMORY(old_dn);
+
if (ldb_dn_compare(old_dn, new_dn) == 0) {
/* we don't need to rename if the old and new dn match */
- talloc_free(r);
+ talloc_free(new_dn);
return NT_STATUS_OK;
}
ret = ldb_rename(s->ldap2.ldb, old_dn, new_dn);
if (ret != LDB_SUCCESS) {
- talloc_free(r);
+ talloc_free(new_dn);
return NT_STATUS_LDAP(ret);
}
s->dest_dsa.computer_dn_str = ldb_dn_alloc_linearized(s, new_dn);
NT_STATUS_HAVE_NO_MEMORY(s->dest_dsa.computer_dn_str);
- talloc_free(r);
+ talloc_free(new_dn);
return NT_STATUS_OK;
}