summaryrefslogtreecommitdiff
path: root/source4/libnet
diff options
context:
space:
mode:
Diffstat (limited to 'source4/libnet')
-rw-r--r--source4/libnet/libnet_become_dc.c59
-rw-r--r--source4/libnet/libnet_become_dc.h4
-rw-r--r--source4/libnet/libnet_vampire.c2
3 files changed, 59 insertions, 6 deletions
diff --git a/source4/libnet/libnet_become_dc.c b/source4/libnet/libnet_become_dc.c
index b7205dca59..f3e4ec7ccd 100644
--- a/source4/libnet/libnet_become_dc.c
+++ b/source4/libnet/libnet_become_dc.c
@@ -729,6 +729,8 @@ struct libnet_BecomeDC_state {
struct libnet_BecomeDC_PrepareDB _pp;
struct libnet_BecomeDC_StoreChunk _sc;
struct libnet_BecomeDC_Callbacks callbacks;
+
+ bool rodc_join;
};
static int32_t get_dc_function_level(struct loadparm_context *lp_ctx)
@@ -1762,7 +1764,7 @@ static void becomeDC_drsuapi1_add_entry_send(struct libnet_BecomeDC_state *s)
if (composite_nomem(identifier->dn, c)) return;
/* allocate attribute array */
- num_attrs = 11;
+ num_attrs = 12;
attrs = talloc_array(r, struct drsuapi_DsReplicaAttribute, num_attrs);
if (composite_nomem(attrs, c)) return;
@@ -1846,7 +1848,7 @@ static void becomeDC_drsuapi1_add_entry_send(struct libnet_BecomeDC_state *s)
i++;
}
- /* objectClass: nTDSDSA */
+ /* objectClass: nTDSDSA or nTDSDSARO*/
{
struct drsuapi_DsAttributeValue *vs;
DATA_BLOB *vd;
@@ -1872,7 +1874,7 @@ static void becomeDC_drsuapi1_add_entry_send(struct libnet_BecomeDC_state *s)
i++;
}
- /* objectCategory: CN=NTDS-DSA,CN=Schema,... */
+ /* objectCategory: CN=NTDS-DSA,CN=Schema,... or CN=NTDS-DSA-RO,CN=Schema,... */
{
struct drsuapi_DsAttributeValue *vs;
DATA_BLOB *vd;
@@ -1886,8 +1888,14 @@ static void becomeDC_drsuapi1_add_entry_send(struct libnet_BecomeDC_state *s)
v[0].guid = GUID_zero();
v[0].sid = s->zero_sid;
- v[0].dn = talloc_asprintf(vd, "CN=NTDS-DSA,%s",
+
+ if (s->rodc_join) {
+ v[0].dn = talloc_asprintf(vd, "CN=NTDS-DSA-RO,%s",
s->forest.schema_dn_str);
+ } else {
+ v[0].dn = talloc_asprintf(vd, "CN=NTDS-DSA,%s",
+ s->forest.schema_dn_str);
+ }
if (composite_nomem(v[0].dn, c)) return;
ndr_err = ndr_push_struct_blob(&vd[0], vd, iconv_convenience, &v[0],
@@ -2147,7 +2155,11 @@ static void becomeDC_drsuapi1_add_entry_send(struct libnet_BecomeDC_state *s)
vd[0] = data_blob_talloc(vd, NULL, 4);
if (composite_nomem(vd[0].data, c)) return;
- SIVAL(vd[0].data, 0, SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
+ if (s->rodc_join) {
+ SIVAL(vd[0].data, 0, SYSTEM_FLAG_CONFIG_ALLOW_RENAME);
+ } else {
+ SIVAL(vd[0].data, 0, SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
+ }
vs[0].blob = &vd[0];
@@ -2190,6 +2202,31 @@ static void becomeDC_drsuapi1_add_entry_send(struct libnet_BecomeDC_state *s)
i++;
}
+ /* options:... */
+ if (s->rodc_join) {
+ struct drsuapi_DsAttributeValue *vs;
+ DATA_BLOB *vd;
+
+ vs = talloc_array(attrs, struct drsuapi_DsAttributeValue, 1);
+ if (composite_nomem(vs, c)) return;
+
+ vd = talloc_array(vs, DATA_BLOB, 1);
+ if (composite_nomem(vd, c)) return;
+
+ vd[0] = data_blob_talloc(vd, NULL, 4);
+ if (composite_nomem(vd[0].data, c)) return;
+
+ SIVAL(vd[0].data, 0, DS_NTDSDSA_OPT_DISABLE_OUTBOUND_REPL);
+
+ vs[0].blob = &vd[0];
+
+ attrs[i].attid = DRSUAPI_ATTRIBUTE_options;
+ attrs[i].value_ctr.num_values = 1;
+ attrs[i].value_ctr.values = vs;
+
+ i++;
+ }
+
/* truncate the attribute list to the attribute count we have filled in */
num_attrs = i;
@@ -2582,6 +2619,9 @@ static void becomeDC_drsuapi3_pull_schema_send(struct libnet_BecomeDC_state *s)
| DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS
| DRSUAPI_DRS_NEVER_SYNCED
| DRSUAPI_DRS_USE_COMPRESSION;
+ if (s->rodc_join) {
+ s->schema_part.replica_flags &= ~DRSUAPI_DRS_WRIT_REP;
+ }
s->schema_part.store_chunk = s->callbacks.schema_chunk;
@@ -2646,6 +2686,9 @@ static void becomeDC_drsuapi3_pull_config_send(struct libnet_BecomeDC_state *s)
| DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS
| DRSUAPI_DRS_NEVER_SYNCED
| DRSUAPI_DRS_USE_COMPRESSION;
+ if (s->rodc_join) {
+ s->schema_part.replica_flags &= ~DRSUAPI_DRS_WRIT_REP;
+ }
s->config_part.store_chunk = s->callbacks.config_chunk;
@@ -2708,6 +2751,9 @@ static void becomeDC_drsuapi3_pull_domain_send(struct libnet_BecomeDC_state *s)
| DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS
| DRSUAPI_DRS_NEVER_SYNCED
| DRSUAPI_DRS_USE_COMPRESSION;
+ if (s->rodc_join) {
+ s->schema_part.replica_flags &= ~DRSUAPI_DRS_WRIT_REP;
+ }
s->domain_part.store_chunk = s->callbacks.domain_chunk;
@@ -3017,6 +3063,9 @@ struct composite_context *libnet_BecomeDC_send(struct libnet_context *ctx, TALLO
/* Callback function pointers */
s->callbacks = r->in.callbacks;
+ /* RODC join*/
+ s->rodc_join = r->in.rodc_join;
+
becomeDC_send_cldap(s);
return c;
}
diff --git a/source4/libnet/libnet_become_dc.h b/source4/libnet/libnet_become_dc.h
index 58fc4dc15d..604813f6bc 100644
--- a/source4/libnet/libnet_become_dc.h
+++ b/source4/libnet/libnet_become_dc.h
@@ -136,7 +136,9 @@ struct libnet_BecomeDC {
const char *dest_dsa_netbios_name;
struct libnet_BecomeDC_Callbacks callbacks;
- } in;
+
+ bool rodc_join;
+ } in;
struct {
const char *error_string;
diff --git a/source4/libnet/libnet_vampire.c b/source4/libnet/libnet_vampire.c
index e38488771e..9554a63b3c 100644
--- a/source4/libnet/libnet_vampire.c
+++ b/source4/libnet/libnet_vampire.c
@@ -686,6 +686,8 @@ NTSTATUS libnet_Vampire(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
b.in.callbacks.config_chunk = vampire_store_chunk;
b.in.callbacks.domain_chunk = vampire_store_chunk;
+ b.in.rodc_join = lp_parm_bool(s->lp_ctx, NULL, "repl", "RODC", false);
+
status = libnet_BecomeDC(ctx, s, &b);
if (!NT_STATUS_IS_OK(status)) {
printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));