diff options
Diffstat (limited to 'source4/libnet')
-rw-r--r-- | source4/libnet/libnet_become_dc.c | 59 | ||||
-rw-r--r-- | source4/libnet/libnet_become_dc.h | 4 | ||||
-rw-r--r-- | source4/libnet/libnet_vampire.c | 2 |
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)); |