2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2006
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "libnet/libnet.h"
23 #include "libcli/composite/composite.h"
24 #include "libcli/cldap/cldap.h"
25 #include "lib/ldb/include/ldb.h"
26 #include "lib/ldb/include/ldb_errors.h"
27 #include "lib/db_wrap.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "dsdb/common/flags.h"
30 #include "librpc/gen_ndr/ndr_drsuapi_c.h"
31 #include "libcli/security/security.h"
33 struct libnet_BecomeDC_state {
34 struct composite_context *creq;
36 struct libnet_context *libnet;
38 struct dom_sid zero_sid;
41 struct cldap_socket *sock;
42 struct cldap_netlogon io;
43 struct nbt_cldap_netlogon_5 netlogon5;
46 struct becomeDC_ldap {
47 struct ldb_context *ldb;
48 const struct ldb_message *rootdse;
51 struct becomeDC_drsuapi {
52 struct libnet_BecomeDC_state *s;
53 struct dcerpc_binding *binding;
54 struct dcerpc_pipe *pipe;
55 struct drsuapi_DsBind bind_r;
56 struct GUID bind_guid;
57 struct drsuapi_DsBindInfoCtr bind_info_ctr;
58 struct drsuapi_DsBindInfo28 local_info28;
59 struct drsuapi_DsBindInfo28 remote_info28;
60 struct policy_handle bind_handle;
61 } drsuapi1, drsuapi2, drsuapi3;
63 struct libnet_BecomeDC_Domain domain;
64 struct libnet_BecomeDC_Forest forest;
65 struct libnet_BecomeDC_SourceDSA source_dsa;
66 struct libnet_BecomeDC_DestDSA dest_dsa;
68 struct becomeDC_partition {
69 struct drsuapi_DsReplicaObjectIdentifier nc;
70 struct GUID destination_dsa_guid;
71 struct GUID source_dsa_guid;
72 struct GUID source_dsa_invocation_id;
73 struct drsuapi_DsReplicaHighWaterMark highwatermark;
74 struct drsuapi_DsReplicaCoursorCtrEx *uptodateness_vector;
75 uint32_t replica_flags;
77 struct drsuapi_DsReplicaObjectListItemEx *first_object;
78 struct drsuapi_DsReplicaObjectListItemEx *last_object;
80 NTSTATUS (*store_chunk)(void *private_data, void *todo);
81 } schema_part, config_part, domain_part;
83 struct becomeDC_fsmo {
85 const char *server_dn_str;
86 const char *ntds_dn_str;
87 struct GUID ntds_guid;
88 } infrastructure_fsmo;
90 struct becomeDC_fsmo rid_manager_fsmo;
92 struct libnet_BecomeDC_CheckOptions _co;
93 struct libnet_BecomeDC_PrepareDB _pp;
94 struct libnet_BecomeDC_Callbacks callbacks;
97 static void becomeDC_connect_ldap1(struct libnet_BecomeDC_state *s);
99 static void becomeDC_recv_cldap(struct cldap_request *req)
101 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
102 struct libnet_BecomeDC_state);
103 struct composite_context *c = s->creq;
105 c->status = cldap_netlogon_recv(req, s, &s->cldap.io);
106 if (!composite_is_ok(c)) return;
108 s->cldap.netlogon5 = s->cldap.io.out.netlogon.logon5;
110 s->domain.dns_name = s->cldap.netlogon5.dns_domain;
111 s->domain.netbios_name = s->cldap.netlogon5.domain;
112 s->domain.guid = s->cldap.netlogon5.domain_uuid;
114 s->forest.dns_name = s->cldap.netlogon5.forest;
116 s->source_dsa.dns_name = s->cldap.netlogon5.pdc_dns_name;
117 s->source_dsa.netbios_name = s->cldap.netlogon5.pdc_name;
118 s->source_dsa.site_name = s->cldap.netlogon5.server_site;
120 s->dest_dsa.site_name = s->cldap.netlogon5.client_site;
122 becomeDC_connect_ldap1(s);
125 static void becomeDC_send_cldap(struct libnet_BecomeDC_state *s)
127 struct composite_context *c = s->creq;
128 struct cldap_request *req;
130 s->cldap.io.in.dest_address = s->source_dsa.address;
131 s->cldap.io.in.realm = s->domain.dns_name;
132 s->cldap.io.in.host = s->dest_dsa.netbios_name;
133 s->cldap.io.in.user = NULL;
134 s->cldap.io.in.domain_guid = NULL;
135 s->cldap.io.in.domain_sid = NULL;
136 s->cldap.io.in.acct_control = -1;
137 s->cldap.io.in.version = 6;
139 s->cldap.sock = cldap_socket_init(s, s->libnet->event_ctx);
140 if (composite_nomem(s->cldap.sock, c)) return;
142 req = cldap_netlogon_send(s->cldap.sock, &s->cldap.io);
143 if (composite_nomem(req, c)) return;
144 req->async.fn = becomeDC_recv_cldap;
145 req->async.private = s;
148 static NTSTATUS becomeDC_ldap_connect(struct libnet_BecomeDC_state *s, struct becomeDC_ldap *ldap)
152 url = talloc_asprintf(s, "ldap://%s/", s->source_dsa.dns_name);
153 NT_STATUS_HAVE_NO_MEMORY(url);
155 ldap->ldb = ldb_wrap_connect(s, url,
160 if (ldap->ldb == NULL) {
161 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
167 static NTSTATUS becomeDC_ldap1_rootdse(struct libnet_BecomeDC_state *s)
170 struct ldb_result *r;
171 struct ldb_dn *basedn;
172 static const char *attrs[] = {
177 basedn = ldb_dn_new(s, s->ldap1.ldb, NULL);
178 NT_STATUS_HAVE_NO_MEMORY(basedn);
180 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
181 "(objectClass=*)", attrs, &r);
183 if (ret != LDB_SUCCESS) {
184 return NT_STATUS_LDAP(ret);
185 } else if (r->count != 1) {
187 return NT_STATUS_INVALID_NETWORK_RESPONSE;
191 s->ldap1.rootdse = r->msgs[0];
193 s->domain.dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "defaultNamingContext", NULL);
194 if (!s->domain.dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
196 s->forest.root_dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "rootDomainNamingContext", NULL);
197 if (!s->forest.root_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
198 s->forest.config_dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "configurationNamingContext", NULL);
199 if (!s->forest.config_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
200 s->forest.schema_dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "schemaNamingContext", NULL);
201 if (!s->forest.schema_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
203 s->source_dsa.server_dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "serverName", NULL);
204 if (!s->source_dsa.server_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
205 s->source_dsa.ntds_dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "dsServiceName", NULL);
206 if (!s->source_dsa.ntds_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
211 static NTSTATUS becomeDC_ldap1_crossref_behavior_version(struct libnet_BecomeDC_state *s)
214 struct ldb_result *r;
215 struct ldb_dn *basedn;
216 static const char *attrs[] = {
217 "msDs-Behavior-Version",
221 basedn = ldb_dn_new(s, s->ldap1.ldb, s->forest.config_dn_str);
222 NT_STATUS_HAVE_NO_MEMORY(basedn);
224 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_ONELEVEL,
225 "(cn=Partitions)", attrs, &r);
227 if (ret != LDB_SUCCESS) {
228 return NT_STATUS_LDAP(ret);
229 } else if (r->count != 1) {
231 return NT_STATUS_INVALID_NETWORK_RESPONSE;
234 s->forest.crossref_behavior_version = ldb_msg_find_attr_as_uint(r->msgs[0], "msDs-Behavior-Version", 0);
240 static NTSTATUS becomeDC_ldap1_domain_behavior_version(struct libnet_BecomeDC_state *s)
243 struct ldb_result *r;
244 struct ldb_dn *basedn;
245 static const char *attrs[] = {
246 "msDs-Behavior-Version",
250 basedn = ldb_dn_new(s, s->ldap1.ldb, s->domain.dn_str);
251 NT_STATUS_HAVE_NO_MEMORY(basedn);
253 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
254 "(objectClass=*)", attrs, &r);
256 if (ret != LDB_SUCCESS) {
257 return NT_STATUS_LDAP(ret);
258 } else if (r->count != 1) {
260 return NT_STATUS_INVALID_NETWORK_RESPONSE;
263 s->domain.behavior_version = ldb_msg_find_attr_as_uint(r->msgs[0], "msDs-Behavior-Version", 0);
269 static NTSTATUS becomeDC_ldap1_schema_object_version(struct libnet_BecomeDC_state *s)
272 struct ldb_result *r;
273 struct ldb_dn *basedn;
274 static const char *attrs[] = {
279 basedn = ldb_dn_new(s, s->ldap1.ldb, s->forest.schema_dn_str);
280 NT_STATUS_HAVE_NO_MEMORY(basedn);
282 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
283 "(objectClass=*)", attrs, &r);
285 if (ret != LDB_SUCCESS) {
286 return NT_STATUS_LDAP(ret);
287 } else if (r->count != 1) {
289 return NT_STATUS_INVALID_NETWORK_RESPONSE;
292 s->forest.schema_object_version = ldb_msg_find_attr_as_uint(r->msgs[0], "objectVersion", 0);
298 static NTSTATUS becomeDC_ldap1_w2k3_update_revision(struct libnet_BecomeDC_state *s)
301 struct ldb_result *r;
302 struct ldb_dn *basedn;
303 static const char *attrs[] = {
308 basedn = ldb_dn_new_fmt(s, s->ldap1.ldb, "CN=Windows2003Update,CN=DomainUpdates,CN=System,%s",
310 NT_STATUS_HAVE_NO_MEMORY(basedn);
312 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
313 "(objectClass=*)", attrs, &r);
315 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
316 /* w2k doesn't have this object */
317 s->domain.w2k3_update_revision = 0;
319 } else if (ret != LDB_SUCCESS) {
320 return NT_STATUS_LDAP(ret);
321 } else if (r->count != 1) {
323 return NT_STATUS_INVALID_NETWORK_RESPONSE;
326 s->domain.w2k3_update_revision = ldb_msg_find_attr_as_uint(r->msgs[0], "revision", 0);
332 static NTSTATUS becomeDC_ldap1_infrastructure_fsmo(struct libnet_BecomeDC_state *s)
335 struct ldb_result *r;
336 struct ldb_dn *basedn;
337 struct ldb_dn *ntds_dn;
338 struct ldb_dn *server_dn;
339 static const char *_1_1_attrs[] = {
343 static const char *fsmo_attrs[] = {
347 static const char *dns_attrs[] = {
351 static const char *guid_attrs[] = {
356 basedn = ldb_dn_new_fmt(s, s->ldap1.ldb, "<WKGUID=2fbac1870ade11d297c400c04fd8d5cd,%s>",
358 NT_STATUS_HAVE_NO_MEMORY(basedn);
360 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
361 "(objectClass=*)", _1_1_attrs, &r);
363 if (ret != LDB_SUCCESS) {
364 return NT_STATUS_LDAP(ret);
365 } else if (r->count != 1) {
367 return NT_STATUS_INVALID_NETWORK_RESPONSE;
370 basedn = talloc_steal(s, r->msgs[0]->dn);
373 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
374 "(objectClass=*)", fsmo_attrs, &r);
376 if (ret != LDB_SUCCESS) {
377 return NT_STATUS_LDAP(ret);
378 } else if (r->count != 1) {
380 return NT_STATUS_INVALID_NETWORK_RESPONSE;
383 s->infrastructure_fsmo.ntds_dn_str = samdb_result_string(r->msgs[0], "fSMORoleOwner", NULL);
384 if (!s->infrastructure_fsmo.ntds_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
385 talloc_steal(s, s->infrastructure_fsmo.ntds_dn_str);
389 ntds_dn = ldb_dn_new(s, s->ldap1.ldb, s->infrastructure_fsmo.ntds_dn_str);
390 NT_STATUS_HAVE_NO_MEMORY(ntds_dn);
392 server_dn = ldb_dn_get_parent(s, ntds_dn);
393 NT_STATUS_HAVE_NO_MEMORY(server_dn);
395 s->infrastructure_fsmo.server_dn_str = ldb_dn_alloc_linearized(s, server_dn);
396 NT_STATUS_HAVE_NO_MEMORY(s->infrastructure_fsmo.server_dn_str);
398 ret = ldb_search(s->ldap1.ldb, server_dn, LDB_SCOPE_BASE,
399 "(objectClass=*)", dns_attrs, &r);
400 if (ret != LDB_SUCCESS) {
401 return NT_STATUS_LDAP(ret);
402 } else if (r->count != 1) {
404 return NT_STATUS_INVALID_NETWORK_RESPONSE;
407 s->infrastructure_fsmo.dns_name = samdb_result_string(r->msgs[0], "dnsHostName", NULL);
408 if (!s->infrastructure_fsmo.dns_name) return NT_STATUS_INVALID_NETWORK_RESPONSE;
409 talloc_steal(s, s->infrastructure_fsmo.dns_name);
413 ret = ldb_search(s->ldap1.ldb, ntds_dn, LDB_SCOPE_BASE,
414 "(objectClass=*)", guid_attrs, &r);
415 if (ret != LDB_SUCCESS) {
416 return NT_STATUS_LDAP(ret);
417 } else if (r->count != 1) {
419 return NT_STATUS_INVALID_NETWORK_RESPONSE;
422 s->infrastructure_fsmo.ntds_guid = samdb_result_guid(r->msgs[0], "objectGUID");
429 static NTSTATUS becomeDC_ldap1_rid_manager_fsmo(struct libnet_BecomeDC_state *s)
432 struct ldb_result *r;
433 struct ldb_dn *basedn;
434 const char *reference_dn_str;
435 struct ldb_dn *ntds_dn;
436 struct ldb_dn *server_dn;
437 static const char *rid_attrs[] = {
438 "rIDManagerReference",
441 static const char *fsmo_attrs[] = {
445 static const char *dns_attrs[] = {
449 static const char *guid_attrs[] = {
454 basedn = ldb_dn_new(s, s->ldap1.ldb, s->domain.dn_str);
455 NT_STATUS_HAVE_NO_MEMORY(basedn);
457 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
458 "(objectClass=*)", rid_attrs, &r);
460 if (ret != LDB_SUCCESS) {
461 return NT_STATUS_LDAP(ret);
462 } else if (r->count != 1) {
464 return NT_STATUS_INVALID_NETWORK_RESPONSE;
467 reference_dn_str = samdb_result_string(r->msgs[0], "rIDManagerReference", NULL);
468 if (!reference_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
470 basedn = ldb_dn_new(s, s->ldap1.ldb, reference_dn_str);
471 NT_STATUS_HAVE_NO_MEMORY(basedn);
475 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
476 "(objectClass=*)", fsmo_attrs, &r);
478 if (ret != LDB_SUCCESS) {
479 return NT_STATUS_LDAP(ret);
480 } else if (r->count != 1) {
482 return NT_STATUS_INVALID_NETWORK_RESPONSE;
485 s->rid_manager_fsmo.ntds_dn_str = samdb_result_string(r->msgs[0], "fSMORoleOwner", NULL);
486 if (!s->rid_manager_fsmo.ntds_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
487 talloc_steal(s, s->rid_manager_fsmo.ntds_dn_str);
491 ntds_dn = ldb_dn_new(s, s->ldap1.ldb, s->rid_manager_fsmo.ntds_dn_str);
492 NT_STATUS_HAVE_NO_MEMORY(ntds_dn);
494 server_dn = ldb_dn_get_parent(s, ntds_dn);
495 NT_STATUS_HAVE_NO_MEMORY(server_dn);
497 s->rid_manager_fsmo.server_dn_str = ldb_dn_alloc_linearized(s, server_dn);
498 NT_STATUS_HAVE_NO_MEMORY(s->rid_manager_fsmo.server_dn_str);
500 ret = ldb_search(s->ldap1.ldb, server_dn, LDB_SCOPE_BASE,
501 "(objectClass=*)", dns_attrs, &r);
502 if (ret != LDB_SUCCESS) {
503 return NT_STATUS_LDAP(ret);
504 } else if (r->count != 1) {
506 return NT_STATUS_INVALID_NETWORK_RESPONSE;
509 s->rid_manager_fsmo.dns_name = samdb_result_string(r->msgs[0], "dnsHostName", NULL);
510 if (!s->rid_manager_fsmo.dns_name) return NT_STATUS_INVALID_NETWORK_RESPONSE;
511 talloc_steal(s, s->rid_manager_fsmo.dns_name);
515 ret = ldb_search(s->ldap1.ldb, ntds_dn, LDB_SCOPE_BASE,
516 "(objectClass=*)", guid_attrs, &r);
517 if (ret != LDB_SUCCESS) {
518 return NT_STATUS_LDAP(ret);
519 } else if (r->count != 1) {
521 return NT_STATUS_INVALID_NETWORK_RESPONSE;
524 s->rid_manager_fsmo.ntds_guid = samdb_result_guid(r->msgs[0], "objectGUID");
531 static NTSTATUS becomeDC_ldap1_site_object(struct libnet_BecomeDC_state *s)
534 struct ldb_result *r;
535 struct ldb_dn *basedn;
537 basedn = ldb_dn_new_fmt(s, s->ldap1.ldb, "CN=%s,CN=Sites,%s",
538 s->dest_dsa.site_name,
539 s->forest.config_dn_str);
540 NT_STATUS_HAVE_NO_MEMORY(basedn);
542 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
543 "(objectClass=*)", NULL, &r);
545 if (ret != LDB_SUCCESS) {
546 return NT_STATUS_LDAP(ret);
547 } else if (r->count != 1) {
549 return NT_STATUS_INVALID_NETWORK_RESPONSE;
552 s->dest_dsa.site_guid = samdb_result_guid(r->msgs[0], "objectGUID");
558 static NTSTATUS becomeDC_check_options(struct libnet_BecomeDC_state *s)
560 if (!s->callbacks.check_options) return NT_STATUS_OK;
562 s->_co.domain = &s->domain;
563 s->_co.forest = &s->forest;
564 s->_co.source_dsa = &s->source_dsa;
566 return s->callbacks.check_options(s->callbacks.private_data, &s->_co);
569 static NTSTATUS becomeDC_ldap1_computer_object(struct libnet_BecomeDC_state *s)
572 struct ldb_result *r;
573 struct ldb_dn *basedn;
575 static const char *attrs[] = {
577 "userAccountControl",
581 basedn = ldb_dn_new(s, s->ldap1.ldb, s->domain.dn_str);
582 NT_STATUS_HAVE_NO_MEMORY(basedn);
584 filter = talloc_asprintf(basedn, "(&(|(objectClass=user)(objectClass=computer))(sAMAccountName=%s$))",
585 s->dest_dsa.netbios_name);
586 NT_STATUS_HAVE_NO_MEMORY(filter);
588 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_SUBTREE,
591 if (ret != LDB_SUCCESS) {
592 return NT_STATUS_LDAP(ret);
593 } else if (r->count != 1) {
595 return NT_STATUS_INVALID_NETWORK_RESPONSE;
598 s->dest_dsa.computer_dn_str = samdb_result_string(r->msgs[0], "distinguishedName", NULL);
599 if (!s->dest_dsa.computer_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
600 talloc_steal(s, s->dest_dsa.computer_dn_str);
602 s->dest_dsa.user_account_control = samdb_result_uint(r->msgs[0], "userAccountControl", 0);
608 static NTSTATUS becomeDC_ldap1_server_object_1(struct libnet_BecomeDC_state *s)
611 struct ldb_result *r;
612 struct ldb_dn *basedn;
613 const char *server_reference_dn_str;
614 struct ldb_dn *server_reference_dn;
615 struct ldb_dn *computer_dn;
617 basedn = ldb_dn_new_fmt(s, s->ldap1.ldb, "CN=%s,CN=Servers,CN=%s,CN=Sites,%s",
618 s->dest_dsa.netbios_name,
619 s->dest_dsa.site_name,
620 s->forest.config_dn_str);
621 NT_STATUS_HAVE_NO_MEMORY(basedn);
623 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
624 "(objectClass=*)", NULL, &r);
626 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
627 /* if the object doesn't exist, we'll create it later */
629 } else if (ret != LDB_SUCCESS) {
630 return NT_STATUS_LDAP(ret);
631 } else if (r->count != 1) {
633 return NT_STATUS_INVALID_NETWORK_RESPONSE;
636 server_reference_dn_str = samdb_result_string(r->msgs[0], "serverReference", NULL);
637 if (server_reference_dn_str) {
638 server_reference_dn = ldb_dn_new(r, s->ldap1.ldb, server_reference_dn_str);
639 NT_STATUS_HAVE_NO_MEMORY(server_reference_dn);
641 computer_dn = ldb_dn_new(r, s->ldap1.ldb, s->dest_dsa.computer_dn_str);
642 NT_STATUS_HAVE_NO_MEMORY(computer_dn);
645 * if the server object belongs to another DC in another domain in the forest,
646 * we should not touch this object!
648 if (ldb_dn_compare(computer_dn, server_reference_dn) != 0) {
650 return NT_STATUS_OBJECT_NAME_COLLISION;
654 /* if the server object is already for the dest_dsa, then we don't need to create it */
655 s->dest_dsa.server_dn_str = samdb_result_string(r->msgs[0], "distinguishedName", NULL);
656 if (!s->dest_dsa.server_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
657 talloc_steal(s, s->dest_dsa.server_dn_str);
663 static NTSTATUS becomeDC_ldap1_server_object_2(struct libnet_BecomeDC_state *s)
666 struct ldb_result *r;
667 struct ldb_dn *basedn;
668 const char *server_reference_bl_dn_str;
669 static const char *attrs[] = {
674 /* if the server_dn_str has a valid value, we skip this lookup */
675 if (s->dest_dsa.server_dn_str) return NT_STATUS_OK;
677 basedn = ldb_dn_new(s, s->ldap1.ldb, s->dest_dsa.computer_dn_str);
678 NT_STATUS_HAVE_NO_MEMORY(basedn);
680 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
681 "(objectClass=*)", attrs, &r);
683 if (ret != LDB_SUCCESS) {
684 return NT_STATUS_LDAP(ret);
685 } else if (r->count != 1) {
687 return NT_STATUS_INVALID_NETWORK_RESPONSE;
690 server_reference_bl_dn_str = samdb_result_string(r->msgs[0], "serverReferenceBL", NULL);
691 if (!server_reference_bl_dn_str) {
692 /* if no back link is present, we're done for this function */
697 /* if the server object is already for the dest_dsa, then we don't need to create it */
698 s->dest_dsa.server_dn_str = samdb_result_string(r->msgs[0], "serverReferenceBL", NULL);
699 if (s->dest_dsa.server_dn_str) {
700 /* if a back link is present, we know that the server object is present */
701 talloc_steal(s, s->dest_dsa.server_dn_str);
708 static NTSTATUS becomeDC_ldap1_server_object_add(struct libnet_BecomeDC_state *s)
711 struct ldb_message *msg;
714 /* if the server_dn_str has a valid value, we skip this lookup */
715 if (s->dest_dsa.server_dn_str) return NT_STATUS_OK;
717 msg = ldb_msg_new(s);
718 NT_STATUS_HAVE_NO_MEMORY(msg);
720 msg->dn = ldb_dn_new_fmt(msg, s->ldap1.ldb, "CN=%s,CN=Servers,CN=%s,CN=Sites,%s",
721 s->dest_dsa.netbios_name,
722 s->dest_dsa.site_name,
723 s->forest.config_dn_str);
724 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
726 ret = ldb_msg_add_string(msg, "objectClass", "server");
729 return NT_STATUS_NO_MEMORY;
731 ret = ldb_msg_add_string(msg, "systemFlags", "50000000");
734 return NT_STATUS_NO_MEMORY;
736 ret = ldb_msg_add_string(msg, "serverReference", s->dest_dsa.computer_dn_str);
739 return NT_STATUS_NO_MEMORY;
742 server_dn_str = ldb_dn_alloc_linearized(s, msg->dn);
743 NT_STATUS_HAVE_NO_MEMORY(server_dn_str);
745 ret = ldb_add(s->ldap1.ldb, msg);
747 if (ret != LDB_SUCCESS) {
748 talloc_free(server_dn_str);
749 return NT_STATUS_LDAP(ret);
752 s->dest_dsa.server_dn_str = server_dn_str;
757 static NTSTATUS becomeDC_ldap1_server_object_modify(struct libnet_BecomeDC_state *s)
760 struct ldb_message *msg;
763 /* make a 'modify' msg, and only for serverReference */
764 msg = ldb_msg_new(s);
765 NT_STATUS_HAVE_NO_MEMORY(msg);
766 msg->dn = ldb_dn_new(msg, s->ldap1.ldb, s->dest_dsa.server_dn_str);
767 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
769 ret = ldb_msg_add_string(msg, "serverReference", s->dest_dsa.computer_dn_str);
772 return NT_STATUS_NO_MEMORY;
775 /* mark all the message elements (should be just one)
776 as LDB_FLAG_MOD_ADD */
777 for (i=0;i<msg->num_elements;i++) {
778 msg->elements[i].flags = LDB_FLAG_MOD_ADD;
781 ret = ldb_modify(s->ldap1.ldb, msg);
782 if (ret == LDB_SUCCESS) {
785 } else if (ret == LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) {
786 /* retry with LDB_FLAG_MOD_REPLACE */
789 return NT_STATUS_LDAP(ret);
792 /* mark all the message elements (should be just one)
793 as LDB_FLAG_MOD_REPLACE */
794 for (i=0;i<msg->num_elements;i++) {
795 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
798 ret = ldb_modify(s->ldap1.ldb, msg);
800 if (ret != LDB_SUCCESS) {
801 return NT_STATUS_LDAP(ret);
807 static void becomeDC_drsuapi_connect_send(struct libnet_BecomeDC_state *s,
808 struct becomeDC_drsuapi *drsuapi,
809 void (*recv_fn)(struct composite_context *req));
810 static void becomeDC_drsuapi1_connect_recv(struct composite_context *req);
811 static void becomeDC_connect_ldap2(struct libnet_BecomeDC_state *s);
813 static void becomeDC_connect_ldap1(struct libnet_BecomeDC_state *s)
815 struct composite_context *c = s->creq;
817 c->status = becomeDC_ldap_connect(s, &s->ldap1);
818 if (!composite_is_ok(c)) return;
820 c->status = becomeDC_ldap1_rootdse(s);
821 if (!composite_is_ok(c)) return;
823 c->status = becomeDC_ldap1_crossref_behavior_version(s);
824 if (!composite_is_ok(c)) return;
826 c->status = becomeDC_ldap1_domain_behavior_version(s);
827 if (!composite_is_ok(c)) return;
829 c->status = becomeDC_ldap1_schema_object_version(s);
830 if (!composite_is_ok(c)) return;
832 c->status = becomeDC_ldap1_w2k3_update_revision(s);
833 if (!composite_is_ok(c)) return;
835 c->status = becomeDC_ldap1_infrastructure_fsmo(s);
836 if (!composite_is_ok(c)) return;
838 c->status = becomeDC_ldap1_rid_manager_fsmo(s);
839 if (!composite_is_ok(c)) return;
841 c->status = becomeDC_ldap1_site_object(s);
842 if (!composite_is_ok(c)) return;
844 c->status = becomeDC_check_options(s);
845 if (!composite_is_ok(c)) return;
847 c->status = becomeDC_ldap1_computer_object(s);
848 if (!composite_is_ok(c)) return;
850 c->status = becomeDC_ldap1_server_object_1(s);
851 if (!composite_is_ok(c)) return;
853 c->status = becomeDC_ldap1_server_object_2(s);
854 if (!composite_is_ok(c)) return;
856 c->status = becomeDC_ldap1_server_object_add(s);
857 if (!composite_is_ok(c)) return;
859 c->status = becomeDC_ldap1_server_object_modify(s);
860 if (!composite_is_ok(c)) return;
862 becomeDC_drsuapi_connect_send(s, &s->drsuapi1, becomeDC_drsuapi1_connect_recv);
865 static void becomeDC_drsuapi_connect_send(struct libnet_BecomeDC_state *s,
866 struct becomeDC_drsuapi *drsuapi,
867 void (*recv_fn)(struct composite_context *req))
869 struct composite_context *c = s->creq;
870 struct composite_context *creq;
875 if (!drsuapi->binding) {
876 binding_str = talloc_asprintf(s, "ncacn_ip_tcp:%s[krb5,seal]", s->source_dsa.dns_name);
877 if (composite_nomem(binding_str, c)) return;
879 c->status = dcerpc_parse_binding(s, binding_str, &drsuapi->binding);
880 talloc_free(binding_str);
881 if (!composite_is_ok(c)) return;
884 creq = dcerpc_pipe_connect_b_send(s, drsuapi->binding, &dcerpc_table_drsuapi,
885 s->libnet->cred, s->libnet->event_ctx);
886 composite_continue(c, creq, recv_fn, s);
889 static void becomeDC_drsuapi_bind_send(struct libnet_BecomeDC_state *s,
890 struct becomeDC_drsuapi *drsuapi,
891 void (*recv_fn)(struct rpc_request *req));
892 static void becomeDC_drsuapi1_bind_recv(struct rpc_request *req);
894 static void becomeDC_drsuapi1_connect_recv(struct composite_context *req)
896 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
897 struct libnet_BecomeDC_state);
898 struct composite_context *c = s->creq;
900 c->status = dcerpc_pipe_connect_b_recv(req, s, &s->drsuapi1.pipe);
901 if (!composite_is_ok(c)) return;
903 becomeDC_drsuapi_bind_send(s, &s->drsuapi1, becomeDC_drsuapi1_bind_recv);
906 static void becomeDC_drsuapi_bind_send(struct libnet_BecomeDC_state *s,
907 struct becomeDC_drsuapi *drsuapi,
908 void (*recv_fn)(struct rpc_request *req))
910 struct composite_context *c = s->creq;
911 struct rpc_request *req;
912 struct drsuapi_DsBindInfo28 *bind_info28;
914 GUID_from_string(DRSUAPI_DS_BIND_GUID_W2K3, &drsuapi->bind_guid);
916 bind_info28 = &drsuapi->local_info28;
917 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_BASE;
918 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION;
919 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI;
920 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2;
921 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS;
922 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1;
923 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION;
924 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE;
925 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2;
926 if (s->domain.behavior_version == 2) {
927 /* TODO: find out how this is really triggered! */
928 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION;
930 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2;
931 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD;
932 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND;
933 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO;
934 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION;
935 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01;
936 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP;
937 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY;
938 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3;
939 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_00100000;
940 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2;
941 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6;
942 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS;
943 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8;
944 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5;
945 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6;
946 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3;
947 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7;
948 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT;
949 #if 0 /* we don't support XPRESS compression yet */
950 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS;
952 bind_info28->site_guid = s->dest_dsa.site_guid;
953 if (s->domain.behavior_version == 2) {
954 /* TODO: find out how this is really triggered! */
955 bind_info28->u1 = 528;
957 bind_info28->u1 = 516;
959 bind_info28->repl_epoch = 0;
961 drsuapi->bind_info_ctr.length = 28;
962 drsuapi->bind_info_ctr.info.info28 = *bind_info28;
964 drsuapi->bind_r.in.bind_guid = &drsuapi->bind_guid;
965 drsuapi->bind_r.in.bind_info = &drsuapi->bind_info_ctr;
966 drsuapi->bind_r.out.bind_handle = &drsuapi->bind_handle;
968 req = dcerpc_drsuapi_DsBind_send(drsuapi->pipe, s, &drsuapi->bind_r);
969 composite_continue_rpc(c, req, recv_fn, s);
972 static WERROR becomeDC_drsuapi_bind_recv(struct libnet_BecomeDC_state *s,
973 struct becomeDC_drsuapi *drsuapi)
975 if (!W_ERROR_IS_OK(drsuapi->bind_r.out.result)) {
976 return drsuapi->bind_r.out.result;
979 ZERO_STRUCT(drsuapi->remote_info28);
980 if (drsuapi->bind_r.out.bind_info) {
981 switch (drsuapi->bind_r.out.bind_info->length) {
983 struct drsuapi_DsBindInfo24 *info24;
984 info24 = &drsuapi->bind_r.out.bind_info->info.info24;
985 drsuapi->remote_info28.supported_extensions = info24->supported_extensions;
986 drsuapi->remote_info28.site_guid = info24->site_guid;
987 drsuapi->remote_info28.u1 = info24->u1;
988 drsuapi->remote_info28.repl_epoch = 0;
992 drsuapi->remote_info28 = drsuapi->bind_r.out.bind_info->info.info28;
1000 static void becomeDC_drsuapi1_add_entry_send(struct libnet_BecomeDC_state *s);
1002 static void becomeDC_drsuapi1_bind_recv(struct rpc_request *req)
1004 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
1005 struct libnet_BecomeDC_state);
1006 struct composite_context *c = s->creq;
1009 c->status = dcerpc_ndr_request_recv(req);
1010 if (!composite_is_ok(c)) return;
1012 status = becomeDC_drsuapi_bind_recv(s, &s->drsuapi1);
1013 if (!W_ERROR_IS_OK(status)) {
1014 composite_error(c, werror_to_ntstatus(status));
1018 becomeDC_drsuapi1_add_entry_send(s);
1021 static void becomeDC_drsuapi1_add_entry_recv(struct rpc_request *req);
1023 static void becomeDC_drsuapi1_add_entry_send(struct libnet_BecomeDC_state *s)
1025 struct composite_context *c = s->creq;
1026 struct rpc_request *req;
1027 struct drsuapi_DsAddEntry *r;
1028 struct drsuapi_DsReplicaObjectIdentifier *identifier;
1029 uint32_t num_attrs, i = 0;
1030 struct drsuapi_DsReplicaAttribute *attrs;
1033 /* choose a random invocationId */
1034 s->dest_dsa.invocation_id = GUID_random();
1037 * if the schema version indicates w2k3, then
1038 * also send some w2k3 specific attributes
1040 if (s->forest.schema_object_version >= 30) {
1046 r = talloc_zero(s, struct drsuapi_DsAddEntry);
1047 if (composite_nomem(r, c)) return;
1049 /* setup identifier */
1050 identifier = talloc(r, struct drsuapi_DsReplicaObjectIdentifier);
1051 if (composite_nomem(identifier, c)) return;
1052 identifier->guid = GUID_zero();
1053 identifier->sid = s->zero_sid;
1054 identifier->dn = talloc_asprintf(identifier, "CN=NTDS Settings,%s",
1055 s->dest_dsa.server_dn_str);
1056 if (composite_nomem(identifier->dn, c)) return;
1058 /* allocate attribute array */
1060 attrs = talloc_array(r, struct drsuapi_DsReplicaAttribute, num_attrs);
1061 if (composite_nomem(attrs, c)) return;
1063 /* ntSecurityDescriptor */
1065 struct drsuapi_DsAttributeValueSecurityDescriptor *vs;
1066 struct security_descriptor *v;
1067 struct dom_sid *domain_admins_sid;
1068 const char *domain_admins_sid_str;
1070 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueSecurityDescriptor, 1);
1071 if (composite_nomem(vs, c)) return;
1073 domain_admins_sid = dom_sid_add_rid(vs, s->domain.sid, DOMAIN_RID_ADMINS);
1074 if (composite_nomem(domain_admins_sid, c)) return;
1076 domain_admins_sid_str = dom_sid_string(domain_admins_sid, domain_admins_sid);
1077 if (composite_nomem(domain_admins_sid_str, c)) return;
1079 v = security_descriptor_create(vs,
1080 /* owner: domain admins */
1081 domain_admins_sid_str,
1082 /* owner group: domain admins */
1083 domain_admins_sid_str,
1084 /* authenticated users */
1085 SID_NT_AUTHENTICATED_USERS,
1086 SEC_ACE_TYPE_ACCESS_ALLOWED,
1087 SEC_STD_READ_CONTROL |
1090 SEC_ADS_LIST_OBJECT,
1093 domain_admins_sid_str,
1094 SEC_ACE_TYPE_ACCESS_ALLOWED,
1096 SEC_ADS_CREATE_CHILD |
1098 SEC_ADS_SELF_WRITE |
1100 SEC_ADS_WRITE_PROP |
1101 SEC_ADS_DELETE_TREE |
1102 SEC_ADS_LIST_OBJECT |
1103 SEC_ADS_CONTROL_ACCESS,
1107 SEC_ACE_TYPE_ACCESS_ALLOWED,
1109 SEC_ADS_CREATE_CHILD |
1110 SEC_ADS_DELETE_CHILD |
1112 SEC_ADS_SELF_WRITE |
1114 SEC_ADS_WRITE_PROP |
1115 SEC_ADS_DELETE_TREE |
1116 SEC_ADS_LIST_OBJECT |
1117 SEC_ADS_CONTROL_ACCESS,
1121 if (composite_nomem(v, c)) return;
1125 attrs[i].attid = DRSUAPI_ATTRIBUTE_ntSecurityDescriptor;
1126 attrs[i].value_ctr.security_descriptor.num_values = 1;
1127 attrs[i].value_ctr.security_descriptor.values = vs;
1132 /* objectClass: nTDSDSA */
1134 struct drsuapi_DsAttributeValueObjectClassId *vs;
1135 enum drsuapi_DsObjectClassId *v;
1137 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueObjectClassId, 1);
1138 if (composite_nomem(vs, c)) return;
1140 v = talloc_array(vs, enum drsuapi_DsObjectClassId, 1);
1141 if (composite_nomem(v, c)) return;
1143 /* value for nTDSDSA */
1146 vs[0].objectClassId = &v[0];
1148 attrs[i].attid = DRSUAPI_ATTRIBUTE_objectClass;
1149 attrs[i].value_ctr.object_class_id.num_values = 1;
1150 attrs[i].value_ctr.object_class_id.values = vs;
1155 /* objectCategory: CN=NTDS-DSA,CN=Schema,... */
1157 struct drsuapi_DsAttributeValueDNString *vs;
1158 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1160 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 1);
1161 if (composite_nomem(vs, c)) return;
1163 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 1);
1164 if (composite_nomem(v, c)) return;
1166 v[0].guid = GUID_zero();
1167 v[0].sid = s->zero_sid;
1168 v[0].dn = talloc_asprintf(v, "CN=NTDS-DSA,%s",
1169 s->forest.schema_dn_str);
1170 if (composite_nomem(v->dn, c)) return;
1172 vs[0].object = &v[0];
1174 attrs[i].attid = DRSUAPI_ATTRIBUTE_objectCategory;
1175 attrs[i].value_ctr.dn_string.num_values = 1;
1176 attrs[i].value_ctr.dn_string.values = vs;
1181 /* invocationId: random guid */
1183 struct drsuapi_DsAttributeValueGUID *vs;
1186 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueGUID, 1);
1187 if (composite_nomem(vs, c)) return;
1189 v = talloc_array(vs, struct GUID, 1);
1190 if (composite_nomem(v, c)) return;
1192 v[0] = s->dest_dsa.invocation_id;
1196 attrs[i].attid = DRSUAPI_ATTRIBUTE_invocationId;
1197 attrs[i].value_ctr.guid.num_values = 1;
1198 attrs[i].value_ctr.guid.values = vs;
1203 /* hasMasterNCs: ... */
1205 struct drsuapi_DsAttributeValueDNString *vs;
1206 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1208 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 3);
1209 if (composite_nomem(vs, c)) return;
1211 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 3);
1212 if (composite_nomem(v, c)) return;
1214 v[0].guid = GUID_zero();
1215 v[0].sid = s->zero_sid;
1216 v[0].dn = s->forest.config_dn_str;
1218 v[1].guid = GUID_zero();
1219 v[1].sid = s->zero_sid;
1220 v[1].dn = s->domain.dn_str;
1222 v[2].guid = GUID_zero();
1223 v[2].sid = s->zero_sid;
1224 v[2].dn = s->forest.schema_dn_str;
1226 vs[0].object = &v[0];
1227 vs[1].object = &v[1];
1228 vs[2].object = &v[2];
1230 attrs[i].attid = DRSUAPI_ATTRIBUTE_hasMasterNCs;
1231 attrs[i].value_ctr.dn_string.num_values = 3;
1232 attrs[i].value_ctr.dn_string.values = vs;
1237 /* msDS-hasMasterNCs: ... */
1239 struct drsuapi_DsAttributeValueDNString *vs;
1240 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1242 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 3);
1243 if (composite_nomem(vs, c)) return;
1245 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 3);
1246 if (composite_nomem(v, c)) return;
1248 v[0].guid = GUID_zero();
1249 v[0].sid = s->zero_sid;
1250 v[0].dn = s->forest.config_dn_str;
1252 v[1].guid = GUID_zero();
1253 v[1].sid = s->zero_sid;
1254 v[1].dn = s->domain.dn_str;
1256 v[2].guid = GUID_zero();
1257 v[2].sid = s->zero_sid;
1258 v[2].dn = s->forest.schema_dn_str;
1260 vs[0].object = &v[0];
1261 vs[1].object = &v[1];
1262 vs[2].object = &v[2];
1264 attrs[i].attid = DRSUAPI_ATTRIBUTE_msDS_hasMasterNCs;
1265 attrs[i].value_ctr.dn_string.num_values = 3;
1266 attrs[i].value_ctr.dn_string.values = vs;
1271 /* dMDLocation: CN=Schema,... */
1273 struct drsuapi_DsAttributeValueDNString *vs;
1274 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1276 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 1);
1277 if (composite_nomem(vs, c)) return;
1279 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 1);
1280 if (composite_nomem(v, c)) return;
1282 v[0].guid = GUID_zero();
1283 v[0].sid = s->zero_sid;
1284 v[0].dn = s->forest.schema_dn_str;
1286 vs[0].object = &v[0];
1288 attrs[i].attid = DRSUAPI_ATTRIBUTE_dMDLocation;
1289 attrs[i].value_ctr.dn_string.num_values = 1;
1290 attrs[i].value_ctr.dn_string.values = vs;
1295 /* msDS-HasDomainNCs: <domain_partition> */
1297 struct drsuapi_DsAttributeValueDNString *vs;
1298 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1300 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 1);
1301 if (composite_nomem(vs, c)) return;
1303 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 1);
1304 if (composite_nomem(v, c)) return;
1306 v[0].guid = GUID_zero();
1307 v[0].sid = s->zero_sid;
1308 v[0].dn = s->domain.dn_str;
1310 vs[0].object = &v[0];
1312 attrs[i].attid = DRSUAPI_ATTRIBUTE_msDS_HasDomainNCs;
1313 attrs[i].value_ctr.dn_string.num_values = 1;
1314 attrs[i].value_ctr.dn_string.values = vs;
1319 /* msDS-Behavior-Version */
1321 struct drsuapi_DsAttributeValueUINT32 *vs;
1324 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueUINT32, 1);
1325 if (composite_nomem(vs, c)) return;
1327 v = talloc_array(vs, uint32_t, 1);
1328 if (composite_nomem(v, c)) return;
1330 v[0] = DS_BEHAVIOR_WIN2003;
1332 vs[0].value = &v[0];
1334 attrs[i].attid = DRSUAPI_ATTRIBUTE_msDS_Behavior_Version;
1335 attrs[i].value_ctr.uint32.num_values = 1;
1336 attrs[i].value_ctr.uint32.values = vs;
1343 struct drsuapi_DsAttributeValueUINT32 *vs;
1346 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueUINT32, 1);
1347 if (composite_nomem(vs, c)) return;
1349 v = talloc_array(vs, uint32_t, 1);
1350 if (composite_nomem(v, c)) return;
1352 v[0] = SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE;
1354 vs[0].value = &v[0];
1356 attrs[i].attid = DRSUAPI_ATTRIBUTE_systemFlags;
1357 attrs[i].value_ctr.uint32.num_values = 1;
1358 attrs[i].value_ctr.uint32.values = vs;
1363 /* serverReference: ... */
1365 struct drsuapi_DsAttributeValueDNString *vs;
1366 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1368 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 1);
1369 if (composite_nomem(vs, c)) return;
1371 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 1);
1372 if (composite_nomem(v, c)) return;
1374 v[0].guid = GUID_zero();
1375 v[0].sid = s->zero_sid;
1376 v[0].dn = s->dest_dsa.computer_dn_str;
1378 vs[0].object = &v[0];
1380 attrs[i].attid = DRSUAPI_ATTRIBUTE_serverReference;
1381 attrs[i].value_ctr.dn_string.num_values = 1;
1382 attrs[i].value_ctr.dn_string.values = vs;
1387 /* truncate the attribute list to the attribute count we have filled in */
1390 /* setup request structure */
1391 r->in.bind_handle = &s->drsuapi1.bind_handle;
1393 r->in.req.req2.first_object.next_object = NULL;
1394 r->in.req.req2.first_object.object.identifier = identifier;
1395 r->in.req.req2.first_object.object.unknown1 = 0x00000000;
1396 r->in.req.req2.first_object.object.attribute_ctr.num_attributes = num_attrs;
1397 r->in.req.req2.first_object.object.attribute_ctr.attributes = attrs;
1399 req = dcerpc_drsuapi_DsAddEntry_send(s->drsuapi1.pipe, r, r);
1400 composite_continue_rpc(c, req, becomeDC_drsuapi1_add_entry_recv, s);
1403 static void becomeDC_drsuapi2_connect_recv(struct composite_context *req);
1404 static NTSTATUS becomeDC_prepare_db(struct libnet_BecomeDC_state *s);
1406 static void becomeDC_drsuapi1_add_entry_recv(struct rpc_request *req)
1408 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
1409 struct libnet_BecomeDC_state);
1410 struct composite_context *c = s->creq;
1411 struct drsuapi_DsAddEntry *r = talloc_get_type(req->ndr.struct_ptr,
1412 struct drsuapi_DsAddEntry);
1414 c->status = dcerpc_ndr_request_recv(req);
1415 if (!composite_is_ok(c)) return;
1417 if (!W_ERROR_IS_OK(r->out.result)) {
1418 composite_error(c, werror_to_ntstatus(r->out.result));
1422 if (r->out.level == 3) {
1423 if (r->out.ctr.ctr3.count != 1) {
1426 if (r->out.ctr.ctr3.level != 1) {
1427 composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
1431 if (!r->out.ctr.ctr3.error) {
1432 composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
1436 status = r->out.ctr.ctr3.error->info1.status;
1438 if (!r->out.ctr.ctr3.error->info1.info) {
1439 composite_error(c, werror_to_ntstatus(status));
1443 /* see if we can get a more detailed error */
1444 switch (r->out.ctr.ctr3.error->info1.level) {
1446 status = r->out.ctr.ctr3.error->info1.info->error1.status;
1452 status = r->out.ctr.ctr3.error->info1.info->errorX.status;
1456 composite_error(c, werror_to_ntstatus(status));
1460 s->dest_dsa.ntds_guid = r->out.ctr.ctr3.objects[0].guid;
1461 } else if (r->out.level == 2) {
1462 if (r->out.ctr.ctr2.count != 1) {
1463 composite_error(c, werror_to_ntstatus(r->out.ctr.ctr2.error.status));
1467 s->dest_dsa.ntds_guid = r->out.ctr.ctr2.objects[0].guid;
1469 composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
1475 c->status = becomeDC_prepare_db(s);
1476 if (!composite_is_ok(c)) return;
1478 becomeDC_drsuapi_connect_send(s, &s->drsuapi2, becomeDC_drsuapi2_connect_recv);
1481 static NTSTATUS becomeDC_prepare_db(struct libnet_BecomeDC_state *s)
1483 if (!s->callbacks.prepare_db) return NT_STATUS_OK;
1485 s->_pp.domain = &s->domain;
1486 s->_pp.forest = &s->forest;
1487 s->_pp.source_dsa = &s->source_dsa;
1488 s->_pp.dest_dsa = &s->dest_dsa;
1490 return s->callbacks.prepare_db(s->callbacks.private_data, &s->_pp);
1493 static void becomeDC_drsuapi2_bind_recv(struct rpc_request *req);
1495 static void becomeDC_drsuapi2_connect_recv(struct composite_context *req)
1497 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
1498 struct libnet_BecomeDC_state);
1499 struct composite_context *c = s->creq;
1501 c->status = dcerpc_pipe_connect_b_recv(req, s, &s->drsuapi2.pipe);
1502 if (!composite_is_ok(c)) return;
1504 becomeDC_drsuapi_bind_send(s, &s->drsuapi2, becomeDC_drsuapi2_bind_recv);
1507 static void becomeDC_drsuapi3_connect_recv(struct composite_context *req);
1509 static void becomeDC_drsuapi2_bind_recv(struct rpc_request *req)
1511 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
1512 struct libnet_BecomeDC_state);
1513 struct composite_context *c = s->creq;
1517 c->status = dcerpc_ndr_request_recv(req);
1518 if (!composite_is_ok(c)) return;
1520 status = becomeDC_drsuapi_bind_recv(s, &s->drsuapi2);
1521 if (!W_ERROR_IS_OK(status)) {
1522 composite_error(c, werror_to_ntstatus(status));
1526 /* this avoids the epmapper lookup on the 2nd connection */
1527 binding_str = dcerpc_binding_string(s, s->drsuapi2.binding);
1528 if (composite_nomem(binding_str, c)) return;
1530 c->status = dcerpc_parse_binding(s, binding_str, &s->drsuapi3.binding);
1531 talloc_free(binding_str);
1532 if (!composite_is_ok(c)) return;
1534 becomeDC_drsuapi_connect_send(s, &s->drsuapi3, becomeDC_drsuapi3_connect_recv);
1537 static void becomeDC_drsuapi3_pull_schema_send(struct libnet_BecomeDC_state *s);
1539 static void becomeDC_drsuapi3_connect_recv(struct composite_context *req)
1541 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
1542 struct libnet_BecomeDC_state);
1543 struct composite_context *c = s->creq;
1545 c->status = dcerpc_pipe_connect_b_recv(req, s, &s->drsuapi3.pipe);
1546 if (!composite_is_ok(c)) return;
1548 becomeDC_drsuapi3_pull_schema_send(s);
1551 static void becomeDC_drsuapi_pull_partition_send(struct libnet_BecomeDC_state *s,
1552 struct becomeDC_drsuapi *drsuapi_h,
1553 struct becomeDC_drsuapi *drsuapi_p,
1554 struct becomeDC_partition *partition,
1555 void (*recv_fn)(struct rpc_request *req))
1557 struct composite_context *c = s->creq;
1558 struct rpc_request *req;
1559 struct drsuapi_DsGetNCChanges *r;
1561 r = talloc(s, struct drsuapi_DsGetNCChanges);
1562 if (composite_nomem(r, c)) return;
1564 r->in.bind_handle = &drsuapi_h->bind_handle;
1565 if (drsuapi_h->remote_info28.supported_extensions & DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8) {
1567 r->in.req.req8.destination_dsa_guid = partition->destination_dsa_guid;
1568 r->in.req.req8.source_dsa_invocation_id = partition->source_dsa_invocation_id;
1569 r->in.req.req8.naming_context = &partition->nc;
1570 r->in.req.req8.highwatermark = partition->highwatermark;
1571 r->in.req.req8.uptodateness_vector = partition->uptodateness_vector;
1572 r->in.req.req8.replica_flags = partition->replica_flags;
1573 r->in.req.req8.max_object_count = 133;
1574 r->in.req.req8.max_ndr_size = 1336811;
1575 r->in.req.req8.unknown4 = 0;
1576 r->in.req.req8.h1 = 0;
1577 r->in.req.req8.unique_ptr1 = 0;
1578 r->in.req.req8.unique_ptr2 = 0;
1579 r->in.req.req8.mapping_ctr.num_mappings = 0;
1580 r->in.req.req8.mapping_ctr.mappings = NULL;
1583 r->in.req.req5.destination_dsa_guid = partition->destination_dsa_guid;
1584 r->in.req.req5.source_dsa_invocation_id = partition->source_dsa_invocation_id;
1585 r->in.req.req5.naming_context = &partition->nc;
1586 r->in.req.req5.highwatermark = partition->highwatermark;
1587 r->in.req.req5.uptodateness_vector = partition->uptodateness_vector;
1588 r->in.req.req5.replica_flags = partition->replica_flags;
1589 r->in.req.req5.max_object_count = 133;
1590 r->in.req.req5.max_ndr_size = 1336770;
1591 r->in.req.req5.unknown4 = 0;
1592 r->in.req.req5.h1 = 0;
1595 DEBUG(0,("start NC[%s] tmp_highest_usn[%llu] highest_usn[%llu]\n",
1597 partition->highwatermark.tmp_highest_usn,
1598 partition->highwatermark.highest_usn));
1601 * we should try to use the drsuapi_p->pipe here, as w2k3 does
1602 * but it seems that some extra flags in the DCERPC Bind call
1603 * are needed for it. Or the same KRB5 TGS is needed on both
1606 req = dcerpc_drsuapi_DsGetNCChanges_send(drsuapi_h->pipe, r, r);
1607 composite_continue_rpc(c, req, recv_fn, s);
1610 static WERROR becomeDC_drsuapi_pull_partition_recv(struct libnet_BecomeDC_state *s,
1611 struct becomeDC_partition *partition,
1612 struct drsuapi_DsGetNCChanges *r)
1614 struct drsuapi_DsGetNCChangesCtr1 *ctr1 = NULL;
1615 struct drsuapi_DsGetNCChangesCtr6 *ctr6 = NULL;
1616 uint32_t out_level = 0;
1617 struct GUID *source_dsa_guid;
1618 struct GUID *source_dsa_invocation_id;
1619 struct drsuapi_DsReplicaHighWaterMark *new_highwatermark;
1620 struct drsuapi_DsReplicaObjectListItemEx *first_object;
1621 struct drsuapi_DsReplicaObjectListItemEx *cur;
1623 if (!W_ERROR_IS_OK(r->out.result)) {
1624 return r->out.result;
1627 if (r->out.level == 1) {
1629 ctr1 = &r->out.ctr.ctr1;
1630 } else if (r->out.level == 2) {
1632 ctr1 = r->out.ctr.ctr2.ctr.mszip1.ctr1;
1633 } else if (r->out.level == 6) {
1635 ctr6 = &r->out.ctr.ctr6;
1636 } else if (r->out.level == 7 &&
1637 r->out.ctr.ctr7.level == 6 &&
1638 r->out.ctr.ctr7.type == DRSUAPI_COMPRESSION_TYPE_MSZIP) {
1640 ctr6 = r->out.ctr.ctr7.ctr.mszip6.ctr6;
1642 return WERR_BAD_NET_RESP;
1645 switch (out_level) {
1647 source_dsa_guid = &ctr1->source_dsa_guid;
1648 source_dsa_invocation_id = &ctr1->source_dsa_invocation_id;
1649 new_highwatermark = &ctr1->new_highwatermark;
1650 first_object = ctr1->first_object;
1653 source_dsa_guid = &ctr6->source_dsa_guid;
1654 source_dsa_invocation_id = &ctr6->source_dsa_invocation_id;
1655 new_highwatermark = &ctr6->new_highwatermark;
1656 first_object = ctr6->first_object;
1660 partition->highwatermark = *new_highwatermark;
1661 partition->source_dsa_guid = *source_dsa_guid;
1662 partition->source_dsa_invocation_id = *source_dsa_invocation_id;
1664 if (!partition->first_object) {
1665 partition->first_object = talloc_steal(s, first_object);
1667 partition->last_object->next_object = talloc_steal(partition->last_object,
1670 for (cur = first_object; cur->next_object; cur = cur->next_object) {}
1671 partition->last_object = cur;
1673 DEBUG(0,("end NC[%s] tmp_highest_usn[%llu] highest_usn[%llu]\n",
1675 partition->highwatermark.tmp_highest_usn,
1676 partition->highwatermark.highest_usn));
1678 if (partition->store_chunk) {
1680 nt_status = partition->store_chunk(s->callbacks.private_data, NULL);
1681 if (!NT_STATUS_IS_OK(nt_status)) {
1682 return ntstatus_to_werror(nt_status);
1689 static void becomeDC_drsuapi3_pull_schema_recv(struct rpc_request *req);
1691 static void becomeDC_drsuapi3_pull_schema_send(struct libnet_BecomeDC_state *s)
1693 s->schema_part.nc.guid = GUID_zero();
1694 s->schema_part.nc.sid = s->zero_sid;
1695 s->schema_part.nc.dn = s->forest.schema_dn_str;
1697 s->schema_part.destination_dsa_guid = s->drsuapi2.bind_guid;
1699 s->schema_part.replica_flags = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
1700 | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
1701 | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS
1702 | DRSUAPI_DS_REPLICA_NEIGHBOUR_FULL_IN_PROGRESS
1703 | DRSUAPI_DS_REPLICA_NEIGHBOUR_NEVER_SYNCED
1704 | DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES;
1706 s->schema_part.store_chunk = s->callbacks.schema_chunk;
1708 becomeDC_drsuapi_pull_partition_send(s, &s->drsuapi2, &s->drsuapi3, &s->schema_part,
1709 becomeDC_drsuapi3_pull_schema_recv);
1712 static void becomeDC_drsuapi3_pull_config_send(struct libnet_BecomeDC_state *s);
1714 static void becomeDC_drsuapi3_pull_schema_recv(struct rpc_request *req)
1716 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
1717 struct libnet_BecomeDC_state);
1718 struct composite_context *c = s->creq;
1719 struct drsuapi_DsGetNCChanges *r = talloc_get_type(req->ndr.struct_ptr,
1720 struct drsuapi_DsGetNCChanges);
1723 c->status = dcerpc_ndr_request_recv(req);
1724 if (!composite_is_ok(c)) return;
1726 status = becomeDC_drsuapi_pull_partition_recv(s, &s->schema_part, r);
1727 if (!W_ERROR_IS_OK(status)) {
1728 composite_error(c, werror_to_ntstatus(status));
1734 if (s->schema_part.highwatermark.tmp_highest_usn > s->schema_part.highwatermark.highest_usn) {
1735 becomeDC_drsuapi_pull_partition_send(s, &s->drsuapi2, &s->drsuapi3, &s->schema_part,
1736 becomeDC_drsuapi3_pull_schema_recv);
1740 becomeDC_drsuapi3_pull_config_send(s);
1743 static void becomeDC_drsuapi3_pull_config_recv(struct rpc_request *req);
1745 static void becomeDC_drsuapi3_pull_config_send(struct libnet_BecomeDC_state *s)
1747 s->config_part.nc.guid = GUID_zero();
1748 s->config_part.nc.sid = s->zero_sid;
1749 s->config_part.nc.dn = s->forest.config_dn_str;
1751 s->config_part.destination_dsa_guid = s->drsuapi2.bind_guid;
1753 s->config_part.replica_flags = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
1754 | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
1755 | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS
1756 | DRSUAPI_DS_REPLICA_NEIGHBOUR_FULL_IN_PROGRESS
1757 | DRSUAPI_DS_REPLICA_NEIGHBOUR_NEVER_SYNCED
1758 | DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES;
1760 s->config_part.store_chunk = s->callbacks.config_chunk;
1762 becomeDC_drsuapi_pull_partition_send(s, &s->drsuapi2, &s->drsuapi3, &s->config_part,
1763 becomeDC_drsuapi3_pull_config_recv);
1766 static void becomeDC_drsuapi3_pull_config_recv(struct rpc_request *req)
1768 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
1769 struct libnet_BecomeDC_state);
1770 struct composite_context *c = s->creq;
1771 struct drsuapi_DsGetNCChanges *r = talloc_get_type(req->ndr.struct_ptr,
1772 struct drsuapi_DsGetNCChanges);
1775 c->status = dcerpc_ndr_request_recv(req);
1776 if (!composite_is_ok(c)) return;
1778 status = becomeDC_drsuapi_pull_partition_recv(s, &s->config_part, r);
1779 if (!W_ERROR_IS_OK(status)) {
1780 composite_error(c, werror_to_ntstatus(status));
1786 if (s->config_part.highwatermark.tmp_highest_usn > s->config_part.highwatermark.highest_usn) {
1787 becomeDC_drsuapi_pull_partition_send(s, &s->drsuapi2, &s->drsuapi3, &s->config_part,
1788 becomeDC_drsuapi3_pull_config_recv);
1792 becomeDC_connect_ldap2(s);
1795 static void becomeDC_drsuapi3_pull_domain_recv(struct rpc_request *req);
1797 static void becomeDC_drsuapi3_pull_domain_send(struct libnet_BecomeDC_state *s)
1799 s->domain_part.nc.guid = GUID_zero();
1800 s->domain_part.nc.sid = s->zero_sid;
1801 s->domain_part.nc.dn = s->domain.dn_str;
1803 s->domain_part.destination_dsa_guid = s->drsuapi2.bind_guid;
1805 s->domain_part.replica_flags = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
1806 | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
1807 | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS
1808 | DRSUAPI_DS_REPLICA_NEIGHBOUR_FULL_IN_PROGRESS
1809 | DRSUAPI_DS_REPLICA_NEIGHBOUR_NEVER_SYNCED
1810 | DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES;
1812 s->domain_part.store_chunk = s->callbacks.domain_chunk;
1814 becomeDC_drsuapi_pull_partition_send(s, &s->drsuapi2, &s->drsuapi3, &s->domain_part,
1815 becomeDC_drsuapi3_pull_domain_recv);
1818 static void becomeDC_drsuapi_update_refs_send(struct libnet_BecomeDC_state *s,
1819 struct becomeDC_drsuapi *drsuapi,
1820 struct becomeDC_partition *partition,
1821 void (*recv_fn)(struct rpc_request *req));
1822 static void becomeDC_drsuapi2_update_refs_schema_recv(struct rpc_request *req);
1824 static void becomeDC_drsuapi3_pull_domain_recv(struct rpc_request *req)
1826 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
1827 struct libnet_BecomeDC_state);
1828 struct composite_context *c = s->creq;
1829 struct drsuapi_DsGetNCChanges *r = talloc_get_type(req->ndr.struct_ptr,
1830 struct drsuapi_DsGetNCChanges);
1833 c->status = dcerpc_ndr_request_recv(req);
1834 if (!composite_is_ok(c)) return;
1836 status = becomeDC_drsuapi_pull_partition_recv(s, &s->domain_part, r);
1837 if (!W_ERROR_IS_OK(status)) {
1838 composite_error(c, werror_to_ntstatus(status));
1844 if (s->domain_part.highwatermark.tmp_highest_usn > s->domain_part.highwatermark.highest_usn) {
1845 becomeDC_drsuapi_pull_partition_send(s, &s->drsuapi2, &s->drsuapi3, &s->domain_part,
1846 becomeDC_drsuapi3_pull_domain_recv);
1850 becomeDC_drsuapi_update_refs_send(s, &s->drsuapi2, &s->schema_part,
1851 becomeDC_drsuapi2_update_refs_schema_recv);
1854 static void becomeDC_drsuapi_update_refs_send(struct libnet_BecomeDC_state *s,
1855 struct becomeDC_drsuapi *drsuapi,
1856 struct becomeDC_partition *partition,
1857 void (*recv_fn)(struct rpc_request *req))
1859 struct composite_context *c = s->creq;
1860 struct rpc_request *req;
1861 struct drsuapi_DsReplicaUpdateRefs *r;
1862 const char *ntds_guid_str;
1863 const char *ntds_dns_name;
1865 r = talloc(s, struct drsuapi_DsReplicaUpdateRefs);
1866 if (composite_nomem(r, c)) return;
1868 ntds_guid_str = GUID_string(r, &s->dest_dsa.ntds_guid);
1869 if (composite_nomem(ntds_guid_str, c)) return;
1871 ntds_dns_name = talloc_asprintf(r, "%s._msdcs.%s",
1873 s->domain.dns_name);
1874 if (composite_nomem(ntds_dns_name, c)) return;
1876 r->in.bind_handle = &drsuapi->bind_handle;
1878 r->in.req.req1.naming_context = &partition->nc;
1879 r->in.req.req1.dest_dsa_dns_name= ntds_dns_name;
1880 r->in.req.req1.dest_dsa_guid = s->dest_dsa.ntds_guid;
1881 r->in.req.req1.options = DRSUAPI_DS_REPLICA_UPDATE_ADD_REFERENCE
1882 | DRSUAPI_DS_REPLICA_UPDATE_DELETE_REFERENCE
1883 | DRSUAPI_DS_REPLICA_UPDATE_0x00000010;
1885 req = dcerpc_drsuapi_DsReplicaUpdateRefs_send(drsuapi->pipe, r, r);
1886 composite_continue_rpc(c, req, recv_fn, s);
1889 static void becomeDC_drsuapi2_update_refs_config_recv(struct rpc_request *req);
1891 static void becomeDC_drsuapi2_update_refs_schema_recv(struct rpc_request *req)
1893 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
1894 struct libnet_BecomeDC_state);
1895 struct composite_context *c = s->creq;
1896 struct drsuapi_DsReplicaUpdateRefs *r = talloc_get_type(req->ndr.struct_ptr,
1897 struct drsuapi_DsReplicaUpdateRefs);
1899 c->status = dcerpc_ndr_request_recv(req);
1900 if (!composite_is_ok(c)) return;
1902 if (!W_ERROR_IS_OK(r->out.result)) {
1903 composite_error(c, werror_to_ntstatus(r->out.result));
1909 becomeDC_drsuapi_update_refs_send(s, &s->drsuapi2, &s->config_part,
1910 becomeDC_drsuapi2_update_refs_config_recv);
1913 static void becomeDC_drsuapi2_update_refs_domain_recv(struct rpc_request *req);
1915 static void becomeDC_drsuapi2_update_refs_config_recv(struct rpc_request *req)
1917 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
1918 struct libnet_BecomeDC_state);
1919 struct composite_context *c = s->creq;
1920 struct drsuapi_DsReplicaUpdateRefs *r = talloc_get_type(req->ndr.struct_ptr,
1921 struct drsuapi_DsReplicaUpdateRefs);
1923 c->status = dcerpc_ndr_request_recv(req);
1924 if (!composite_is_ok(c)) return;
1926 if (!W_ERROR_IS_OK(r->out.result)) {
1927 composite_error(c, werror_to_ntstatus(r->out.result));
1933 becomeDC_drsuapi_update_refs_send(s, &s->drsuapi2, &s->domain_part,
1934 becomeDC_drsuapi2_update_refs_domain_recv);
1937 static void becomeDC_drsuapi2_update_refs_domain_recv(struct rpc_request *req)
1939 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
1940 struct libnet_BecomeDC_state);
1941 struct composite_context *c = s->creq;
1942 struct drsuapi_DsReplicaUpdateRefs *r = talloc_get_type(req->ndr.struct_ptr,
1943 struct drsuapi_DsReplicaUpdateRefs);
1945 c->status = dcerpc_ndr_request_recv(req);
1946 if (!composite_is_ok(c)) return;
1948 if (!W_ERROR_IS_OK(r->out.result)) {
1949 composite_error(c, werror_to_ntstatus(r->out.result));
1955 /* TODO: use DDNS updates and register dns names */
1959 static NTSTATUS becomeDC_ldap2_modify_computer(struct libnet_BecomeDC_state *s)
1962 struct ldb_message *msg;
1964 uint32_t user_account_control = UF_SERVER_TRUST_ACCOUNT |
1965 UF_TRUSTED_FOR_DELEGATION;
1967 /* as the value is already as we want it to be, we're done */
1968 if (s->dest_dsa.user_account_control == user_account_control) {
1969 return NT_STATUS_OK;
1972 /* make a 'modify' msg, and only for serverReference */
1973 msg = ldb_msg_new(s);
1974 NT_STATUS_HAVE_NO_MEMORY(msg);
1975 msg->dn = ldb_dn_new(msg, s->ldap2.ldb, s->dest_dsa.computer_dn_str);
1976 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
1978 ret = ldb_msg_add_fmt(msg, "userAccountControl", "%u", user_account_control);
1981 return NT_STATUS_NO_MEMORY;
1984 /* mark all the message elements (should be just one)
1985 as LDB_FLAG_MOD_REPLACE */
1986 for (i=0;i<msg->num_elements;i++) {
1987 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
1990 ret = ldb_modify(s->ldap2.ldb, msg);
1992 if (ret != LDB_SUCCESS) {
1993 return NT_STATUS_LDAP(ret);
1996 s->dest_dsa.user_account_control = user_account_control;
1998 return NT_STATUS_OK;
2001 static NTSTATUS becomeDC_ldap2_move_computer(struct libnet_BecomeDC_state *s)
2004 struct ldb_result *r;
2005 struct ldb_dn *basedn;
2006 struct ldb_dn *old_dn;
2007 struct ldb_dn *new_dn;
2008 static const char *_1_1_attrs[] = {
2013 basedn = ldb_dn_new_fmt(s, s->ldap2.ldb, "<WKGUID=a361b2ffffd211d1aa4b00c04fd7d83a,%s>",
2015 NT_STATUS_HAVE_NO_MEMORY(basedn);
2017 ret = ldb_search(s->ldap2.ldb, basedn, LDB_SCOPE_BASE,
2018 "(objectClass=*)", _1_1_attrs, &r);
2019 talloc_free(basedn);
2020 if (ret != LDB_SUCCESS) {
2021 return NT_STATUS_LDAP(ret);
2022 } else if (r->count != 1) {
2024 return NT_STATUS_INVALID_NETWORK_RESPONSE;
2027 old_dn = ldb_dn_new(r, s->ldap2.ldb, s->dest_dsa.computer_dn_str);
2028 NT_STATUS_HAVE_NO_MEMORY(old_dn);
2030 new_dn = r->msgs[0]->dn;
2032 if (!ldb_dn_add_child_fmt(new_dn, "CN=%s", s->dest_dsa.netbios_name)) {
2034 return NT_STATUS_NO_MEMORY;
2037 if (ldb_dn_compare(old_dn, new_dn) == 0) {
2038 /* we don't need to rename if the old and new dn match */
2040 return NT_STATUS_OK;
2043 ret = ldb_rename(s->ldap2.ldb, old_dn, new_dn);
2044 if (ret != LDB_SUCCESS) {
2046 return NT_STATUS_LDAP(ret);
2049 s->dest_dsa.computer_dn_str = ldb_dn_alloc_linearized(s, new_dn);
2050 NT_STATUS_HAVE_NO_MEMORY(s->dest_dsa.computer_dn_str);
2054 return NT_STATUS_OK;
2057 static void becomeDC_connect_ldap2(struct libnet_BecomeDC_state *s)
2059 struct composite_context *c = s->creq;
2061 c->status = becomeDC_ldap_connect(s, &s->ldap2);
2062 if (!composite_is_ok(c)) return;
2064 c->status = becomeDC_ldap2_modify_computer(s);
2065 if (!composite_is_ok(c)) return;
2067 c->status = becomeDC_ldap2_move_computer(s);
2068 if (!composite_is_ok(c)) return;
2070 becomeDC_drsuapi3_pull_domain_send(s);
2073 struct composite_context *libnet_BecomeDC_send(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_BecomeDC *r)
2075 struct composite_context *c;
2076 struct libnet_BecomeDC_state *s;
2079 c = composite_create(mem_ctx, ctx->event_ctx);
2080 if (c == NULL) return NULL;
2082 s = talloc_zero(c, struct libnet_BecomeDC_state);
2083 if (composite_nomem(s, c)) return c;
2084 c->private_data = s;
2089 s->domain.dns_name = talloc_strdup(s, r->in.domain_dns_name);
2090 if (composite_nomem(s->domain.dns_name, c)) return c;
2091 s->domain.netbios_name = talloc_strdup(s, r->in.domain_netbios_name);
2092 if (composite_nomem(s->domain.netbios_name, c)) return c;
2093 s->domain.sid = dom_sid_dup(s, r->in.domain_sid);
2094 if (composite_nomem(s->domain.sid, c)) return c;
2096 /* Source DSA input */
2097 s->source_dsa.address = talloc_strdup(s, r->in.source_dsa_address);
2098 if (composite_nomem(s->source_dsa.address, c)) return c;
2100 /* Destination DSA input */
2101 s->dest_dsa.netbios_name= talloc_strdup(s, r->in.dest_dsa_netbios_name);
2102 if (composite_nomem(s->dest_dsa.netbios_name, c)) return c;
2104 /* Destination DSA dns_name construction */
2105 tmp_name = strlower_talloc(s, s->dest_dsa.netbios_name);
2106 if (composite_nomem(tmp_name, c)) return c;
2107 s->dest_dsa.dns_name = talloc_asprintf_append(tmp_name, ".%s",
2108 s->domain.dns_name);
2109 if (composite_nomem(s->dest_dsa.dns_name, c)) return c;
2111 /* Callback function pointers */
2112 s->callbacks = r->in.callbacks;
2114 becomeDC_send_cldap(s);
2118 NTSTATUS libnet_BecomeDC_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, struct libnet_BecomeDC *r)
2122 status = composite_wait(c);
2124 ZERO_STRUCT(r->out);
2130 NTSTATUS libnet_BecomeDC(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_BecomeDC *r)
2133 struct composite_context *c;
2134 c = libnet_BecomeDC_send(ctx, mem_ctx, r);
2135 status = libnet_BecomeDC_recv(c, mem_ctx, r);