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"
32 #include "librpc/gen_ndr/ndr_security.h"
34 struct libnet_BecomeDC_state {
35 struct composite_context *creq;
37 struct libnet_context *libnet;
39 struct dom_sid zero_sid;
42 struct cldap_socket *sock;
43 struct cldap_netlogon io;
44 struct nbt_cldap_netlogon_5 netlogon5;
47 struct becomeDC_ldap {
48 struct ldb_context *ldb;
49 const struct ldb_message *rootdse;
52 struct becomeDC_drsuapi {
53 struct libnet_BecomeDC_state *s;
54 struct dcerpc_binding *binding;
55 struct dcerpc_pipe *pipe;
56 struct drsuapi_DsBind bind_r;
57 struct GUID bind_guid;
58 struct drsuapi_DsBindInfoCtr bind_info_ctr;
59 struct drsuapi_DsBindInfo28 local_info28;
60 struct drsuapi_DsBindInfo28 remote_info28;
61 struct policy_handle bind_handle;
62 } drsuapi1, drsuapi2, drsuapi3;
64 struct libnet_BecomeDC_Domain domain;
65 struct libnet_BecomeDC_Forest forest;
66 struct libnet_BecomeDC_SourceDSA source_dsa;
67 struct libnet_BecomeDC_DestDSA dest_dsa;
69 struct libnet_BecomeDC_Partition schema_part, config_part, domain_part;
71 struct becomeDC_fsmo {
73 const char *server_dn_str;
74 const char *ntds_dn_str;
75 struct GUID ntds_guid;
76 } infrastructure_fsmo;
78 struct becomeDC_fsmo rid_manager_fsmo;
80 struct libnet_BecomeDC_CheckOptions _co;
81 struct libnet_BecomeDC_PrepareDB _pp;
82 struct libnet_BecomeDC_StoreChunk _sc;
83 struct libnet_BecomeDC_Callbacks callbacks;
86 static void becomeDC_connect_ldap1(struct libnet_BecomeDC_state *s);
88 static void becomeDC_recv_cldap(struct cldap_request *req)
90 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
91 struct libnet_BecomeDC_state);
92 struct composite_context *c = s->creq;
94 c->status = cldap_netlogon_recv(req, s, &s->cldap.io);
95 if (!composite_is_ok(c)) return;
97 s->cldap.netlogon5 = s->cldap.io.out.netlogon.logon5;
99 s->domain.dns_name = s->cldap.netlogon5.dns_domain;
100 s->domain.netbios_name = s->cldap.netlogon5.domain;
101 s->domain.guid = s->cldap.netlogon5.domain_uuid;
103 s->forest.dns_name = s->cldap.netlogon5.forest;
105 s->source_dsa.dns_name = s->cldap.netlogon5.pdc_dns_name;
106 s->source_dsa.netbios_name = s->cldap.netlogon5.pdc_name;
107 s->source_dsa.site_name = s->cldap.netlogon5.server_site;
109 s->dest_dsa.site_name = s->cldap.netlogon5.client_site;
111 becomeDC_connect_ldap1(s);
114 static void becomeDC_send_cldap(struct libnet_BecomeDC_state *s)
116 struct composite_context *c = s->creq;
117 struct cldap_request *req;
119 s->cldap.io.in.dest_address = s->source_dsa.address;
120 s->cldap.io.in.realm = s->domain.dns_name;
121 s->cldap.io.in.host = s->dest_dsa.netbios_name;
122 s->cldap.io.in.user = NULL;
123 s->cldap.io.in.domain_guid = NULL;
124 s->cldap.io.in.domain_sid = NULL;
125 s->cldap.io.in.acct_control = -1;
126 s->cldap.io.in.version = 6;
128 s->cldap.sock = cldap_socket_init(s, s->libnet->event_ctx);
129 if (composite_nomem(s->cldap.sock, c)) return;
131 req = cldap_netlogon_send(s->cldap.sock, &s->cldap.io);
132 if (composite_nomem(req, c)) return;
133 req->async.fn = becomeDC_recv_cldap;
134 req->async.private = s;
137 static NTSTATUS becomeDC_ldap_connect(struct libnet_BecomeDC_state *s, struct becomeDC_ldap *ldap)
141 url = talloc_asprintf(s, "ldap://%s/", s->source_dsa.dns_name);
142 NT_STATUS_HAVE_NO_MEMORY(url);
144 ldap->ldb = ldb_wrap_connect(s, url,
149 if (ldap->ldb == NULL) {
150 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
156 static NTSTATUS becomeDC_ldap1_rootdse(struct libnet_BecomeDC_state *s)
159 struct ldb_result *r;
160 struct ldb_dn *basedn;
161 static const char *attrs[] = {
166 basedn = ldb_dn_new(s, s->ldap1.ldb, NULL);
167 NT_STATUS_HAVE_NO_MEMORY(basedn);
169 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
170 "(objectClass=*)", attrs, &r);
172 if (ret != LDB_SUCCESS) {
173 return NT_STATUS_LDAP(ret);
174 } else if (r->count != 1) {
176 return NT_STATUS_INVALID_NETWORK_RESPONSE;
180 s->ldap1.rootdse = r->msgs[0];
182 s->domain.dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "defaultNamingContext", NULL);
183 if (!s->domain.dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
185 s->forest.root_dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "rootDomainNamingContext", NULL);
186 if (!s->forest.root_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
187 s->forest.config_dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "configurationNamingContext", NULL);
188 if (!s->forest.config_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
189 s->forest.schema_dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "schemaNamingContext", NULL);
190 if (!s->forest.schema_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
192 s->source_dsa.server_dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "serverName", NULL);
193 if (!s->source_dsa.server_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
194 s->source_dsa.ntds_dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "dsServiceName", NULL);
195 if (!s->source_dsa.ntds_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
200 static NTSTATUS becomeDC_ldap1_crossref_behavior_version(struct libnet_BecomeDC_state *s)
203 struct ldb_result *r;
204 struct ldb_dn *basedn;
205 static const char *attrs[] = {
206 "msDs-Behavior-Version",
210 basedn = ldb_dn_new(s, s->ldap1.ldb, s->forest.config_dn_str);
211 NT_STATUS_HAVE_NO_MEMORY(basedn);
213 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_ONELEVEL,
214 "(cn=Partitions)", attrs, &r);
216 if (ret != LDB_SUCCESS) {
217 return NT_STATUS_LDAP(ret);
218 } else if (r->count != 1) {
220 return NT_STATUS_INVALID_NETWORK_RESPONSE;
223 s->forest.crossref_behavior_version = ldb_msg_find_attr_as_uint(r->msgs[0], "msDs-Behavior-Version", 0);
229 static NTSTATUS becomeDC_ldap1_domain_behavior_version(struct libnet_BecomeDC_state *s)
232 struct ldb_result *r;
233 struct ldb_dn *basedn;
234 static const char *attrs[] = {
235 "msDs-Behavior-Version",
239 basedn = ldb_dn_new(s, s->ldap1.ldb, s->domain.dn_str);
240 NT_STATUS_HAVE_NO_MEMORY(basedn);
242 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
243 "(objectClass=*)", attrs, &r);
245 if (ret != LDB_SUCCESS) {
246 return NT_STATUS_LDAP(ret);
247 } else if (r->count != 1) {
249 return NT_STATUS_INVALID_NETWORK_RESPONSE;
252 s->domain.behavior_version = ldb_msg_find_attr_as_uint(r->msgs[0], "msDs-Behavior-Version", 0);
258 static NTSTATUS becomeDC_ldap1_schema_object_version(struct libnet_BecomeDC_state *s)
261 struct ldb_result *r;
262 struct ldb_dn *basedn;
263 static const char *attrs[] = {
268 basedn = ldb_dn_new(s, s->ldap1.ldb, s->forest.schema_dn_str);
269 NT_STATUS_HAVE_NO_MEMORY(basedn);
271 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
272 "(objectClass=*)", attrs, &r);
274 if (ret != LDB_SUCCESS) {
275 return NT_STATUS_LDAP(ret);
276 } else if (r->count != 1) {
278 return NT_STATUS_INVALID_NETWORK_RESPONSE;
281 s->forest.schema_object_version = ldb_msg_find_attr_as_uint(r->msgs[0], "objectVersion", 0);
287 static NTSTATUS becomeDC_ldap1_w2k3_update_revision(struct libnet_BecomeDC_state *s)
290 struct ldb_result *r;
291 struct ldb_dn *basedn;
292 static const char *attrs[] = {
297 basedn = ldb_dn_new_fmt(s, s->ldap1.ldb, "CN=Windows2003Update,CN=DomainUpdates,CN=System,%s",
299 NT_STATUS_HAVE_NO_MEMORY(basedn);
301 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
302 "(objectClass=*)", attrs, &r);
304 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
305 /* w2k doesn't have this object */
306 s->domain.w2k3_update_revision = 0;
308 } else if (ret != LDB_SUCCESS) {
309 return NT_STATUS_LDAP(ret);
310 } else if (r->count != 1) {
312 return NT_STATUS_INVALID_NETWORK_RESPONSE;
315 s->domain.w2k3_update_revision = ldb_msg_find_attr_as_uint(r->msgs[0], "revision", 0);
321 static NTSTATUS becomeDC_ldap1_infrastructure_fsmo(struct libnet_BecomeDC_state *s)
324 struct ldb_result *r;
325 struct ldb_dn *basedn;
326 struct ldb_dn *ntds_dn;
327 struct ldb_dn *server_dn;
328 static const char *_1_1_attrs[] = {
332 static const char *fsmo_attrs[] = {
336 static const char *dns_attrs[] = {
340 static const char *guid_attrs[] = {
345 basedn = ldb_dn_new_fmt(s, s->ldap1.ldb, "<WKGUID=2fbac1870ade11d297c400c04fd8d5cd,%s>",
347 NT_STATUS_HAVE_NO_MEMORY(basedn);
349 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
350 "(objectClass=*)", _1_1_attrs, &r);
352 if (ret != LDB_SUCCESS) {
353 return NT_STATUS_LDAP(ret);
354 } else if (r->count != 1) {
356 return NT_STATUS_INVALID_NETWORK_RESPONSE;
359 basedn = talloc_steal(s, r->msgs[0]->dn);
362 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
363 "(objectClass=*)", fsmo_attrs, &r);
365 if (ret != LDB_SUCCESS) {
366 return NT_STATUS_LDAP(ret);
367 } else if (r->count != 1) {
369 return NT_STATUS_INVALID_NETWORK_RESPONSE;
372 s->infrastructure_fsmo.ntds_dn_str = samdb_result_string(r->msgs[0], "fSMORoleOwner", NULL);
373 if (!s->infrastructure_fsmo.ntds_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
374 talloc_steal(s, s->infrastructure_fsmo.ntds_dn_str);
378 ntds_dn = ldb_dn_new(s, s->ldap1.ldb, s->infrastructure_fsmo.ntds_dn_str);
379 NT_STATUS_HAVE_NO_MEMORY(ntds_dn);
381 server_dn = ldb_dn_get_parent(s, ntds_dn);
382 NT_STATUS_HAVE_NO_MEMORY(server_dn);
384 s->infrastructure_fsmo.server_dn_str = ldb_dn_alloc_linearized(s, server_dn);
385 NT_STATUS_HAVE_NO_MEMORY(s->infrastructure_fsmo.server_dn_str);
387 ret = ldb_search(s->ldap1.ldb, server_dn, LDB_SCOPE_BASE,
388 "(objectClass=*)", dns_attrs, &r);
389 if (ret != LDB_SUCCESS) {
390 return NT_STATUS_LDAP(ret);
391 } else if (r->count != 1) {
393 return NT_STATUS_INVALID_NETWORK_RESPONSE;
396 s->infrastructure_fsmo.dns_name = samdb_result_string(r->msgs[0], "dnsHostName", NULL);
397 if (!s->infrastructure_fsmo.dns_name) return NT_STATUS_INVALID_NETWORK_RESPONSE;
398 talloc_steal(s, s->infrastructure_fsmo.dns_name);
402 ret = ldb_search(s->ldap1.ldb, ntds_dn, LDB_SCOPE_BASE,
403 "(objectClass=*)", guid_attrs, &r);
404 if (ret != LDB_SUCCESS) {
405 return NT_STATUS_LDAP(ret);
406 } else if (r->count != 1) {
408 return NT_STATUS_INVALID_NETWORK_RESPONSE;
411 s->infrastructure_fsmo.ntds_guid = samdb_result_guid(r->msgs[0], "objectGUID");
418 static NTSTATUS becomeDC_ldap1_rid_manager_fsmo(struct libnet_BecomeDC_state *s)
421 struct ldb_result *r;
422 struct ldb_dn *basedn;
423 const char *reference_dn_str;
424 struct ldb_dn *ntds_dn;
425 struct ldb_dn *server_dn;
426 static const char *rid_attrs[] = {
427 "rIDManagerReference",
430 static const char *fsmo_attrs[] = {
434 static const char *dns_attrs[] = {
438 static const char *guid_attrs[] = {
443 basedn = ldb_dn_new(s, s->ldap1.ldb, s->domain.dn_str);
444 NT_STATUS_HAVE_NO_MEMORY(basedn);
446 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
447 "(objectClass=*)", rid_attrs, &r);
449 if (ret != LDB_SUCCESS) {
450 return NT_STATUS_LDAP(ret);
451 } else if (r->count != 1) {
453 return NT_STATUS_INVALID_NETWORK_RESPONSE;
456 reference_dn_str = samdb_result_string(r->msgs[0], "rIDManagerReference", NULL);
457 if (!reference_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
459 basedn = ldb_dn_new(s, s->ldap1.ldb, reference_dn_str);
460 NT_STATUS_HAVE_NO_MEMORY(basedn);
464 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
465 "(objectClass=*)", fsmo_attrs, &r);
467 if (ret != LDB_SUCCESS) {
468 return NT_STATUS_LDAP(ret);
469 } else if (r->count != 1) {
471 return NT_STATUS_INVALID_NETWORK_RESPONSE;
474 s->rid_manager_fsmo.ntds_dn_str = samdb_result_string(r->msgs[0], "fSMORoleOwner", NULL);
475 if (!s->rid_manager_fsmo.ntds_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
476 talloc_steal(s, s->rid_manager_fsmo.ntds_dn_str);
480 ntds_dn = ldb_dn_new(s, s->ldap1.ldb, s->rid_manager_fsmo.ntds_dn_str);
481 NT_STATUS_HAVE_NO_MEMORY(ntds_dn);
483 server_dn = ldb_dn_get_parent(s, ntds_dn);
484 NT_STATUS_HAVE_NO_MEMORY(server_dn);
486 s->rid_manager_fsmo.server_dn_str = ldb_dn_alloc_linearized(s, server_dn);
487 NT_STATUS_HAVE_NO_MEMORY(s->rid_manager_fsmo.server_dn_str);
489 ret = ldb_search(s->ldap1.ldb, server_dn, LDB_SCOPE_BASE,
490 "(objectClass=*)", dns_attrs, &r);
491 if (ret != LDB_SUCCESS) {
492 return NT_STATUS_LDAP(ret);
493 } else if (r->count != 1) {
495 return NT_STATUS_INVALID_NETWORK_RESPONSE;
498 s->rid_manager_fsmo.dns_name = samdb_result_string(r->msgs[0], "dnsHostName", NULL);
499 if (!s->rid_manager_fsmo.dns_name) return NT_STATUS_INVALID_NETWORK_RESPONSE;
500 talloc_steal(s, s->rid_manager_fsmo.dns_name);
504 ret = ldb_search(s->ldap1.ldb, ntds_dn, LDB_SCOPE_BASE,
505 "(objectClass=*)", guid_attrs, &r);
506 if (ret != LDB_SUCCESS) {
507 return NT_STATUS_LDAP(ret);
508 } else if (r->count != 1) {
510 return NT_STATUS_INVALID_NETWORK_RESPONSE;
513 s->rid_manager_fsmo.ntds_guid = samdb_result_guid(r->msgs[0], "objectGUID");
520 static NTSTATUS becomeDC_ldap1_site_object(struct libnet_BecomeDC_state *s)
523 struct ldb_result *r;
524 struct ldb_dn *basedn;
526 basedn = ldb_dn_new_fmt(s, s->ldap1.ldb, "CN=%s,CN=Sites,%s",
527 s->dest_dsa.site_name,
528 s->forest.config_dn_str);
529 NT_STATUS_HAVE_NO_MEMORY(basedn);
531 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
532 "(objectClass=*)", NULL, &r);
534 if (ret != LDB_SUCCESS) {
535 return NT_STATUS_LDAP(ret);
536 } else if (r->count != 1) {
538 return NT_STATUS_INVALID_NETWORK_RESPONSE;
541 s->dest_dsa.site_guid = samdb_result_guid(r->msgs[0], "objectGUID");
547 static NTSTATUS becomeDC_check_options(struct libnet_BecomeDC_state *s)
549 if (!s->callbacks.check_options) return NT_STATUS_OK;
551 s->_co.domain = &s->domain;
552 s->_co.forest = &s->forest;
553 s->_co.source_dsa = &s->source_dsa;
555 return s->callbacks.check_options(s->callbacks.private_data, &s->_co);
558 static NTSTATUS becomeDC_ldap1_computer_object(struct libnet_BecomeDC_state *s)
561 struct ldb_result *r;
562 struct ldb_dn *basedn;
564 static const char *attrs[] = {
566 "userAccountControl",
570 basedn = ldb_dn_new(s, s->ldap1.ldb, s->domain.dn_str);
571 NT_STATUS_HAVE_NO_MEMORY(basedn);
573 filter = talloc_asprintf(basedn, "(&(|(objectClass=user)(objectClass=computer))(sAMAccountName=%s$))",
574 s->dest_dsa.netbios_name);
575 NT_STATUS_HAVE_NO_MEMORY(filter);
577 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_SUBTREE,
580 if (ret != LDB_SUCCESS) {
581 return NT_STATUS_LDAP(ret);
582 } else if (r->count != 1) {
584 return NT_STATUS_INVALID_NETWORK_RESPONSE;
587 s->dest_dsa.computer_dn_str = samdb_result_string(r->msgs[0], "distinguishedName", NULL);
588 if (!s->dest_dsa.computer_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
589 talloc_steal(s, s->dest_dsa.computer_dn_str);
591 s->dest_dsa.user_account_control = samdb_result_uint(r->msgs[0], "userAccountControl", 0);
597 static NTSTATUS becomeDC_ldap1_server_object_1(struct libnet_BecomeDC_state *s)
600 struct ldb_result *r;
601 struct ldb_dn *basedn;
602 const char *server_reference_dn_str;
603 struct ldb_dn *server_reference_dn;
604 struct ldb_dn *computer_dn;
606 basedn = ldb_dn_new_fmt(s, s->ldap1.ldb, "CN=%s,CN=Servers,CN=%s,CN=Sites,%s",
607 s->dest_dsa.netbios_name,
608 s->dest_dsa.site_name,
609 s->forest.config_dn_str);
610 NT_STATUS_HAVE_NO_MEMORY(basedn);
612 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
613 "(objectClass=*)", NULL, &r);
615 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
616 /* if the object doesn't exist, we'll create it later */
618 } else if (ret != LDB_SUCCESS) {
619 return NT_STATUS_LDAP(ret);
620 } else if (r->count != 1) {
622 return NT_STATUS_INVALID_NETWORK_RESPONSE;
625 server_reference_dn_str = samdb_result_string(r->msgs[0], "serverReference", NULL);
626 if (server_reference_dn_str) {
627 server_reference_dn = ldb_dn_new(r, s->ldap1.ldb, server_reference_dn_str);
628 NT_STATUS_HAVE_NO_MEMORY(server_reference_dn);
630 computer_dn = ldb_dn_new(r, s->ldap1.ldb, s->dest_dsa.computer_dn_str);
631 NT_STATUS_HAVE_NO_MEMORY(computer_dn);
634 * if the server object belongs to another DC in another domain in the forest,
635 * we should not touch this object!
637 if (ldb_dn_compare(computer_dn, server_reference_dn) != 0) {
639 return NT_STATUS_OBJECT_NAME_COLLISION;
643 /* if the server object is already for the dest_dsa, then we don't need to create it */
644 s->dest_dsa.server_dn_str = samdb_result_string(r->msgs[0], "distinguishedName", NULL);
645 if (!s->dest_dsa.server_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
646 talloc_steal(s, s->dest_dsa.server_dn_str);
652 static NTSTATUS becomeDC_ldap1_server_object_2(struct libnet_BecomeDC_state *s)
655 struct ldb_result *r;
656 struct ldb_dn *basedn;
657 const char *server_reference_bl_dn_str;
658 static const char *attrs[] = {
663 /* if the server_dn_str has a valid value, we skip this lookup */
664 if (s->dest_dsa.server_dn_str) return NT_STATUS_OK;
666 basedn = ldb_dn_new(s, s->ldap1.ldb, s->dest_dsa.computer_dn_str);
667 NT_STATUS_HAVE_NO_MEMORY(basedn);
669 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
670 "(objectClass=*)", attrs, &r);
672 if (ret != LDB_SUCCESS) {
673 return NT_STATUS_LDAP(ret);
674 } else if (r->count != 1) {
676 return NT_STATUS_INVALID_NETWORK_RESPONSE;
679 server_reference_bl_dn_str = samdb_result_string(r->msgs[0], "serverReferenceBL", NULL);
680 if (!server_reference_bl_dn_str) {
681 /* if no back link is present, we're done for this function */
686 /* if the server object is already for the dest_dsa, then we don't need to create it */
687 s->dest_dsa.server_dn_str = samdb_result_string(r->msgs[0], "serverReferenceBL", NULL);
688 if (s->dest_dsa.server_dn_str) {
689 /* if a back link is present, we know that the server object is present */
690 talloc_steal(s, s->dest_dsa.server_dn_str);
697 static NTSTATUS becomeDC_ldap1_server_object_add(struct libnet_BecomeDC_state *s)
700 struct ldb_message *msg;
703 /* if the server_dn_str has a valid value, we skip this lookup */
704 if (s->dest_dsa.server_dn_str) return NT_STATUS_OK;
706 msg = ldb_msg_new(s);
707 NT_STATUS_HAVE_NO_MEMORY(msg);
709 msg->dn = ldb_dn_new_fmt(msg, s->ldap1.ldb, "CN=%s,CN=Servers,CN=%s,CN=Sites,%s",
710 s->dest_dsa.netbios_name,
711 s->dest_dsa.site_name,
712 s->forest.config_dn_str);
713 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
715 ret = ldb_msg_add_string(msg, "objectClass", "server");
718 return NT_STATUS_NO_MEMORY;
720 ret = ldb_msg_add_string(msg, "systemFlags", "50000000");
723 return NT_STATUS_NO_MEMORY;
725 ret = ldb_msg_add_string(msg, "serverReference", s->dest_dsa.computer_dn_str);
728 return NT_STATUS_NO_MEMORY;
731 server_dn_str = ldb_dn_alloc_linearized(s, msg->dn);
732 NT_STATUS_HAVE_NO_MEMORY(server_dn_str);
734 ret = ldb_add(s->ldap1.ldb, msg);
736 if (ret != LDB_SUCCESS) {
737 talloc_free(server_dn_str);
738 return NT_STATUS_LDAP(ret);
741 s->dest_dsa.server_dn_str = server_dn_str;
746 static NTSTATUS becomeDC_ldap1_server_object_modify(struct libnet_BecomeDC_state *s)
749 struct ldb_message *msg;
752 /* make a 'modify' msg, and only for serverReference */
753 msg = ldb_msg_new(s);
754 NT_STATUS_HAVE_NO_MEMORY(msg);
755 msg->dn = ldb_dn_new(msg, s->ldap1.ldb, s->dest_dsa.server_dn_str);
756 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
758 ret = ldb_msg_add_string(msg, "serverReference", s->dest_dsa.computer_dn_str);
761 return NT_STATUS_NO_MEMORY;
764 /* mark all the message elements (should be just one)
765 as LDB_FLAG_MOD_ADD */
766 for (i=0;i<msg->num_elements;i++) {
767 msg->elements[i].flags = LDB_FLAG_MOD_ADD;
770 ret = ldb_modify(s->ldap1.ldb, msg);
771 if (ret == LDB_SUCCESS) {
774 } else if (ret == LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) {
775 /* retry with LDB_FLAG_MOD_REPLACE */
778 return NT_STATUS_LDAP(ret);
781 /* mark all the message elements (should be just one)
782 as LDB_FLAG_MOD_REPLACE */
783 for (i=0;i<msg->num_elements;i++) {
784 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
787 ret = ldb_modify(s->ldap1.ldb, msg);
789 if (ret != LDB_SUCCESS) {
790 return NT_STATUS_LDAP(ret);
796 static void becomeDC_drsuapi_connect_send(struct libnet_BecomeDC_state *s,
797 struct becomeDC_drsuapi *drsuapi,
798 void (*recv_fn)(struct composite_context *req));
799 static void becomeDC_drsuapi1_connect_recv(struct composite_context *req);
800 static void becomeDC_connect_ldap2(struct libnet_BecomeDC_state *s);
802 static void becomeDC_connect_ldap1(struct libnet_BecomeDC_state *s)
804 struct composite_context *c = s->creq;
806 c->status = becomeDC_ldap_connect(s, &s->ldap1);
807 if (!composite_is_ok(c)) return;
809 c->status = becomeDC_ldap1_rootdse(s);
810 if (!composite_is_ok(c)) return;
812 c->status = becomeDC_ldap1_crossref_behavior_version(s);
813 if (!composite_is_ok(c)) return;
815 c->status = becomeDC_ldap1_domain_behavior_version(s);
816 if (!composite_is_ok(c)) return;
818 c->status = becomeDC_ldap1_schema_object_version(s);
819 if (!composite_is_ok(c)) return;
821 c->status = becomeDC_ldap1_w2k3_update_revision(s);
822 if (!composite_is_ok(c)) return;
824 c->status = becomeDC_ldap1_infrastructure_fsmo(s);
825 if (!composite_is_ok(c)) return;
827 c->status = becomeDC_ldap1_rid_manager_fsmo(s);
828 if (!composite_is_ok(c)) return;
830 c->status = becomeDC_ldap1_site_object(s);
831 if (!composite_is_ok(c)) return;
833 c->status = becomeDC_check_options(s);
834 if (!composite_is_ok(c)) return;
836 c->status = becomeDC_ldap1_computer_object(s);
837 if (!composite_is_ok(c)) return;
839 c->status = becomeDC_ldap1_server_object_1(s);
840 if (!composite_is_ok(c)) return;
842 c->status = becomeDC_ldap1_server_object_2(s);
843 if (!composite_is_ok(c)) return;
845 c->status = becomeDC_ldap1_server_object_add(s);
846 if (!composite_is_ok(c)) return;
848 c->status = becomeDC_ldap1_server_object_modify(s);
849 if (!composite_is_ok(c)) return;
851 becomeDC_drsuapi_connect_send(s, &s->drsuapi1, becomeDC_drsuapi1_connect_recv);
854 static void becomeDC_drsuapi_connect_send(struct libnet_BecomeDC_state *s,
855 struct becomeDC_drsuapi *drsuapi,
856 void (*recv_fn)(struct composite_context *req))
858 struct composite_context *c = s->creq;
859 struct composite_context *creq;
864 if (!drsuapi->binding) {
865 binding_str = talloc_asprintf(s, "ncacn_ip_tcp:%s[krb5,seal]", s->source_dsa.dns_name);
866 if (composite_nomem(binding_str, c)) return;
868 c->status = dcerpc_parse_binding(s, binding_str, &drsuapi->binding);
869 talloc_free(binding_str);
870 if (!composite_is_ok(c)) return;
873 creq = dcerpc_pipe_connect_b_send(s, drsuapi->binding, &dcerpc_table_drsuapi,
874 s->libnet->cred, s->libnet->event_ctx);
875 composite_continue(c, creq, recv_fn, s);
878 static void becomeDC_drsuapi_bind_send(struct libnet_BecomeDC_state *s,
879 struct becomeDC_drsuapi *drsuapi,
880 void (*recv_fn)(struct rpc_request *req));
881 static void becomeDC_drsuapi1_bind_recv(struct rpc_request *req);
883 static void becomeDC_drsuapi1_connect_recv(struct composite_context *req)
885 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
886 struct libnet_BecomeDC_state);
887 struct composite_context *c = s->creq;
889 c->status = dcerpc_pipe_connect_b_recv(req, s, &s->drsuapi1.pipe);
890 if (!composite_is_ok(c)) return;
892 becomeDC_drsuapi_bind_send(s, &s->drsuapi1, becomeDC_drsuapi1_bind_recv);
895 static void becomeDC_drsuapi_bind_send(struct libnet_BecomeDC_state *s,
896 struct becomeDC_drsuapi *drsuapi,
897 void (*recv_fn)(struct rpc_request *req))
899 struct composite_context *c = s->creq;
900 struct rpc_request *req;
901 struct drsuapi_DsBindInfo28 *bind_info28;
903 GUID_from_string(DRSUAPI_DS_BIND_GUID_W2K3, &drsuapi->bind_guid);
905 bind_info28 = &drsuapi->local_info28;
906 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_BASE;
907 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION;
908 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI;
909 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2;
910 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS;
911 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1;
912 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION;
913 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE;
914 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2;
915 if (s->domain.behavior_version == 2) {
916 /* TODO: find out how this is really triggered! */
917 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION;
919 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2;
920 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD;
921 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND;
922 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO;
923 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION;
924 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01;
925 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP;
926 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY;
927 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3;
928 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_00100000;
929 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2;
930 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6;
931 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS;
932 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8;
933 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5;
934 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6;
935 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3;
936 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7;
937 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT;
938 #if 0 /* we don't support XPRESS compression yet */
939 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS;
941 bind_info28->site_guid = s->dest_dsa.site_guid;
942 if (s->domain.behavior_version == 2) {
943 /* TODO: find out how this is really triggered! */
944 bind_info28->u1 = 528;
946 bind_info28->u1 = 516;
948 bind_info28->repl_epoch = 0;
950 drsuapi->bind_info_ctr.length = 28;
951 drsuapi->bind_info_ctr.info.info28 = *bind_info28;
953 drsuapi->bind_r.in.bind_guid = &drsuapi->bind_guid;
954 drsuapi->bind_r.in.bind_info = &drsuapi->bind_info_ctr;
955 drsuapi->bind_r.out.bind_handle = &drsuapi->bind_handle;
957 req = dcerpc_drsuapi_DsBind_send(drsuapi->pipe, s, &drsuapi->bind_r);
958 composite_continue_rpc(c, req, recv_fn, s);
961 static WERROR becomeDC_drsuapi_bind_recv(struct libnet_BecomeDC_state *s,
962 struct becomeDC_drsuapi *drsuapi)
964 if (!W_ERROR_IS_OK(drsuapi->bind_r.out.result)) {
965 return drsuapi->bind_r.out.result;
968 ZERO_STRUCT(drsuapi->remote_info28);
969 if (drsuapi->bind_r.out.bind_info) {
970 switch (drsuapi->bind_r.out.bind_info->length) {
972 struct drsuapi_DsBindInfo24 *info24;
973 info24 = &drsuapi->bind_r.out.bind_info->info.info24;
974 drsuapi->remote_info28.supported_extensions = info24->supported_extensions;
975 drsuapi->remote_info28.site_guid = info24->site_guid;
976 drsuapi->remote_info28.u1 = info24->u1;
977 drsuapi->remote_info28.repl_epoch = 0;
981 drsuapi->remote_info28 = drsuapi->bind_r.out.bind_info->info.info28;
989 static void becomeDC_drsuapi1_add_entry_send(struct libnet_BecomeDC_state *s);
991 static void becomeDC_drsuapi1_bind_recv(struct rpc_request *req)
993 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
994 struct libnet_BecomeDC_state);
995 struct composite_context *c = s->creq;
998 c->status = dcerpc_ndr_request_recv(req);
999 if (!composite_is_ok(c)) return;
1001 status = becomeDC_drsuapi_bind_recv(s, &s->drsuapi1);
1002 if (!W_ERROR_IS_OK(status)) {
1003 composite_error(c, werror_to_ntstatus(status));
1007 becomeDC_drsuapi1_add_entry_send(s);
1010 static void becomeDC_drsuapi1_add_entry_recv(struct rpc_request *req);
1012 static void becomeDC_drsuapi1_add_entry_send(struct libnet_BecomeDC_state *s)
1014 struct composite_context *c = s->creq;
1015 struct rpc_request *req;
1016 struct drsuapi_DsAddEntry *r;
1017 struct drsuapi_DsReplicaObjectIdentifier *identifier;
1018 uint32_t num_attrs, i = 0;
1019 struct drsuapi_DsReplicaAttribute *attrs;
1022 /* choose a random invocationId */
1023 s->dest_dsa.invocation_id = GUID_random();
1026 * if the schema version indicates w2k3, then
1027 * also send some w2k3 specific attributes
1029 if (s->forest.schema_object_version >= 30) {
1035 r = talloc_zero(s, struct drsuapi_DsAddEntry);
1036 if (composite_nomem(r, c)) return;
1038 /* setup identifier */
1039 identifier = talloc(r, struct drsuapi_DsReplicaObjectIdentifier);
1040 if (composite_nomem(identifier, c)) return;
1041 identifier->guid = GUID_zero();
1042 identifier->sid = s->zero_sid;
1043 identifier->dn = talloc_asprintf(identifier, "CN=NTDS Settings,%s",
1044 s->dest_dsa.server_dn_str);
1045 if (composite_nomem(identifier->dn, c)) return;
1047 /* allocate attribute array */
1049 attrs = talloc_array(r, struct drsuapi_DsReplicaAttribute, num_attrs);
1050 if (composite_nomem(attrs, c)) return;
1052 /* ntSecurityDescriptor */
1054 struct drsuapi_DsAttributeValueDataBlob *vs;
1056 struct security_descriptor *v;
1057 struct dom_sid *domain_admins_sid;
1058 const char *domain_admins_sid_str;
1060 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDataBlob, 1);
1061 if (composite_nomem(vs, c)) return;
1063 vd = talloc_array(vs, DATA_BLOB, 1);
1064 if (composite_nomem(vd, c)) return;
1066 domain_admins_sid = dom_sid_add_rid(vs, s->domain.sid, DOMAIN_RID_ADMINS);
1067 if (composite_nomem(domain_admins_sid, c)) return;
1069 domain_admins_sid_str = dom_sid_string(domain_admins_sid, domain_admins_sid);
1070 if (composite_nomem(domain_admins_sid_str, c)) return;
1072 v = security_descriptor_create(vd,
1073 /* owner: domain admins */
1074 domain_admins_sid_str,
1075 /* owner group: domain admins */
1076 domain_admins_sid_str,
1077 /* authenticated users */
1078 SID_NT_AUTHENTICATED_USERS,
1079 SEC_ACE_TYPE_ACCESS_ALLOWED,
1080 SEC_STD_READ_CONTROL |
1083 SEC_ADS_LIST_OBJECT,
1086 domain_admins_sid_str,
1087 SEC_ACE_TYPE_ACCESS_ALLOWED,
1089 SEC_ADS_CREATE_CHILD |
1091 SEC_ADS_SELF_WRITE |
1093 SEC_ADS_WRITE_PROP |
1094 SEC_ADS_DELETE_TREE |
1095 SEC_ADS_LIST_OBJECT |
1096 SEC_ADS_CONTROL_ACCESS,
1100 SEC_ACE_TYPE_ACCESS_ALLOWED,
1102 SEC_ADS_CREATE_CHILD |
1103 SEC_ADS_DELETE_CHILD |
1105 SEC_ADS_SELF_WRITE |
1107 SEC_ADS_WRITE_PROP |
1108 SEC_ADS_DELETE_TREE |
1109 SEC_ADS_LIST_OBJECT |
1110 SEC_ADS_CONTROL_ACCESS,
1114 if (composite_nomem(v, c)) return;
1116 c->status = ndr_push_struct_blob(&vd[0], r, v,(ndr_push_flags_fn_t)ndr_push_security_descriptor);
1117 if (!composite_is_ok(c)) return;
1119 vs[0].data = &vd[0];
1121 attrs[i].attid = DRSUAPI_ATTRIBUTE_ntSecurityDescriptor;
1122 attrs[i].value_ctr.data_blob.num_values = 1;
1123 attrs[i].value_ctr.data_blob.values = vs;
1128 /* objectClass: nTDSDSA */
1130 struct drsuapi_DsAttributeValueObjectClassId *vs;
1131 enum drsuapi_DsObjectClassId *v;
1133 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueObjectClassId, 1);
1134 if (composite_nomem(vs, c)) return;
1136 v = talloc_array(vs, enum drsuapi_DsObjectClassId, 1);
1137 if (composite_nomem(v, c)) return;
1139 /* value for nTDSDSA */
1142 vs[0].objectClassId = &v[0];
1144 attrs[i].attid = DRSUAPI_ATTRIBUTE_objectClass;
1145 attrs[i].value_ctr.object_class_id.num_values = 1;
1146 attrs[i].value_ctr.object_class_id.values = vs;
1151 /* objectCategory: CN=NTDS-DSA,CN=Schema,... */
1153 struct drsuapi_DsAttributeValueDNString *vs;
1154 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1156 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 1);
1157 if (composite_nomem(vs, c)) return;
1159 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 1);
1160 if (composite_nomem(v, c)) return;
1162 v[0].guid = GUID_zero();
1163 v[0].sid = s->zero_sid;
1164 v[0].dn = talloc_asprintf(v, "CN=NTDS-DSA,%s",
1165 s->forest.schema_dn_str);
1166 if (composite_nomem(v->dn, c)) return;
1168 vs[0].object = &v[0];
1170 attrs[i].attid = DRSUAPI_ATTRIBUTE_objectCategory;
1171 attrs[i].value_ctr.dn_string.num_values = 1;
1172 attrs[i].value_ctr.dn_string.values = vs;
1177 /* invocationId: random guid */
1179 struct drsuapi_DsAttributeValueGUID *vs;
1182 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueGUID, 1);
1183 if (composite_nomem(vs, c)) return;
1185 v = talloc_array(vs, struct GUID, 1);
1186 if (composite_nomem(v, c)) return;
1188 v[0] = s->dest_dsa.invocation_id;
1192 attrs[i].attid = DRSUAPI_ATTRIBUTE_invocationId;
1193 attrs[i].value_ctr.guid.num_values = 1;
1194 attrs[i].value_ctr.guid.values = vs;
1199 /* hasMasterNCs: ... */
1201 struct drsuapi_DsAttributeValueDNString *vs;
1202 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1204 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 3);
1205 if (composite_nomem(vs, c)) return;
1207 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 3);
1208 if (composite_nomem(v, c)) return;
1210 v[0].guid = GUID_zero();
1211 v[0].sid = s->zero_sid;
1212 v[0].dn = s->forest.config_dn_str;
1214 v[1].guid = GUID_zero();
1215 v[1].sid = s->zero_sid;
1216 v[1].dn = s->domain.dn_str;
1218 v[2].guid = GUID_zero();
1219 v[2].sid = s->zero_sid;
1220 v[2].dn = s->forest.schema_dn_str;
1222 vs[0].object = &v[0];
1223 vs[1].object = &v[1];
1224 vs[2].object = &v[2];
1226 attrs[i].attid = DRSUAPI_ATTRIBUTE_hasMasterNCs;
1227 attrs[i].value_ctr.dn_string.num_values = 3;
1228 attrs[i].value_ctr.dn_string.values = vs;
1233 /* msDS-hasMasterNCs: ... */
1235 struct drsuapi_DsAttributeValueDNString *vs;
1236 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1238 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 3);
1239 if (composite_nomem(vs, c)) return;
1241 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 3);
1242 if (composite_nomem(v, c)) return;
1244 v[0].guid = GUID_zero();
1245 v[0].sid = s->zero_sid;
1246 v[0].dn = s->forest.config_dn_str;
1248 v[1].guid = GUID_zero();
1249 v[1].sid = s->zero_sid;
1250 v[1].dn = s->domain.dn_str;
1252 v[2].guid = GUID_zero();
1253 v[2].sid = s->zero_sid;
1254 v[2].dn = s->forest.schema_dn_str;
1256 vs[0].object = &v[0];
1257 vs[1].object = &v[1];
1258 vs[2].object = &v[2];
1260 attrs[i].attid = DRSUAPI_ATTRIBUTE_msDS_hasMasterNCs;
1261 attrs[i].value_ctr.dn_string.num_values = 3;
1262 attrs[i].value_ctr.dn_string.values = vs;
1267 /* dMDLocation: CN=Schema,... */
1269 struct drsuapi_DsAttributeValueDNString *vs;
1270 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1272 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 1);
1273 if (composite_nomem(vs, c)) return;
1275 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 1);
1276 if (composite_nomem(v, c)) return;
1278 v[0].guid = GUID_zero();
1279 v[0].sid = s->zero_sid;
1280 v[0].dn = s->forest.schema_dn_str;
1282 vs[0].object = &v[0];
1284 attrs[i].attid = DRSUAPI_ATTRIBUTE_dMDLocation;
1285 attrs[i].value_ctr.dn_string.num_values = 1;
1286 attrs[i].value_ctr.dn_string.values = vs;
1291 /* msDS-HasDomainNCs: <domain_partition> */
1293 struct drsuapi_DsAttributeValueDNString *vs;
1294 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1296 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 1);
1297 if (composite_nomem(vs, c)) return;
1299 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 1);
1300 if (composite_nomem(v, c)) return;
1302 v[0].guid = GUID_zero();
1303 v[0].sid = s->zero_sid;
1304 v[0].dn = s->domain.dn_str;
1306 vs[0].object = &v[0];
1308 attrs[i].attid = DRSUAPI_ATTRIBUTE_msDS_HasDomainNCs;
1309 attrs[i].value_ctr.dn_string.num_values = 1;
1310 attrs[i].value_ctr.dn_string.values = vs;
1315 /* msDS-Behavior-Version */
1317 struct drsuapi_DsAttributeValueUINT32 *vs;
1320 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueUINT32, 1);
1321 if (composite_nomem(vs, c)) return;
1323 v = talloc_array(vs, uint32_t, 1);
1324 if (composite_nomem(v, c)) return;
1326 v[0] = DS_BEHAVIOR_WIN2003;
1328 vs[0].value = &v[0];
1330 attrs[i].attid = DRSUAPI_ATTRIBUTE_msDS_Behavior_Version;
1331 attrs[i].value_ctr.uint32.num_values = 1;
1332 attrs[i].value_ctr.uint32.values = vs;
1339 struct drsuapi_DsAttributeValueUINT32 *vs;
1342 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueUINT32, 1);
1343 if (composite_nomem(vs, c)) return;
1345 v = talloc_array(vs, uint32_t, 1);
1346 if (composite_nomem(v, c)) return;
1348 v[0] = SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE;
1350 vs[0].value = &v[0];
1352 attrs[i].attid = DRSUAPI_ATTRIBUTE_systemFlags;
1353 attrs[i].value_ctr.uint32.num_values = 1;
1354 attrs[i].value_ctr.uint32.values = vs;
1359 /* serverReference: ... */
1361 struct drsuapi_DsAttributeValueDNString *vs;
1362 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1364 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 1);
1365 if (composite_nomem(vs, c)) return;
1367 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 1);
1368 if (composite_nomem(v, c)) return;
1370 v[0].guid = GUID_zero();
1371 v[0].sid = s->zero_sid;
1372 v[0].dn = s->dest_dsa.computer_dn_str;
1374 vs[0].object = &v[0];
1376 attrs[i].attid = DRSUAPI_ATTRIBUTE_serverReference;
1377 attrs[i].value_ctr.dn_string.num_values = 1;
1378 attrs[i].value_ctr.dn_string.values = vs;
1383 /* truncate the attribute list to the attribute count we have filled in */
1386 /* setup request structure */
1387 r->in.bind_handle = &s->drsuapi1.bind_handle;
1389 r->in.req.req2.first_object.next_object = NULL;
1390 r->in.req.req2.first_object.object.identifier = identifier;
1391 r->in.req.req2.first_object.object.unknown1 = 0x00000000;
1392 r->in.req.req2.first_object.object.attribute_ctr.num_attributes = num_attrs;
1393 r->in.req.req2.first_object.object.attribute_ctr.attributes = attrs;
1395 req = dcerpc_drsuapi_DsAddEntry_send(s->drsuapi1.pipe, r, r);
1396 composite_continue_rpc(c, req, becomeDC_drsuapi1_add_entry_recv, s);
1399 static void becomeDC_drsuapi2_connect_recv(struct composite_context *req);
1400 static NTSTATUS becomeDC_prepare_db(struct libnet_BecomeDC_state *s);
1402 static void becomeDC_drsuapi1_add_entry_recv(struct rpc_request *req)
1404 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
1405 struct libnet_BecomeDC_state);
1406 struct composite_context *c = s->creq;
1407 struct drsuapi_DsAddEntry *r = talloc_get_type(req->ndr.struct_ptr,
1408 struct drsuapi_DsAddEntry);
1410 c->status = dcerpc_ndr_request_recv(req);
1411 if (!composite_is_ok(c)) return;
1413 if (!W_ERROR_IS_OK(r->out.result)) {
1414 composite_error(c, werror_to_ntstatus(r->out.result));
1418 if (r->out.level == 3) {
1419 if (r->out.ctr.ctr3.count != 1) {
1422 if (r->out.ctr.ctr3.level != 1) {
1423 composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
1427 if (!r->out.ctr.ctr3.error) {
1428 composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
1432 status = r->out.ctr.ctr3.error->info1.status;
1434 if (!r->out.ctr.ctr3.error->info1.info) {
1435 composite_error(c, werror_to_ntstatus(status));
1439 /* see if we can get a more detailed error */
1440 switch (r->out.ctr.ctr3.error->info1.level) {
1442 status = r->out.ctr.ctr3.error->info1.info->error1.status;
1448 status = r->out.ctr.ctr3.error->info1.info->errorX.status;
1452 composite_error(c, werror_to_ntstatus(status));
1456 s->dest_dsa.ntds_guid = r->out.ctr.ctr3.objects[0].guid;
1457 } else if (r->out.level == 2) {
1458 if (r->out.ctr.ctr2.count != 1) {
1459 composite_error(c, werror_to_ntstatus(r->out.ctr.ctr2.error.status));
1463 s->dest_dsa.ntds_guid = r->out.ctr.ctr2.objects[0].guid;
1465 composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
1471 s->dest_dsa.ntds_dn_str = talloc_asprintf(s, "CN=NTDS Settings,%s",
1472 s->dest_dsa.server_dn_str);
1473 if (composite_nomem(s->dest_dsa.ntds_dn_str, c)) return;
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 libnet_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 = NULL;
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 = NULL;
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;
1596 * we should try to use the drsuapi_p->pipe here, as w2k3 does
1597 * but it seems that some extra flags in the DCERPC Bind call
1598 * are needed for it. Or the same KRB5 TGS is needed on both
1601 req = dcerpc_drsuapi_DsGetNCChanges_send(drsuapi_h->pipe, r, r);
1602 composite_continue_rpc(c, req, recv_fn, s);
1605 static WERROR becomeDC_drsuapi_pull_partition_recv(struct libnet_BecomeDC_state *s,
1606 struct libnet_BecomeDC_Partition *partition,
1607 struct drsuapi_DsGetNCChanges *r)
1609 uint32_t ctr_level = 0;
1610 struct drsuapi_DsGetNCChangesCtr1 *ctr1 = NULL;
1611 struct drsuapi_DsGetNCChangesCtr6 *ctr6 = NULL;
1612 struct GUID *source_dsa_guid;
1613 struct GUID *source_dsa_invocation_id;
1614 struct drsuapi_DsReplicaHighWaterMark *new_highwatermark;
1617 if (!W_ERROR_IS_OK(r->out.result)) {
1618 return r->out.result;
1621 if (r->out.level == 1) {
1623 ctr1 = &r->out.ctr.ctr1;
1624 } else if (r->out.level == 2) {
1626 ctr1 = r->out.ctr.ctr2.ctr.mszip1.ctr1;
1627 } else if (r->out.level == 6) {
1629 ctr6 = &r->out.ctr.ctr6;
1630 } else if (r->out.level == 7 &&
1631 r->out.ctr.ctr7.level == 6 &&
1632 r->out.ctr.ctr7.type == DRSUAPI_COMPRESSION_TYPE_MSZIP) {
1634 ctr6 = r->out.ctr.ctr7.ctr.mszip6.ctr6;
1636 return WERR_BAD_NET_RESP;
1639 switch (ctr_level) {
1641 source_dsa_guid = &ctr1->source_dsa_guid;
1642 source_dsa_invocation_id = &ctr1->source_dsa_invocation_id;
1643 new_highwatermark = &ctr1->new_highwatermark;
1646 source_dsa_guid = &ctr6->source_dsa_guid;
1647 source_dsa_invocation_id = &ctr6->source_dsa_invocation_id;
1648 new_highwatermark = &ctr6->new_highwatermark;
1652 partition->highwatermark = *new_highwatermark;
1653 partition->source_dsa_guid = *source_dsa_guid;
1654 partition->source_dsa_invocation_id = *source_dsa_invocation_id;
1656 if (!partition->store_chunk) return WERR_OK;
1658 s->_sc.domain = &s->domain;
1659 s->_sc.forest = &s->forest;
1660 s->_sc.source_dsa = &s->source_dsa;
1661 s->_sc.dest_dsa = &s->dest_dsa;
1662 s->_sc.partition = partition;
1663 s->_sc.ctr_level = ctr_level;
1667 nt_status = partition->store_chunk(s->callbacks.private_data, &s->_sc);
1668 if (!NT_STATUS_IS_OK(nt_status)) {
1669 return ntstatus_to_werror(nt_status);
1675 static void becomeDC_drsuapi3_pull_schema_recv(struct rpc_request *req);
1677 static void becomeDC_drsuapi3_pull_schema_send(struct libnet_BecomeDC_state *s)
1679 s->schema_part.nc.guid = GUID_zero();
1680 s->schema_part.nc.sid = s->zero_sid;
1681 s->schema_part.nc.dn = s->forest.schema_dn_str;
1683 s->schema_part.destination_dsa_guid = s->drsuapi2.bind_guid;
1685 s->schema_part.replica_flags = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
1686 | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
1687 | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS
1688 | DRSUAPI_DS_REPLICA_NEIGHBOUR_FULL_IN_PROGRESS
1689 | DRSUAPI_DS_REPLICA_NEIGHBOUR_NEVER_SYNCED
1690 | DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES;
1692 s->schema_part.store_chunk = s->callbacks.schema_chunk;
1694 becomeDC_drsuapi_pull_partition_send(s, &s->drsuapi2, &s->drsuapi3, &s->schema_part,
1695 becomeDC_drsuapi3_pull_schema_recv);
1698 static void becomeDC_drsuapi3_pull_config_send(struct libnet_BecomeDC_state *s);
1700 static void becomeDC_drsuapi3_pull_schema_recv(struct rpc_request *req)
1702 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
1703 struct libnet_BecomeDC_state);
1704 struct composite_context *c = s->creq;
1705 struct drsuapi_DsGetNCChanges *r = talloc_get_type(req->ndr.struct_ptr,
1706 struct drsuapi_DsGetNCChanges);
1709 c->status = dcerpc_ndr_request_recv(req);
1710 if (!composite_is_ok(c)) return;
1712 status = becomeDC_drsuapi_pull_partition_recv(s, &s->schema_part, r);
1713 if (!W_ERROR_IS_OK(status)) {
1714 composite_error(c, werror_to_ntstatus(status));
1720 if (s->schema_part.highwatermark.tmp_highest_usn > s->schema_part.highwatermark.highest_usn) {
1721 becomeDC_drsuapi_pull_partition_send(s, &s->drsuapi2, &s->drsuapi3, &s->schema_part,
1722 becomeDC_drsuapi3_pull_schema_recv);
1726 becomeDC_drsuapi3_pull_config_send(s);
1729 static void becomeDC_drsuapi3_pull_config_recv(struct rpc_request *req);
1731 static void becomeDC_drsuapi3_pull_config_send(struct libnet_BecomeDC_state *s)
1733 s->config_part.nc.guid = GUID_zero();
1734 s->config_part.nc.sid = s->zero_sid;
1735 s->config_part.nc.dn = s->forest.config_dn_str;
1737 s->config_part.destination_dsa_guid = s->drsuapi2.bind_guid;
1739 s->config_part.replica_flags = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
1740 | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
1741 | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS
1742 | DRSUAPI_DS_REPLICA_NEIGHBOUR_FULL_IN_PROGRESS
1743 | DRSUAPI_DS_REPLICA_NEIGHBOUR_NEVER_SYNCED
1744 | DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES;
1746 s->config_part.store_chunk = s->callbacks.config_chunk;
1748 becomeDC_drsuapi_pull_partition_send(s, &s->drsuapi2, &s->drsuapi3, &s->config_part,
1749 becomeDC_drsuapi3_pull_config_recv);
1752 static void becomeDC_drsuapi3_pull_config_recv(struct rpc_request *req)
1754 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
1755 struct libnet_BecomeDC_state);
1756 struct composite_context *c = s->creq;
1757 struct drsuapi_DsGetNCChanges *r = talloc_get_type(req->ndr.struct_ptr,
1758 struct drsuapi_DsGetNCChanges);
1761 c->status = dcerpc_ndr_request_recv(req);
1762 if (!composite_is_ok(c)) return;
1764 status = becomeDC_drsuapi_pull_partition_recv(s, &s->config_part, r);
1765 if (!W_ERROR_IS_OK(status)) {
1766 composite_error(c, werror_to_ntstatus(status));
1772 if (s->config_part.highwatermark.tmp_highest_usn > s->config_part.highwatermark.highest_usn) {
1773 becomeDC_drsuapi_pull_partition_send(s, &s->drsuapi2, &s->drsuapi3, &s->config_part,
1774 becomeDC_drsuapi3_pull_config_recv);
1778 becomeDC_connect_ldap2(s);
1781 static void becomeDC_drsuapi3_pull_domain_recv(struct rpc_request *req);
1783 static void becomeDC_drsuapi3_pull_domain_send(struct libnet_BecomeDC_state *s)
1785 s->domain_part.nc.guid = GUID_zero();
1786 s->domain_part.nc.sid = s->zero_sid;
1787 s->domain_part.nc.dn = s->domain.dn_str;
1789 s->domain_part.destination_dsa_guid = s->drsuapi2.bind_guid;
1791 s->domain_part.replica_flags = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
1792 | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
1793 | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS
1794 | DRSUAPI_DS_REPLICA_NEIGHBOUR_FULL_IN_PROGRESS
1795 | DRSUAPI_DS_REPLICA_NEIGHBOUR_NEVER_SYNCED
1796 | DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES;
1798 s->domain_part.store_chunk = s->callbacks.domain_chunk;
1800 becomeDC_drsuapi_pull_partition_send(s, &s->drsuapi2, &s->drsuapi3, &s->domain_part,
1801 becomeDC_drsuapi3_pull_domain_recv);
1804 static void becomeDC_drsuapi_update_refs_send(struct libnet_BecomeDC_state *s,
1805 struct becomeDC_drsuapi *drsuapi,
1806 struct libnet_BecomeDC_Partition *partition,
1807 void (*recv_fn)(struct rpc_request *req));
1808 static void becomeDC_drsuapi2_update_refs_schema_recv(struct rpc_request *req);
1810 static void becomeDC_drsuapi3_pull_domain_recv(struct rpc_request *req)
1812 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
1813 struct libnet_BecomeDC_state);
1814 struct composite_context *c = s->creq;
1815 struct drsuapi_DsGetNCChanges *r = talloc_get_type(req->ndr.struct_ptr,
1816 struct drsuapi_DsGetNCChanges);
1819 c->status = dcerpc_ndr_request_recv(req);
1820 if (!composite_is_ok(c)) return;
1822 status = becomeDC_drsuapi_pull_partition_recv(s, &s->domain_part, r);
1823 if (!W_ERROR_IS_OK(status)) {
1824 composite_error(c, werror_to_ntstatus(status));
1830 if (s->domain_part.highwatermark.tmp_highest_usn > s->domain_part.highwatermark.highest_usn) {
1831 becomeDC_drsuapi_pull_partition_send(s, &s->drsuapi2, &s->drsuapi3, &s->domain_part,
1832 becomeDC_drsuapi3_pull_domain_recv);
1836 becomeDC_drsuapi_update_refs_send(s, &s->drsuapi2, &s->schema_part,
1837 becomeDC_drsuapi2_update_refs_schema_recv);
1840 static void becomeDC_drsuapi_update_refs_send(struct libnet_BecomeDC_state *s,
1841 struct becomeDC_drsuapi *drsuapi,
1842 struct libnet_BecomeDC_Partition *partition,
1843 void (*recv_fn)(struct rpc_request *req))
1845 struct composite_context *c = s->creq;
1846 struct rpc_request *req;
1847 struct drsuapi_DsReplicaUpdateRefs *r;
1848 const char *ntds_guid_str;
1849 const char *ntds_dns_name;
1851 r = talloc(s, struct drsuapi_DsReplicaUpdateRefs);
1852 if (composite_nomem(r, c)) return;
1854 ntds_guid_str = GUID_string(r, &s->dest_dsa.ntds_guid);
1855 if (composite_nomem(ntds_guid_str, c)) return;
1857 ntds_dns_name = talloc_asprintf(r, "%s._msdcs.%s",
1859 s->domain.dns_name);
1860 if (composite_nomem(ntds_dns_name, c)) return;
1862 r->in.bind_handle = &drsuapi->bind_handle;
1864 r->in.req.req1.naming_context = &partition->nc;
1865 r->in.req.req1.dest_dsa_dns_name= ntds_dns_name;
1866 r->in.req.req1.dest_dsa_guid = s->dest_dsa.ntds_guid;
1867 r->in.req.req1.options = DRSUAPI_DS_REPLICA_UPDATE_ADD_REFERENCE
1868 | DRSUAPI_DS_REPLICA_UPDATE_DELETE_REFERENCE
1869 | DRSUAPI_DS_REPLICA_UPDATE_0x00000010;
1871 req = dcerpc_drsuapi_DsReplicaUpdateRefs_send(drsuapi->pipe, r, r);
1872 composite_continue_rpc(c, req, recv_fn, s);
1875 static void becomeDC_drsuapi2_update_refs_config_recv(struct rpc_request *req);
1877 static void becomeDC_drsuapi2_update_refs_schema_recv(struct rpc_request *req)
1879 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
1880 struct libnet_BecomeDC_state);
1881 struct composite_context *c = s->creq;
1882 struct drsuapi_DsReplicaUpdateRefs *r = talloc_get_type(req->ndr.struct_ptr,
1883 struct drsuapi_DsReplicaUpdateRefs);
1885 c->status = dcerpc_ndr_request_recv(req);
1886 if (!composite_is_ok(c)) return;
1888 if (!W_ERROR_IS_OK(r->out.result)) {
1889 composite_error(c, werror_to_ntstatus(r->out.result));
1895 becomeDC_drsuapi_update_refs_send(s, &s->drsuapi2, &s->config_part,
1896 becomeDC_drsuapi2_update_refs_config_recv);
1899 static void becomeDC_drsuapi2_update_refs_domain_recv(struct rpc_request *req);
1901 static void becomeDC_drsuapi2_update_refs_config_recv(struct rpc_request *req)
1903 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
1904 struct libnet_BecomeDC_state);
1905 struct composite_context *c = s->creq;
1906 struct drsuapi_DsReplicaUpdateRefs *r = talloc_get_type(req->ndr.struct_ptr,
1907 struct drsuapi_DsReplicaUpdateRefs);
1909 c->status = dcerpc_ndr_request_recv(req);
1910 if (!composite_is_ok(c)) return;
1912 if (!W_ERROR_IS_OK(r->out.result)) {
1913 composite_error(c, werror_to_ntstatus(r->out.result));
1919 becomeDC_drsuapi_update_refs_send(s, &s->drsuapi2, &s->domain_part,
1920 becomeDC_drsuapi2_update_refs_domain_recv);
1923 static void becomeDC_drsuapi2_update_refs_domain_recv(struct rpc_request *req)
1925 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
1926 struct libnet_BecomeDC_state);
1927 struct composite_context *c = s->creq;
1928 struct drsuapi_DsReplicaUpdateRefs *r = talloc_get_type(req->ndr.struct_ptr,
1929 struct drsuapi_DsReplicaUpdateRefs);
1931 c->status = dcerpc_ndr_request_recv(req);
1932 if (!composite_is_ok(c)) return;
1934 if (!W_ERROR_IS_OK(r->out.result)) {
1935 composite_error(c, werror_to_ntstatus(r->out.result));
1941 /* TODO: use DDNS updates and register dns names */
1945 static NTSTATUS becomeDC_ldap2_modify_computer(struct libnet_BecomeDC_state *s)
1948 struct ldb_message *msg;
1950 uint32_t user_account_control = UF_SERVER_TRUST_ACCOUNT |
1951 UF_TRUSTED_FOR_DELEGATION;
1953 /* as the value is already as we want it to be, we're done */
1954 if (s->dest_dsa.user_account_control == user_account_control) {
1955 return NT_STATUS_OK;
1958 /* make a 'modify' msg, and only for serverReference */
1959 msg = ldb_msg_new(s);
1960 NT_STATUS_HAVE_NO_MEMORY(msg);
1961 msg->dn = ldb_dn_new(msg, s->ldap2.ldb, s->dest_dsa.computer_dn_str);
1962 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
1964 ret = ldb_msg_add_fmt(msg, "userAccountControl", "%u", user_account_control);
1967 return NT_STATUS_NO_MEMORY;
1970 /* mark all the message elements (should be just one)
1971 as LDB_FLAG_MOD_REPLACE */
1972 for (i=0;i<msg->num_elements;i++) {
1973 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
1976 ret = ldb_modify(s->ldap2.ldb, msg);
1978 if (ret != LDB_SUCCESS) {
1979 return NT_STATUS_LDAP(ret);
1982 s->dest_dsa.user_account_control = user_account_control;
1984 return NT_STATUS_OK;
1987 static NTSTATUS becomeDC_ldap2_move_computer(struct libnet_BecomeDC_state *s)
1990 struct ldb_result *r;
1991 struct ldb_dn *basedn;
1992 struct ldb_dn *old_dn;
1993 struct ldb_dn *new_dn;
1994 static const char *_1_1_attrs[] = {
1999 basedn = ldb_dn_new_fmt(s, s->ldap2.ldb, "<WKGUID=a361b2ffffd211d1aa4b00c04fd7d83a,%s>",
2001 NT_STATUS_HAVE_NO_MEMORY(basedn);
2003 ret = ldb_search(s->ldap2.ldb, basedn, LDB_SCOPE_BASE,
2004 "(objectClass=*)", _1_1_attrs, &r);
2005 talloc_free(basedn);
2006 if (ret != LDB_SUCCESS) {
2007 return NT_STATUS_LDAP(ret);
2008 } else if (r->count != 1) {
2010 return NT_STATUS_INVALID_NETWORK_RESPONSE;
2013 old_dn = ldb_dn_new(r, s->ldap2.ldb, s->dest_dsa.computer_dn_str);
2014 NT_STATUS_HAVE_NO_MEMORY(old_dn);
2016 new_dn = r->msgs[0]->dn;
2018 if (!ldb_dn_add_child_fmt(new_dn, "CN=%s", s->dest_dsa.netbios_name)) {
2020 return NT_STATUS_NO_MEMORY;
2023 if (ldb_dn_compare(old_dn, new_dn) == 0) {
2024 /* we don't need to rename if the old and new dn match */
2026 return NT_STATUS_OK;
2029 ret = ldb_rename(s->ldap2.ldb, old_dn, new_dn);
2030 if (ret != LDB_SUCCESS) {
2032 return NT_STATUS_LDAP(ret);
2035 s->dest_dsa.computer_dn_str = ldb_dn_alloc_linearized(s, new_dn);
2036 NT_STATUS_HAVE_NO_MEMORY(s->dest_dsa.computer_dn_str);
2040 return NT_STATUS_OK;
2043 static void becomeDC_connect_ldap2(struct libnet_BecomeDC_state *s)
2045 struct composite_context *c = s->creq;
2047 c->status = becomeDC_ldap_connect(s, &s->ldap2);
2048 if (!composite_is_ok(c)) return;
2050 c->status = becomeDC_ldap2_modify_computer(s);
2051 if (!composite_is_ok(c)) return;
2053 c->status = becomeDC_ldap2_move_computer(s);
2054 if (!composite_is_ok(c)) return;
2056 becomeDC_drsuapi3_pull_domain_send(s);
2059 struct composite_context *libnet_BecomeDC_send(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_BecomeDC *r)
2061 struct composite_context *c;
2062 struct libnet_BecomeDC_state *s;
2065 c = composite_create(mem_ctx, ctx->event_ctx);
2066 if (c == NULL) return NULL;
2068 s = talloc_zero(c, struct libnet_BecomeDC_state);
2069 if (composite_nomem(s, c)) return c;
2070 c->private_data = s;
2075 s->domain.dns_name = talloc_strdup(s, r->in.domain_dns_name);
2076 if (composite_nomem(s->domain.dns_name, c)) return c;
2077 s->domain.netbios_name = talloc_strdup(s, r->in.domain_netbios_name);
2078 if (composite_nomem(s->domain.netbios_name, c)) return c;
2079 s->domain.sid = dom_sid_dup(s, r->in.domain_sid);
2080 if (composite_nomem(s->domain.sid, c)) return c;
2082 /* Source DSA input */
2083 s->source_dsa.address = talloc_strdup(s, r->in.source_dsa_address);
2084 if (composite_nomem(s->source_dsa.address, c)) return c;
2086 /* Destination DSA input */
2087 s->dest_dsa.netbios_name= talloc_strdup(s, r->in.dest_dsa_netbios_name);
2088 if (composite_nomem(s->dest_dsa.netbios_name, c)) return c;
2090 /* Destination DSA dns_name construction */
2091 tmp_name = strlower_talloc(s, s->dest_dsa.netbios_name);
2092 if (composite_nomem(tmp_name, c)) return c;
2093 s->dest_dsa.dns_name = talloc_asprintf_append(tmp_name, ".%s",
2094 s->domain.dns_name);
2095 if (composite_nomem(s->dest_dsa.dns_name, c)) return c;
2097 /* Callback function pointers */
2098 s->callbacks = r->in.callbacks;
2100 becomeDC_send_cldap(s);
2104 NTSTATUS libnet_BecomeDC_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, struct libnet_BecomeDC *r)
2108 status = composite_wait(c);
2110 ZERO_STRUCT(r->out);
2116 NTSTATUS libnet_BecomeDC(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_BecomeDC *r)
2119 struct composite_context *c;
2120 c = libnet_BecomeDC_send(ctx, mem_ctx, r);
2121 status = libnet_BecomeDC_recv(c, mem_ctx, r);