2 Unix SMB/CIFS implementation.
4 Extract the user/system database from a remote server
6 Copyright (C) Stefan Metzmacher 2004-2006
7 Copyright (C) Brad Henry 2005
8 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2008
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "libnet/libnet.h"
27 #include "lib/events/events.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "../lib/util/dlinklist.h"
31 #include <ldb_errors.h>
32 #include "librpc/ndr/libndr.h"
33 #include "librpc/gen_ndr/ndr_drsuapi.h"
34 #include "librpc/gen_ndr/ndr_drsblobs.h"
35 #include "librpc/gen_ndr/ndr_misc.h"
36 #include "system/time.h"
38 #include "auth/auth.h"
39 #include "auth/credentials/credentials.h"
40 #include "param/param.h"
41 #include "param/provision.h"
42 #include "libcli/security/security.h"
43 #include "dsdb/common/util.h"
46 List of tasks vampire.py must perform:
48 - but don't write the secrets.ldb
49 - results for this should be enough to handle the provision
50 - if vampire method is samsync
51 - Provision using these results
52 - do we still want to support this NT4 technology?
53 - Start samsync with libnet code
54 - provision in the callback
55 - Write out the secrets database, using the code from libnet_Join
58 struct libnet_vampire_cb_state
{
59 const char *netbios_name
;
60 const char *domain_name
;
62 struct cli_credentials
*machine_account
;
64 /* Schema loaded from local LDIF files */
65 struct dsdb_schema
*provision_schema
;
67 /* 1st pass, with some OIDs/attribute names/class names not
68 * converted, because we may not know them yet */
69 struct dsdb_schema
*self_made_schema
;
71 /* prefixMap in LDB format, from the remote DRS server */
72 DATA_BLOB prefixmap_blob
;
73 const struct dsdb_schema
*schema
;
75 struct ldb_context
*ldb
;
78 uint32_t object_count
;
79 struct drsuapi_DsReplicaObjectListItemEx
*first_object
;
80 struct drsuapi_DsReplicaObjectListItemEx
*last_object
;
83 const char *targetdir
;
85 struct loadparm_context
*lp_ctx
;
86 struct tevent_context
*event_ctx
;
87 unsigned total_objects
;
89 const char *server_dn_str
;
92 /* initialise a state structure ready for replication of chunks */
93 void *libnet_vampire_replicate_init(TALLOC_CTX
*mem_ctx
,
94 struct ldb_context
*samdb
,
95 struct loadparm_context
*lp_ctx
)
97 struct libnet_vampire_cb_state
*s
= talloc_zero(mem_ctx
, struct libnet_vampire_cb_state
);
104 s
->provision_schema
= dsdb_get_schema(s
->ldb
, s
);
105 s
->schema
= s
->provision_schema
;
106 s
->netbios_name
= lpcfg_netbios_name(lp_ctx
);
107 s
->domain_name
= lpcfg_workgroup(lp_ctx
);
108 s
->realm
= lpcfg_realm(lp_ctx
);
113 /* Caller is expected to keep supplied pointers around for the lifetime of the structure */
114 void *libnet_vampire_cb_state_init(TALLOC_CTX
*mem_ctx
,
115 struct loadparm_context
*lp_ctx
, struct tevent_context
*event_ctx
,
116 const char *netbios_name
, const char *domain_name
, const char *realm
,
117 const char *targetdir
)
119 struct libnet_vampire_cb_state
*s
= talloc_zero(mem_ctx
, struct libnet_vampire_cb_state
);
125 s
->event_ctx
= event_ctx
;
126 s
->netbios_name
= netbios_name
;
127 s
->domain_name
= domain_name
;
129 s
->targetdir
= targetdir
;
133 struct ldb_context
*libnet_vampire_cb_ldb(struct libnet_vampire_cb_state
*state
)
135 state
= talloc_get_type_abort(state
, struct libnet_vampire_cb_state
);
139 struct loadparm_context
*libnet_vampire_cb_lp_ctx(struct libnet_vampire_cb_state
*state
)
141 state
= talloc_get_type_abort(state
, struct libnet_vampire_cb_state
);
142 return state
->lp_ctx
;
145 NTSTATUS
libnet_vampire_cb_prepare_db(void *private_data
,
146 const struct libnet_BecomeDC_PrepareDB
*p
)
148 struct libnet_vampire_cb_state
*s
= talloc_get_type(private_data
, struct libnet_vampire_cb_state
);
149 struct provision_settings settings
;
150 struct provision_result result
;
153 ZERO_STRUCT(settings
);
154 settings
.site_name
= p
->dest_dsa
->site_name
;
155 settings
.root_dn_str
= p
->forest
->root_dn_str
;
156 settings
.domain_dn_str
= p
->domain
->dn_str
;
157 settings
.config_dn_str
= p
->forest
->config_dn_str
;
158 settings
.schema_dn_str
= p
->forest
->schema_dn_str
;
159 settings
.netbios_name
= p
->dest_dsa
->netbios_name
;
160 settings
.realm
= s
->realm
;
161 settings
.domain
= s
->domain_name
;
162 settings
.server_dn_str
= p
->dest_dsa
->server_dn_str
;
163 settings
.machine_password
= generate_random_password(s
, 16, 255);
164 settings
.targetdir
= s
->targetdir
;
165 settings
.use_ntvfs
= true;
166 status
= provision_bare(s
, s
->lp_ctx
, &settings
, &result
);
168 if (!NT_STATUS_IS_OK(status
)) {
172 s
->ldb
= talloc_steal(s
, result
.samdb
);
173 s
->lp_ctx
= talloc_reparent(talloc_parent(result
.lp_ctx
), s
, result
.lp_ctx
);
174 s
->provision_schema
= dsdb_get_schema(s
->ldb
, s
);
175 s
->server_dn_str
= talloc_steal(s
, p
->dest_dsa
->server_dn_str
);
177 /* wrap the entire vapire operation in a transaction. This
178 isn't just cosmetic - we use this to ensure that linked
179 attribute back links are added at the end by relying on a
180 transaction commit hook in the linked attributes module. We
181 need to do this as the order of objects coming from the
182 server is not sufficiently deterministic to know that the
183 record that a backlink needs to be created in has itself
184 been created before the object containing the forward link
185 has come over the wire */
186 if (ldb_transaction_start(s
->ldb
) != LDB_SUCCESS
) {
187 return NT_STATUS_FOOBAR
;
195 NTSTATUS
libnet_vampire_cb_check_options(void *private_data
,
196 const struct libnet_BecomeDC_CheckOptions
*o
)
198 struct libnet_vampire_cb_state
*s
= talloc_get_type(private_data
, struct libnet_vampire_cb_state
);
200 DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
202 o
->domain
->netbios_name
, o
->domain
->dns_name
));
204 DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
205 o
->source_dsa
->dns_name
, o
->source_dsa
->site_name
));
207 DEBUG(0,("Options:crossRef behavior_version[%u]\n"
208 "\tschema object_version[%u]\n"
209 "\tdomain behavior_version[%u]\n"
210 "\tdomain w2k3_update_revision[%u]\n",
211 o
->forest
->crossref_behavior_version
,
212 o
->forest
->schema_object_version
,
213 o
->domain
->behavior_version
,
214 o
->domain
->w2k3_update_revision
));
219 static NTSTATUS
libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state
*s
,
220 const struct libnet_BecomeDC_StoreChunk
*c
)
223 struct schema_list
*next
, *prev
;
224 const struct drsuapi_DsReplicaObjectListItemEx
*obj
;
228 struct dsdb_schema_prefixmap
*pfm_remote
;
229 const struct drsuapi_DsReplicaOIDMapping_Ctr
*mapping_ctr
;
230 struct schema_list
*schema_list
= NULL
, *schema_list_item
, *schema_list_next_item
;
231 struct dsdb_schema
*working_schema
;
232 struct dsdb_schema
*provision_schema
;
233 uint32_t object_count
= 0;
234 struct drsuapi_DsReplicaObjectListItemEx
*first_object
;
235 const struct drsuapi_DsReplicaObjectListItemEx
*cur
;
236 uint32_t linked_attributes_count
;
237 struct drsuapi_DsReplicaLinkedAttribute
*linked_attributes
;
238 const struct drsuapi_DsReplicaCursor2CtrEx
*uptodateness_vector
;
239 struct dsdb_extended_replicated_objects
*schema_objs
;
240 struct repsFromTo1
*s_dsa
;
242 struct ldb_context
*schema_ldb
;
243 struct ldb_message
*msg
;
244 struct ldb_message_element
*prefixMap_el
;
249 uint32_t ignore_attids
[] = {
250 DRSUAPI_ATTID_auxiliaryClass
,
251 DRSUAPI_ATTID_mayContain
,
252 DRSUAPI_ATTID_mustContain
,
253 DRSUAPI_ATTID_possSuperiors
,
254 DRSUAPI_ATTID_systemPossSuperiors
,
255 DRSUAPI_ATTID_INVALID
258 DEBUG(0,("Analyze and apply schema objects\n"));
260 s_dsa
= talloc_zero(s
, struct repsFromTo1
);
261 NT_STATUS_HAVE_NO_MEMORY(s_dsa
);
262 s_dsa
->other_info
= talloc(s_dsa
, struct repsFromTo1OtherInfo
);
263 NT_STATUS_HAVE_NO_MEMORY(s_dsa
->other_info
);
265 switch (c
->ctr_level
) {
267 mapping_ctr
= &c
->ctr1
->mapping_ctr
;
268 object_count
= s
->schema_part
.object_count
;
269 first_object
= s
->schema_part
.first_object
;
270 linked_attributes_count
= 0;
271 linked_attributes
= NULL
;
272 s_dsa
->highwatermark
= c
->ctr1
->new_highwatermark
;
273 s_dsa
->source_dsa_obj_guid
= c
->ctr1
->source_dsa_guid
;
274 s_dsa
->source_dsa_invocation_id
= c
->ctr1
->source_dsa_invocation_id
;
275 uptodateness_vector
= NULL
; /* TODO: map it */
278 mapping_ctr
= &c
->ctr6
->mapping_ctr
;
279 object_count
= s
->schema_part
.object_count
;
280 first_object
= s
->schema_part
.first_object
;
281 linked_attributes_count
= c
->ctr6
->linked_attributes_count
;
282 linked_attributes
= c
->ctr6
->linked_attributes
;
283 s_dsa
->highwatermark
= c
->ctr6
->new_highwatermark
;
284 s_dsa
->source_dsa_obj_guid
= c
->ctr6
->source_dsa_guid
;
285 s_dsa
->source_dsa_invocation_id
= c
->ctr6
->source_dsa_invocation_id
;
286 uptodateness_vector
= c
->ctr6
->uptodateness_vector
;
289 return NT_STATUS_INVALID_PARAMETER
;
292 status
= dsdb_schema_pfm_from_drsuapi_pfm(mapping_ctr
, true,
293 s
, &pfm_remote
, NULL
);
294 if (!W_ERROR_IS_OK(status
)) {
295 DEBUG(0,(__location__
": Failed to decode remote prefixMap: %s",
296 win_errstr(status
)));
297 return werror_to_ntstatus(status
);
300 s_dsa
->replica_flags
= DRSUAPI_DRS_WRIT_REP
301 | DRSUAPI_DRS_INIT_SYNC
302 | DRSUAPI_DRS_PER_SYNC
;
303 memset(s_dsa
->schedule
, 0x11, sizeof(s_dsa
->schedule
));
305 tmp_dns_name
= GUID_string(s_dsa
->other_info
, &s_dsa
->source_dsa_obj_guid
);
306 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name
);
307 tmp_dns_name
= talloc_asprintf_append_buffer(tmp_dns_name
, "._msdcs.%s", c
->forest
->dns_name
);
308 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name
);
309 s_dsa
->other_info
->dns_name
= tmp_dns_name
;
311 schema_ldb
= provision_get_schema(s
, s
->lp_ctx
,
312 c
->forest
->schema_dn_str
,
315 DEBUG(0,("Failed to re-load from local provision using remote prefixMap. "
316 "Will continue with local prefixMap\n"));
317 provision_schema
= dsdb_get_schema(s
->ldb
, s
);
319 provision_schema
= dsdb_get_schema(schema_ldb
, s
);
320 ret
= dsdb_reference_schema(s
->ldb
, provision_schema
, false);
321 if (ret
!= LDB_SUCCESS
) {
322 DEBUG(0,("Failed to attach schema from local provision using remote prefixMap."));
323 return NT_STATUS_UNSUCCESSFUL
;
325 talloc_free(schema_ldb
);
328 /* create a list of objects yet to be converted */
329 for (cur
= first_object
; cur
; cur
= cur
->next_object
) {
330 schema_list_item
= talloc(s
, struct schema_list
);
331 schema_list_item
->obj
= cur
;
332 DLIST_ADD_END(schema_list
, schema_list_item
, struct schema_list
);
335 /* resolve objects until all are resolved and in local schema */
337 working_schema
= provision_schema
;
339 while (schema_list
) {
340 uint32_t converted_obj_count
= 0;
341 uint32_t failed_obj_count
= 0;
342 TALLOC_CTX
*tmp_ctx
= talloc_new(s
);
343 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx
);
345 for (schema_list_item
= schema_list
; schema_list_item
; schema_list_item
=schema_list_next_item
) {
346 struct dsdb_extended_replicated_object object
;
348 cur
= schema_list_item
->obj
;
350 /* Save the next item, now we have saved out
351 * the current one, so we can DLIST_REMOVE it
353 schema_list_next_item
= schema_list_item
->next
;
356 * Convert the objects into LDB messages using the
357 * schema we have so far. It's ok if we fail to convert
358 * an object. We should convert more objects on next pass.
360 status
= dsdb_convert_object_ex(s
->ldb
, working_schema
, pfm_remote
,
365 if (!W_ERROR_IS_OK(status
)) {
366 DEBUG(1,("Warning: Failed to convert schema object %s into ldb msg\n",
367 cur
->object
.identifier
->dn
));
372 * Convert the schema from ldb_message format
373 * (OIDs as OID strings) into schema, using
374 * the remote prefixMap
376 status
= dsdb_schema_set_el_from_ldb_msg(s
->ldb
,
379 if (!W_ERROR_IS_OK(status
)) {
380 DEBUG(1,("Warning: failed to convert object %s into a schema element: %s\n",
381 ldb_dn_get_linearized(object
.msg
->dn
),
382 win_errstr(status
)));
385 DLIST_REMOVE(schema_list
, schema_list_item
);
386 converted_obj_count
++;
390 talloc_free(tmp_ctx
);
392 DEBUG(4,("Schema load pass %d: %d/%d of %d objects left to be converted.\n",
393 pass_no
, failed_obj_count
, converted_obj_count
, object_count
));
396 /* check if we converted any objects in this pass */
397 if (converted_obj_count
== 0) {
398 DEBUG(0,("Can't continue Schema load: didn't manage to convert any objects: all %d remaining of %d objects failed to convert\n", failed_obj_count
, object_count
));
399 return NT_STATUS_INTERNAL_ERROR
;
403 /* prepare for another cycle */
404 working_schema
= s
->self_made_schema
;
406 ret
= dsdb_setup_sorted_accessors(s
->ldb
, working_schema
);
407 if (LDB_SUCCESS
!= ret
) {
408 DEBUG(0,("Failed to create schema-cache indexes!\n"));
409 return NT_STATUS_INTERNAL_ERROR
;
414 /* free temp objects for 1st conversion phase */
415 talloc_unlink(s
, provision_schema
);
416 TALLOC_FREE(schema_list
);
419 * attach the schema we just brought over DRS to the ldb,
420 * so we can use it in dsdb_convert_object_ex below
422 ret
= dsdb_set_schema(s
->ldb
, s
->self_made_schema
);
423 if (ret
!= LDB_SUCCESS
) {
424 DEBUG(0,("Failed to attach working schema from DRS.\n"));
425 return NT_STATUS_FOOBAR
;
428 /* we don't want to access the self made schema anymore */
429 s
->schema
= s
->self_made_schema
;
430 s
->self_made_schema
= NULL
;
432 /* Now convert the schema elements again, using the schema we finalised, ready to actually import */
433 status
= dsdb_replicated_objects_convert(s
->ldb
,
439 linked_attributes_count
,
446 if (!W_ERROR_IS_OK(status
)) {
447 DEBUG(0,("Failed to convert objects when trying to import over DRS (2nd pass, to store remote schema): %s\n", win_errstr(status
)));
448 return werror_to_ntstatus(status
);
451 if (lpcfg_parm_bool(s
->lp_ctx
, NULL
, "become dc", "dump objects", false)) {
452 for (i
=0; i
< schema_objs
->num_objects
; i
++) {
453 struct ldb_ldif ldif
;
454 fprintf(stdout
, "#\n");
455 ldif
.changetype
= LDB_CHANGETYPE_NONE
;
456 ldif
.msg
= schema_objs
->objects
[i
].msg
;
457 ldb_ldif_write_file(s
->ldb
, stdout
, &ldif
);
458 NDR_PRINT_DEBUG(replPropertyMetaDataBlob
, schema_objs
->objects
[i
].meta_data
);
462 status
= dsdb_replicated_objects_commit(s
->ldb
, NULL
, schema_objs
, &seq_num
);
463 if (!W_ERROR_IS_OK(status
)) {
464 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status
)));
465 return werror_to_ntstatus(status
);
468 msg
= ldb_msg_new(schema_objs
);
469 NT_STATUS_HAVE_NO_MEMORY(msg
);
470 msg
->dn
= schema_objs
->partition_dn
;
472 /* We must ensure a prefixMap has been written. Unlike other
473 * attributes (including schemaInfo), it is not replicated in
474 * the normal replication stream. We can use the one from
475 * s->prefixmap_blob because we operate with one, unchanging
476 * prefixMap for this entire operation. */
477 ret
= ldb_msg_add_value(msg
, "prefixMap", &s
->prefixmap_blob
, &prefixMap_el
);
478 if (ret
!= LDB_SUCCESS
) {
479 return NT_STATUS_FOOBAR
;
481 /* We want to know if a prefixMap was written already, as it
482 * would mean that the above comment was not true, and we have
483 * somehow updated the prefixMap during this transaction */
484 prefixMap_el
->flags
= LDB_FLAG_MOD_ADD
;
486 ret
= dsdb_modify(s
->ldb
, msg
, DSDB_FLAG_AS_SYSTEM
);
487 if (ret
!= LDB_SUCCESS
) {
488 DEBUG(0,("Failed to add prefixMap: %s\n", ldb_errstring(s
->ldb
)));
489 return NT_STATUS_FOOBAR
;
493 talloc_free(schema_objs
);
495 /* We must set these up to ensure the replMetaData is written
496 * correctly, before our NTDS Settings entry is replicated */
497 ok
= samdb_set_ntds_invocation_id(s
->ldb
, &c
->dest_dsa
->invocation_id
);
499 DEBUG(0,("Failed to set cached ntds invocationId\n"));
500 return NT_STATUS_FOOBAR
;
502 ok
= samdb_set_ntds_objectGUID(s
->ldb
, &c
->dest_dsa
->ntds_guid
);
504 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
505 return NT_STATUS_FOOBAR
;
508 s
->schema
= dsdb_get_schema(s
->ldb
, s
);
510 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
511 return NT_STATUS_FOOBAR
;
517 NTSTATUS
libnet_vampire_cb_schema_chunk(void *private_data
,
518 const struct libnet_BecomeDC_StoreChunk
*c
)
520 struct libnet_vampire_cb_state
*s
= talloc_get_type(private_data
, struct libnet_vampire_cb_state
);
522 const struct drsuapi_DsReplicaOIDMapping_Ctr
*mapping_ctr
;
523 uint32_t nc_object_count
;
524 uint32_t nc_total_received
= 0;
525 uint32_t object_count
;
526 struct drsuapi_DsReplicaObjectListItemEx
*first_object
;
527 struct drsuapi_DsReplicaObjectListItemEx
*cur
;
528 uint32_t nc_linked_attributes_count
;
529 uint32_t linked_attributes_count
;
530 struct drsuapi_DsReplicaLinkedAttribute
*linked_attributes
;
532 switch (c
->ctr_level
) {
534 mapping_ctr
= &c
->ctr1
->mapping_ctr
;
535 nc_object_count
= c
->ctr1
->extended_ret
; /* maybe w2k send this unexpected? */
536 object_count
= c
->ctr1
->object_count
;
537 first_object
= c
->ctr1
->first_object
;
538 nc_linked_attributes_count
= 0;
539 linked_attributes_count
= 0;
540 linked_attributes
= NULL
;
543 mapping_ctr
= &c
->ctr6
->mapping_ctr
;
544 nc_object_count
= c
->ctr6
->nc_object_count
;
545 object_count
= c
->ctr6
->object_count
;
546 first_object
= c
->ctr6
->first_object
;
547 nc_linked_attributes_count
= c
->ctr6
->nc_linked_attributes_count
;
548 linked_attributes_count
= c
->ctr6
->linked_attributes_count
;
549 linked_attributes
= c
->ctr6
->linked_attributes
;
552 return NT_STATUS_INVALID_PARAMETER
;
555 if (!s
->schema_part
.first_object
) {
556 nc_total_received
= object_count
;
558 nc_total_received
= s
->schema_part
.object_count
+ object_count
;
560 if (nc_object_count
) {
561 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
562 c
->partition
->nc
.dn
, nc_total_received
, nc_object_count
,
563 linked_attributes_count
, nc_linked_attributes_count
));
565 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u]\n",
566 c
->partition
->nc
.dn
, nc_total_received
, linked_attributes_count
));
569 if (!s
->self_made_schema
) {
571 struct drsuapi_DsReplicaOIDMapping_Ctr mapping_ctr_without_schema_info
;
572 /* Put the DRS prefixmap aside for the schema we are
573 * about to load in the provision, and into the one we
574 * are making with the help of DRS */
576 mapping_ctr_without_schema_info
= *mapping_ctr
;
578 /* This strips off the 0xFF schema info from the end,
579 * because we don't want it in the blob */
580 if (mapping_ctr_without_schema_info
.num_mappings
> 0) {
581 mapping_ctr_without_schema_info
.num_mappings
--;
583 werr
= dsdb_get_drsuapi_prefixmap_as_blob(&mapping_ctr_without_schema_info
, s
, &s
->prefixmap_blob
);
584 if (!W_ERROR_IS_OK(werr
)) {
585 return werror_to_ntstatus(werr
);
588 /* Set up two manually-constructed schema - the local
589 * schema from the provision will be used to build
590 * one, which will then in turn be used to build the
592 s
->self_made_schema
= dsdb_new_schema(s
);
593 NT_STATUS_HAVE_NO_MEMORY(s
->self_made_schema
);
595 s
->self_made_schema
->base_dn
= ldb_dn_new(s
->self_made_schema
,
597 c
->forest
->schema_dn_str
);
598 NT_STATUS_HAVE_NO_MEMORY(s
->self_made_schema
->base_dn
);
600 status
= dsdb_load_prefixmap_from_drsuapi(s
->self_made_schema
, mapping_ctr
);
601 if (!W_ERROR_IS_OK(status
)) {
602 return werror_to_ntstatus(status
);
605 status
= dsdb_schema_pfm_contains_drsuapi_pfm(s
->self_made_schema
->prefixmap
, mapping_ctr
);
606 if (!W_ERROR_IS_OK(status
)) {
607 return werror_to_ntstatus(status
);
611 if (!s
->schema_part
.first_object
) {
612 s
->schema_part
.object_count
= object_count
;
613 s
->schema_part
.first_object
= talloc_steal(s
, first_object
);
615 s
->schema_part
.object_count
+= object_count
;
616 s
->schema_part
.last_object
->next_object
= talloc_steal(s
->schema_part
.last_object
,
619 for (cur
= first_object
; cur
->next_object
; cur
= cur
->next_object
) {}
620 s
->schema_part
.last_object
= cur
;
622 if (!c
->partition
->more_data
) {
623 return libnet_vampire_cb_apply_schema(s
, c
);
629 NTSTATUS
libnet_vampire_cb_store_chunk(void *private_data
,
630 const struct libnet_BecomeDC_StoreChunk
*c
)
632 struct libnet_vampire_cb_state
*s
= talloc_get_type(private_data
, struct libnet_vampire_cb_state
);
634 struct dsdb_schema
*schema
;
635 const struct drsuapi_DsReplicaOIDMapping_Ctr
*mapping_ctr
;
636 uint32_t nc_object_count
;
637 uint32_t object_count
;
638 struct drsuapi_DsReplicaObjectListItemEx
*first_object
;
639 uint32_t nc_linked_attributes_count
;
640 uint32_t linked_attributes_count
;
641 struct drsuapi_DsReplicaLinkedAttribute
*linked_attributes
;
642 const struct drsuapi_DsReplicaCursor2CtrEx
*uptodateness_vector
;
643 struct dsdb_extended_replicated_objects
*objs
;
644 uint32_t req_replica_flags
;
645 struct repsFromTo1
*s_dsa
;
650 s_dsa
= talloc_zero(s
, struct repsFromTo1
);
651 NT_STATUS_HAVE_NO_MEMORY(s_dsa
);
652 s_dsa
->other_info
= talloc(s_dsa
, struct repsFromTo1OtherInfo
);
653 NT_STATUS_HAVE_NO_MEMORY(s_dsa
->other_info
);
655 switch (c
->ctr_level
) {
657 mapping_ctr
= &c
->ctr1
->mapping_ctr
;
658 nc_object_count
= c
->ctr1
->extended_ret
; /* maybe w2k send this unexpected? */
659 object_count
= c
->ctr1
->object_count
;
660 first_object
= c
->ctr1
->first_object
;
661 nc_linked_attributes_count
= 0;
662 linked_attributes_count
= 0;
663 linked_attributes
= NULL
;
664 s_dsa
->highwatermark
= c
->ctr1
->new_highwatermark
;
665 s_dsa
->source_dsa_obj_guid
= c
->ctr1
->source_dsa_guid
;
666 s_dsa
->source_dsa_invocation_id
= c
->ctr1
->source_dsa_invocation_id
;
667 uptodateness_vector
= NULL
; /* TODO: map it */
670 mapping_ctr
= &c
->ctr6
->mapping_ctr
;
671 nc_object_count
= c
->ctr6
->nc_object_count
;
672 object_count
= c
->ctr6
->object_count
;
673 first_object
= c
->ctr6
->first_object
;
674 nc_linked_attributes_count
= c
->ctr6
->nc_linked_attributes_count
;
675 linked_attributes_count
= c
->ctr6
->linked_attributes_count
;
676 linked_attributes
= c
->ctr6
->linked_attributes
;
677 s_dsa
->highwatermark
= c
->ctr6
->new_highwatermark
;
678 s_dsa
->source_dsa_obj_guid
= c
->ctr6
->source_dsa_guid
;
679 s_dsa
->source_dsa_invocation_id
= c
->ctr6
->source_dsa_invocation_id
;
680 uptodateness_vector
= c
->ctr6
->uptodateness_vector
;
683 return NT_STATUS_INVALID_PARAMETER
;
686 switch (c
->req_level
) {
689 req_replica_flags
= 0;
692 req_replica_flags
= c
->req5
->replica_flags
;
695 req_replica_flags
= c
->req8
->replica_flags
;
698 req_replica_flags
= c
->req10
->replica_flags
;
701 return NT_STATUS_INVALID_PARAMETER
;
704 if (req_replica_flags
& DRSUAPI_DRS_CRITICAL_ONLY
) {
706 * If we only replicate the critical objects
707 * we should not remember what we already
708 * got, as it is incomplete.
710 ZERO_STRUCT(s_dsa
->highwatermark
);
711 uptodateness_vector
= NULL
;
714 /* TODO: avoid hardcoded flags */
715 s_dsa
->replica_flags
= DRSUAPI_DRS_WRIT_REP
716 | DRSUAPI_DRS_INIT_SYNC
717 | DRSUAPI_DRS_PER_SYNC
;
718 memset(s_dsa
->schedule
, 0x11, sizeof(s_dsa
->schedule
));
720 tmp_dns_name
= GUID_string(s_dsa
->other_info
, &s_dsa
->source_dsa_obj_guid
);
721 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name
);
722 tmp_dns_name
= talloc_asprintf_append_buffer(tmp_dns_name
, "._msdcs.%s", c
->forest
->dns_name
);
723 NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name
);
724 s_dsa
->other_info
->dns_name
= tmp_dns_name
;
726 /* we want to show a count per partition */
727 if (!s
->last_partition
|| strcmp(s
->last_partition
, c
->partition
->nc
.dn
) != 0) {
728 s
->total_objects
= 0;
729 talloc_free(s
->last_partition
);
730 s
->last_partition
= talloc_strdup(s
, c
->partition
->nc
.dn
);
732 s
->total_objects
+= object_count
;
734 if (nc_object_count
) {
735 DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
736 c
->partition
->nc
.dn
, s
->total_objects
, nc_object_count
,
737 linked_attributes_count
, nc_linked_attributes_count
));
739 DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
740 c
->partition
->nc
.dn
, s
->total_objects
, linked_attributes_count
));
744 schema
= dsdb_get_schema(s
->ldb
, NULL
);
746 DEBUG(0,(__location__
": Schema is not loaded yet!\n"));
747 return NT_STATUS_INTERNAL_ERROR
;
750 status
= dsdb_replicated_objects_convert(s
->ldb
,
756 linked_attributes_count
,
763 if (!W_ERROR_IS_OK(status
)) {
764 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status
)));
765 return werror_to_ntstatus(status
);
768 if (lpcfg_parm_bool(s
->lp_ctx
, NULL
, "become dc", "dump objects", false)) {
769 for (i
=0; i
< objs
->num_objects
; i
++) {
770 struct ldb_ldif ldif
;
771 fprintf(stdout
, "#\n");
772 ldif
.changetype
= LDB_CHANGETYPE_NONE
;
773 ldif
.msg
= objs
->objects
[i
].msg
;
774 ldb_ldif_write_file(s
->ldb
, stdout
, &ldif
);
775 NDR_PRINT_DEBUG(replPropertyMetaDataBlob
, objs
->objects
[i
].meta_data
);
778 status
= dsdb_replicated_objects_commit(s
->ldb
, NULL
, objs
, &seq_num
);
779 if (!W_ERROR_IS_OK(status
)) {
780 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status
)));
781 return werror_to_ntstatus(status
);
787 for (i
=0; i
< linked_attributes_count
; i
++) {
788 const struct dsdb_attribute
*sa
;
790 if (!linked_attributes
[i
].identifier
) {
791 DEBUG(0, ("No linked attribute identifier\n"));
792 return NT_STATUS_FOOBAR
;
795 if (!linked_attributes
[i
].value
.blob
) {
796 DEBUG(0, ("No linked attribute value\n"));
797 return NT_STATUS_FOOBAR
;
800 sa
= dsdb_attribute_by_attributeID_id(s
->schema
,
801 linked_attributes
[i
].attid
);
803 DEBUG(0, ("Unable to find attribute via attribute id %d\n", linked_attributes
[i
].attid
));
804 return NT_STATUS_FOOBAR
;
807 if (lpcfg_parm_bool(s
->lp_ctx
, NULL
, "become dc", "dump objects", false)) {
808 DEBUG(0,("# %s\n", sa
->lDAPDisplayName
));
809 NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute
, &linked_attributes
[i
]);
811 linked_attributes
[i
].value
.blob
->data
,
812 linked_attributes
[i
].value
.blob
->length
);
819 static NTSTATUS
update_dnshostname_for_server(TALLOC_CTX
*mem_ctx
,
820 struct ldb_context
*ldb
,
821 const char *server_dn_str
,
822 const char *netbios_name
,
826 struct ldb_message
*msg
;
827 struct ldb_message_element
*el
;
828 struct ldb_dn
*server_dn
;
829 const char *dNSHostName
= strlower_talloc(mem_ctx
,
830 talloc_asprintf(mem_ctx
,
834 msg
= ldb_msg_new(mem_ctx
);
836 return NT_STATUS_NO_MEMORY
;
839 server_dn
= ldb_dn_new(mem_ctx
, ldb
, server_dn_str
);
841 return NT_STATUS_INTERNAL_ERROR
;
845 ret
= ldb_msg_add_empty(msg
, "dNSHostName", LDB_FLAG_MOD_ADD
, &el
);
846 if (ret
!= LDB_SUCCESS
) {
847 return NT_STATUS_INTERNAL_ERROR
;
850 ret
= ldb_msg_add_steal_string(msg
,
852 talloc_asprintf(el
->values
, "%s", dNSHostName
));
853 if (ret
!= LDB_SUCCESS
) {
854 return NT_STATUS_INTERNAL_ERROR
;
857 ret
= dsdb_modify(ldb
, msg
, DSDB_MODIFY_PERMISSIVE
);
858 if (ret
!= LDB_SUCCESS
) {
859 DEBUG(0,(__location__
": Failed to add dnsHostName to the Server object: %s\n",
860 ldb_errstring(ldb
)));
861 return NT_STATUS_INTERNAL_ERROR
;
868 NTSTATUS
libnet_Vampire(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
,
869 struct libnet_Vampire
*r
)
871 struct libnet_JoinDomain
*join
;
872 struct libnet_Replicate rep
;
875 const char *account_name
;
876 const char *netbios_name
;
878 r
->out
.error_string
= NULL
;
880 join
= talloc_zero(mem_ctx
, struct libnet_JoinDomain
);
882 return NT_STATUS_NO_MEMORY
;
885 if (r
->in
.netbios_name
!= NULL
) {
886 netbios_name
= r
->in
.netbios_name
;
888 netbios_name
= talloc_reference(join
, lpcfg_netbios_name(ctx
->lp_ctx
));
891 r
->out
.error_string
= NULL
;
892 return NT_STATUS_NO_MEMORY
;
896 account_name
= talloc_asprintf(join
, "%s$", netbios_name
);
899 r
->out
.error_string
= NULL
;
900 return NT_STATUS_NO_MEMORY
;
903 /* Re-use the domain we are joining as the domain for the user
904 * to be authenticated with, unless they specified
906 cli_credentials_set_domain(ctx
->cred
, r
->in
.domain_name
, CRED_GUESS_ENV
);
908 join
->in
.domain_name
= r
->in
.domain_name
;
909 join
->in
.account_name
= account_name
;
910 join
->in
.netbios_name
= netbios_name
;
911 join
->in
.level
= LIBNET_JOINDOMAIN_AUTOMATIC
;
912 join
->in
.acct_type
= ACB_WSTRUST
;
913 join
->in
.recreate_account
= false;
914 status
= libnet_JoinDomain(ctx
, join
, join
);
915 if (!NT_STATUS_IS_OK(status
)) {
916 r
->out
.error_string
= talloc_steal(mem_ctx
, join
->out
.error_string
);
921 rep
.in
.domain_name
= join
->out
.domain_name
;
922 rep
.in
.netbios_name
= netbios_name
;
923 rep
.in
.targetdir
= r
->in
.targetdir
;
924 rep
.in
.domain_sid
= join
->out
.domain_sid
;
925 rep
.in
.realm
= join
->out
.realm
;
926 rep
.in
.server
= join
->out
.samr_binding
->host
;
927 rep
.in
.join_password
= join
->out
.join_password
;
928 rep
.in
.kvno
= join
->out
.kvno
;
930 status
= libnet_Replicate(ctx
, mem_ctx
, &rep
);
932 r
->out
.domain_sid
= join
->out
.domain_sid
;
933 r
->out
.domain_name
= join
->out
.domain_name
;
934 r
->out
.error_string
= rep
.out
.error_string
;
941 NTSTATUS
libnet_Replicate(struct libnet_context
*ctx
, TALLOC_CTX
*mem_ctx
,
942 struct libnet_Replicate
*r
)
944 struct provision_store_self_join_settings
*set_secrets
;
945 struct libnet_BecomeDC b
;
946 struct libnet_vampire_cb_state
*s
;
947 struct ldb_message
*msg
;
948 const char *error_string
;
952 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
953 const char *account_name
;
954 const char *netbios_name
;
956 r
->out
.error_string
= NULL
;
958 netbios_name
= r
->in
.netbios_name
;
959 account_name
= talloc_asprintf(tmp_ctx
, "%s$", netbios_name
);
961 talloc_free(tmp_ctx
);
962 r
->out
.error_string
= NULL
;
963 return NT_STATUS_NO_MEMORY
;
966 /* Re-use the domain we are joining as the domain for the user
967 * to be authenticated with, unless they specified
969 cli_credentials_set_domain(ctx
->cred
, r
->in
.domain_name
, CRED_GUESS_ENV
);
971 s
= libnet_vampire_cb_state_init(mem_ctx
, ctx
->lp_ctx
, ctx
->event_ctx
,
972 netbios_name
, r
->in
.domain_name
, r
->in
.realm
,
975 return NT_STATUS_NO_MEMORY
;
977 talloc_steal(s
, tmp_ctx
);
982 * We now know the domain and realm for sure - if they didn't
983 * put one on the command line, use this for the rest of the
985 cli_credentials_set_realm(ctx
->cred
, r
->in
.realm
, CRED_GUESS_ENV
);
986 cli_credentials_set_domain(ctx
->cred
, r
->in
.domain_name
, CRED_GUESS_ENV
);
988 /* Now set these values into the smb.conf - we probably had
989 * empty or useless defaults here from whatever smb.conf we
991 lpcfg_set_cmdline(s
->lp_ctx
, "realm", r
->in
.realm
);
992 lpcfg_set_cmdline(s
->lp_ctx
, "workgroup", r
->in
.domain_name
);
994 b
.in
.domain_dns_name
= r
->in
.realm
;
995 b
.in
.domain_netbios_name
= r
->in
.domain_name
;
996 b
.in
.domain_sid
= r
->in
.domain_sid
;
997 b
.in
.source_dsa_address
= r
->in
.server
;
998 b
.in
.dest_dsa_netbios_name
= netbios_name
;
1000 b
.in
.callbacks
.private_data
= s
;
1001 b
.in
.callbacks
.check_options
= libnet_vampire_cb_check_options
;
1002 b
.in
.callbacks
.prepare_db
= libnet_vampire_cb_prepare_db
;
1003 b
.in
.callbacks
.schema_chunk
= libnet_vampire_cb_schema_chunk
;
1004 b
.in
.callbacks
.config_chunk
= libnet_vampire_cb_store_chunk
;
1005 b
.in
.callbacks
.domain_chunk
= libnet_vampire_cb_store_chunk
;
1007 b
.in
.rodc_join
= lpcfg_parm_bool(s
->lp_ctx
, NULL
, "repl", "RODC", false);
1009 status
= libnet_BecomeDC(ctx
, s
, &b
);
1010 if (!NT_STATUS_IS_OK(status
)) {
1011 printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status
));
1016 msg
= ldb_msg_new(s
);
1018 printf("ldb_msg_new() failed\n");
1020 return NT_STATUS_NO_MEMORY
;
1022 msg
->dn
= ldb_dn_new(msg
, s
->ldb
, "@ROOTDSE");
1024 printf("ldb_msg_new(@ROOTDSE) failed\n");
1026 return NT_STATUS_NO_MEMORY
;
1029 ldb_ret
= ldb_msg_add_string(msg
, "isSynchronized", "TRUE");
1030 if (ldb_ret
!= LDB_SUCCESS
) {
1031 printf("ldb_msg_add_string(msg, isSynchronized, TRUE) failed: %d\n", ldb_ret
);
1033 return NT_STATUS_NO_MEMORY
;
1036 for (i
=0; i
< msg
->num_elements
; i
++) {
1037 msg
->elements
[i
].flags
= LDB_FLAG_MOD_REPLACE
;
1040 printf("mark ROOTDSE with isSynchronized=TRUE\n");
1041 ldb_ret
= ldb_modify(s
->ldb
, msg
);
1042 if (ldb_ret
!= LDB_SUCCESS
) {
1043 printf("ldb_modify() failed: %d : %s\n", ldb_ret
, ldb_errstring(s
->ldb
));
1045 return NT_STATUS_INTERNAL_DB_ERROR
;
1047 /* during dcpromo the 2nd computer adds dNSHostName attribute to his Server object
1048 * the attribute appears on the original DC after replication
1050 status
= update_dnshostname_for_server(s
, s
->ldb
, s
->server_dn_str
, s
->netbios_name
, s
->realm
);
1051 if (!NT_STATUS_IS_OK(status
)) {
1052 printf("Failed to update dNSHostName on Server object - %s\n", nt_errstr(status
));
1056 /* prepare the transaction - this prepares to commit all the changes in
1057 the ldb from the whole vampire. Note that this
1058 triggers the writing of the linked attribute backlinks.
1060 if (ldb_transaction_prepare_commit(s
->ldb
) != LDB_SUCCESS
) {
1061 printf("Failed to prepare_commit vampire transaction: %s\n", ldb_errstring(s
->ldb
));
1062 return NT_STATUS_INTERNAL_DB_ERROR
;
1065 set_secrets
= talloc(s
, struct provision_store_self_join_settings
);
1067 r
->out
.error_string
= NULL
;
1069 return NT_STATUS_NO_MEMORY
;
1072 ZERO_STRUCTP(set_secrets
);
1073 set_secrets
->domain_name
= r
->in
.domain_name
;
1074 set_secrets
->realm
= r
->in
.realm
;
1075 set_secrets
->netbios_name
= netbios_name
;
1076 set_secrets
->secure_channel_type
= SEC_CHAN_BDC
;
1077 set_secrets
->machine_password
= r
->in
.join_password
;
1078 set_secrets
->key_version_number
= r
->in
.kvno
;
1079 set_secrets
->domain_sid
= r
->in
.domain_sid
;
1081 status
= provision_store_self_join(ctx
, s
->lp_ctx
, ctx
->event_ctx
, set_secrets
, &error_string
);
1082 if (!NT_STATUS_IS_OK(status
)) {
1083 r
->out
.error_string
= talloc_steal(mem_ctx
, error_string
);
1088 /* commit the transaction now we know the secrets were written
1091 if (ldb_transaction_commit(s
->ldb
) != LDB_SUCCESS
) {
1092 printf("Failed to commit vampire transaction\n");
1093 return NT_STATUS_INTERNAL_DB_ERROR
;
1098 return NT_STATUS_OK
;