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;
39 struct cldap_socket *sock;
40 struct cldap_netlogon io;
41 struct nbt_cldap_netlogon_5 netlogon5;
44 struct becomeDC_ldap {
45 struct ldb_context *ldb;
46 const struct ldb_message *rootdse;
49 struct becomeDC_drsuapi {
50 struct libnet_BecomeDC_state *s;
51 struct dcerpc_binding *binding;
52 struct dcerpc_pipe *pipe;
53 struct drsuapi_DsBind bind_r;
54 struct GUID bind_guid;
55 struct drsuapi_DsBindInfoCtr bind_info_ctr;
56 struct drsuapi_DsBindInfo28 local_info28;
57 struct drsuapi_DsBindInfo28 remote_info28;
58 struct policy_handle bind_handle;
64 const char *netbios_name;
65 const struct dom_sid *sid;
75 const char *root_dn_str;
76 const char *config_dn_str;
77 const char *schema_dn_str;
86 const char *netbios_name;
87 const char *site_name;
88 const char *server_dn_str;
89 const char *ntds_dn_str;
94 const char *netbios_name;
98 const char *site_name;
99 struct GUID site_guid;
100 const char *computer_dn_str;
101 const char *server_dn_str;
102 const char *ntds_dn_str;
103 struct GUID invocation_id;
104 uint32_t user_account_control;
108 uint32_t domain_behavior_version;
109 uint32_t config_behavior_version;
110 uint32_t schema_object_version;
111 uint32_t w2k3_update_revision;
114 struct becomeDC_fsmo {
115 const char *dns_name;
116 const char *server_dn_str;
117 const char *ntds_dn_str;
118 struct GUID ntds_guid;
119 } infrastructure_fsmo;
121 struct becomeDC_fsmo rid_manager_fsmo;
124 static void becomeDC_connect_ldap1(struct libnet_BecomeDC_state *s);
126 static void becomeDC_recv_cldap(struct cldap_request *req)
128 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
129 struct libnet_BecomeDC_state);
130 struct composite_context *c = s->creq;
132 c->status = cldap_netlogon_recv(req, s, &s->cldap.io);
133 if (!composite_is_ok(c)) return;
135 s->cldap.netlogon5 = s->cldap.io.out.netlogon.logon5;
137 s->domain.dns_name = s->cldap.netlogon5.dns_domain;
138 s->domain.netbios_name = s->cldap.netlogon5.domain;
139 s->domain.guid = s->cldap.netlogon5.domain_uuid;
141 s->forest.dns_name = s->cldap.netlogon5.forest;
143 s->source_dsa.dns_name = s->cldap.netlogon5.pdc_dns_name;
144 s->source_dsa.netbios_name = s->cldap.netlogon5.pdc_name;
145 s->source_dsa.site_name = s->cldap.netlogon5.server_site;
147 s->dest_dsa.site_name = s->cldap.netlogon5.client_site;
149 becomeDC_connect_ldap1(s);
152 static void becomeDC_send_cldap(struct libnet_BecomeDC_state *s)
154 struct composite_context *c = s->creq;
155 struct cldap_request *req;
157 s->cldap.io.in.dest_address = s->source_dsa.address;
158 s->cldap.io.in.realm = s->domain.dns_name;
159 s->cldap.io.in.host = s->dest_dsa.netbios_name;
160 s->cldap.io.in.user = NULL;
161 s->cldap.io.in.domain_guid = NULL;
162 s->cldap.io.in.domain_sid = NULL;
163 s->cldap.io.in.acct_control = -1;
164 s->cldap.io.in.version = 6;
166 s->cldap.sock = cldap_socket_init(s, s->libnet->event_ctx);
167 if (composite_nomem(s->cldap.sock, c)) return;
169 req = cldap_netlogon_send(s->cldap.sock, &s->cldap.io);
170 if (composite_nomem(req, c)) return;
171 req->async.fn = becomeDC_recv_cldap;
172 req->async.private = s;
175 static NTSTATUS becomeDC_ldap_connect(struct libnet_BecomeDC_state *s, struct becomeDC_ldap *ldap)
179 url = talloc_asprintf(s, "ldap://%s/", s->source_dsa.dns_name);
180 NT_STATUS_HAVE_NO_MEMORY(url);
182 ldap->ldb = ldb_wrap_connect(s, url,
187 if (ldap->ldb == NULL) {
188 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
194 static NTSTATUS becomeDC_ldap1_rootdse(struct libnet_BecomeDC_state *s)
197 struct ldb_result *r;
198 struct ldb_dn *basedn;
199 static const char *attrs[] = {
204 basedn = ldb_dn_new(s, s->ldap1.ldb, NULL);
205 NT_STATUS_HAVE_NO_MEMORY(basedn);
207 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
208 "(objectClass=*)", attrs, &r);
210 if (ret != LDB_SUCCESS) {
211 return NT_STATUS_LDAP(ret);
212 } else if (r->count != 1) {
214 return NT_STATUS_INVALID_NETWORK_RESPONSE;
218 s->ldap1.rootdse = r->msgs[0];
220 s->domain.dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "defaultNamingContext", NULL);
221 if (!s->domain.dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
223 s->forest.root_dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "rootDomainNamingContext", NULL);
224 if (!s->forest.root_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
225 s->forest.config_dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "configurationNamingContext", NULL);
226 if (!s->forest.config_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
227 s->forest.schema_dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "schemaNamingContext", NULL);
228 if (!s->forest.schema_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
230 s->source_dsa.server_dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "serverName", NULL);
231 if (!s->source_dsa.server_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
232 s->source_dsa.ntds_dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "dsServiceName", NULL);
233 if (!s->source_dsa.ntds_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
238 static NTSTATUS becomeDC_ldap1_config_behavior_version(struct libnet_BecomeDC_state *s)
241 struct ldb_result *r;
242 struct ldb_dn *basedn;
243 static const char *attrs[] = {
244 "msDs-Behavior-Version",
248 basedn = ldb_dn_new(s, s->ldap1.ldb, s->forest.config_dn_str);
249 NT_STATUS_HAVE_NO_MEMORY(basedn);
251 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_ONELEVEL,
252 "(cn=Partitions)", attrs, &r);
254 if (ret != LDB_SUCCESS) {
255 return NT_STATUS_LDAP(ret);
256 } else if (r->count != 1) {
258 return NT_STATUS_INVALID_NETWORK_RESPONSE;
261 s->ads_options.config_behavior_version = ldb_msg_find_attr_as_uint(r->msgs[0], "msDs-Behavior-Version", 0);
267 static NTSTATUS becomeDC_ldap1_domain_behavior_version(struct libnet_BecomeDC_state *s)
270 struct ldb_result *r;
271 struct ldb_dn *basedn;
272 static const char *attrs[] = {
273 "msDs-Behavior-Version",
277 basedn = ldb_dn_new(s, s->ldap1.ldb, s->domain.dn_str);
278 NT_STATUS_HAVE_NO_MEMORY(basedn);
280 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
281 "(objectClass=*)", attrs, &r);
283 if (ret != LDB_SUCCESS) {
284 return NT_STATUS_LDAP(ret);
285 } else if (r->count != 1) {
287 return NT_STATUS_INVALID_NETWORK_RESPONSE;
290 s->ads_options.domain_behavior_version = ldb_msg_find_attr_as_uint(r->msgs[0], "msDs-Behavior-Version", 0);
296 static NTSTATUS becomeDC_ldap1_schema_object_version(struct libnet_BecomeDC_state *s)
299 struct ldb_result *r;
300 struct ldb_dn *basedn;
301 static const char *attrs[] = {
306 basedn = ldb_dn_new(s, s->ldap1.ldb, s->forest.schema_dn_str);
307 NT_STATUS_HAVE_NO_MEMORY(basedn);
309 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
310 "(objectClass=*)", attrs, &r);
312 if (ret != LDB_SUCCESS) {
313 return NT_STATUS_LDAP(ret);
314 } else if (r->count != 1) {
316 return NT_STATUS_INVALID_NETWORK_RESPONSE;
319 s->ads_options.schema_object_version = ldb_msg_find_attr_as_uint(r->msgs[0], "objectVersion", 0);
325 static NTSTATUS becomeDC_ldap1_w2k3_update_revision(struct libnet_BecomeDC_state *s)
328 struct ldb_result *r;
329 struct ldb_dn *basedn;
330 static const char *attrs[] = {
335 basedn = ldb_dn_new_fmt(s, s->ldap1.ldb, "CN=Windows2003Update,CN=DomainUpdates,CN=System,%s",
337 NT_STATUS_HAVE_NO_MEMORY(basedn);
339 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
340 "(objectClass=*)", attrs, &r);
342 if (ret != LDB_SUCCESS) {
343 return NT_STATUS_LDAP(ret);
344 } else if (r->count != 1) {
346 return NT_STATUS_INVALID_NETWORK_RESPONSE;
349 s->ads_options.w2k3_update_revision = ldb_msg_find_attr_as_uint(r->msgs[0], "revision", 0);
355 static NTSTATUS becomeDC_ldap1_infrastructure_fsmo(struct libnet_BecomeDC_state *s)
358 struct ldb_result *r;
359 struct ldb_dn *basedn;
360 struct ldb_dn *ntds_dn;
361 struct ldb_dn *server_dn;
362 static const char *_1_1_attrs[] = {
366 static const char *fsmo_attrs[] = {
370 static const char *dns_attrs[] = {
374 static const char *guid_attrs[] = {
379 basedn = ldb_dn_new_fmt(s, s->ldap1.ldb, "<WKGUID=2fbac1870ade11d297c400c04fd8d5cd,%s>",
381 NT_STATUS_HAVE_NO_MEMORY(basedn);
383 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
384 "(objectClass=*)", _1_1_attrs, &r);
386 if (ret != LDB_SUCCESS) {
387 return NT_STATUS_LDAP(ret);
388 } else if (r->count != 1) {
390 return NT_STATUS_INVALID_NETWORK_RESPONSE;
393 basedn = talloc_steal(s, r->msgs[0]->dn);
396 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
397 "(objectClass=*)", fsmo_attrs, &r);
399 if (ret != LDB_SUCCESS) {
400 return NT_STATUS_LDAP(ret);
401 } else if (r->count != 1) {
403 return NT_STATUS_INVALID_NETWORK_RESPONSE;
406 s->infrastructure_fsmo.ntds_dn_str = samdb_result_string(r->msgs[0], "fSMORoleOwner", NULL);
407 if (!s->infrastructure_fsmo.ntds_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
408 talloc_steal(s, s->infrastructure_fsmo.ntds_dn_str);
412 ntds_dn = ldb_dn_new(s, s->ldap1.ldb, s->infrastructure_fsmo.ntds_dn_str);
413 NT_STATUS_HAVE_NO_MEMORY(ntds_dn);
415 server_dn = ldb_dn_get_parent(s, ntds_dn);
416 NT_STATUS_HAVE_NO_MEMORY(server_dn);
418 s->infrastructure_fsmo.server_dn_str = ldb_dn_alloc_linearized(s, server_dn);
419 NT_STATUS_HAVE_NO_MEMORY(s->infrastructure_fsmo.server_dn_str);
421 ret = ldb_search(s->ldap1.ldb, server_dn, LDB_SCOPE_BASE,
422 "(objectClass=*)", dns_attrs, &r);
423 if (ret != LDB_SUCCESS) {
424 return NT_STATUS_LDAP(ret);
425 } else if (r->count != 1) {
427 return NT_STATUS_INVALID_NETWORK_RESPONSE;
430 s->infrastructure_fsmo.dns_name = samdb_result_string(r->msgs[0], "dnsHostName", NULL);
431 if (!s->infrastructure_fsmo.dns_name) return NT_STATUS_INVALID_NETWORK_RESPONSE;
432 talloc_steal(s, s->infrastructure_fsmo.dns_name);
436 ret = ldb_search(s->ldap1.ldb, ntds_dn, LDB_SCOPE_BASE,
437 "(objectClass=*)", guid_attrs, &r);
438 if (ret != LDB_SUCCESS) {
439 return NT_STATUS_LDAP(ret);
440 } else if (r->count != 1) {
442 return NT_STATUS_INVALID_NETWORK_RESPONSE;
445 s->infrastructure_fsmo.ntds_guid = samdb_result_guid(r->msgs[0], "objectGUID");
452 static NTSTATUS becomeDC_ldap1_rid_manager_fsmo(struct libnet_BecomeDC_state *s)
455 struct ldb_result *r;
456 struct ldb_dn *basedn;
457 const char *reference_dn_str;
458 struct ldb_dn *ntds_dn;
459 struct ldb_dn *server_dn;
460 static const char *rid_attrs[] = {
461 "rIDManagerReference",
464 static const char *fsmo_attrs[] = {
468 static const char *dns_attrs[] = {
472 static const char *guid_attrs[] = {
477 basedn = ldb_dn_new(s, s->ldap1.ldb, s->domain.dn_str);
478 NT_STATUS_HAVE_NO_MEMORY(basedn);
480 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
481 "(objectClass=*)", rid_attrs, &r);
483 if (ret != LDB_SUCCESS) {
484 return NT_STATUS_LDAP(ret);
485 } else if (r->count != 1) {
487 return NT_STATUS_INVALID_NETWORK_RESPONSE;
490 reference_dn_str = samdb_result_string(r->msgs[0], "rIDManagerReference", NULL);
491 if (!reference_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
493 basedn = ldb_dn_new(s, s->ldap1.ldb, reference_dn_str);
494 NT_STATUS_HAVE_NO_MEMORY(basedn);
498 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
499 "(objectClass=*)", fsmo_attrs, &r);
501 if (ret != LDB_SUCCESS) {
502 return NT_STATUS_LDAP(ret);
503 } else if (r->count != 1) {
505 return NT_STATUS_INVALID_NETWORK_RESPONSE;
508 s->rid_manager_fsmo.ntds_dn_str = samdb_result_string(r->msgs[0], "fSMORoleOwner", NULL);
509 if (!s->rid_manager_fsmo.ntds_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
510 talloc_steal(s, s->rid_manager_fsmo.ntds_dn_str);
514 ntds_dn = ldb_dn_new(s, s->ldap1.ldb, s->rid_manager_fsmo.ntds_dn_str);
515 NT_STATUS_HAVE_NO_MEMORY(ntds_dn);
517 server_dn = ldb_dn_get_parent(s, ntds_dn);
518 NT_STATUS_HAVE_NO_MEMORY(server_dn);
520 s->rid_manager_fsmo.server_dn_str = ldb_dn_alloc_linearized(s, server_dn);
521 NT_STATUS_HAVE_NO_MEMORY(s->rid_manager_fsmo.server_dn_str);
523 ret = ldb_search(s->ldap1.ldb, server_dn, LDB_SCOPE_BASE,
524 "(objectClass=*)", dns_attrs, &r);
525 if (ret != LDB_SUCCESS) {
526 return NT_STATUS_LDAP(ret);
527 } else if (r->count != 1) {
529 return NT_STATUS_INVALID_NETWORK_RESPONSE;
532 s->rid_manager_fsmo.dns_name = samdb_result_string(r->msgs[0], "dnsHostName", NULL);
533 if (!s->rid_manager_fsmo.dns_name) return NT_STATUS_INVALID_NETWORK_RESPONSE;
534 talloc_steal(s, s->rid_manager_fsmo.dns_name);
538 ret = ldb_search(s->ldap1.ldb, ntds_dn, LDB_SCOPE_BASE,
539 "(objectClass=*)", guid_attrs, &r);
540 if (ret != LDB_SUCCESS) {
541 return NT_STATUS_LDAP(ret);
542 } else if (r->count != 1) {
544 return NT_STATUS_INVALID_NETWORK_RESPONSE;
547 s->rid_manager_fsmo.ntds_guid = samdb_result_guid(r->msgs[0], "objectGUID");
554 static NTSTATUS becomeDC_ldap1_site_object(struct libnet_BecomeDC_state *s)
557 struct ldb_result *r;
558 struct ldb_dn *basedn;
560 basedn = ldb_dn_new_fmt(s, s->ldap1.ldb, "CN=%s,CN=Sites,%s",
561 s->dest_dsa.site_name,
562 s->forest.config_dn_str);
563 NT_STATUS_HAVE_NO_MEMORY(basedn);
565 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
566 "(objectClass=*)", NULL, &r);
568 if (ret != LDB_SUCCESS) {
569 return NT_STATUS_LDAP(ret);
570 } else if (r->count != 1) {
572 return NT_STATUS_INVALID_NETWORK_RESPONSE;
575 s->dest_dsa.site_guid = samdb_result_guid(r->msgs[0], "objectGUID");
581 static NTSTATUS becomeDC_ldap1_computer_object(struct libnet_BecomeDC_state *s)
584 struct ldb_result *r;
585 struct ldb_dn *basedn;
587 static const char *attrs[] = {
589 "userAccountControl",
593 basedn = ldb_dn_new(s, s->ldap1.ldb, s->domain.dn_str);
594 NT_STATUS_HAVE_NO_MEMORY(basedn);
596 filter = talloc_asprintf(basedn, "(&(|(objectClass=user)(objectClass=computer))(sAMAccountName=%s$))",
597 s->dest_dsa.netbios_name);
598 NT_STATUS_HAVE_NO_MEMORY(filter);
600 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_SUBTREE,
603 if (ret != LDB_SUCCESS) {
604 return NT_STATUS_LDAP(ret);
605 } else if (r->count != 1) {
607 return NT_STATUS_INVALID_NETWORK_RESPONSE;
610 s->dest_dsa.computer_dn_str = samdb_result_string(r->msgs[0], "distinguishedName", NULL);
611 if (!s->dest_dsa.computer_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
612 talloc_steal(s, s->dest_dsa.computer_dn_str);
614 s->dest_dsa.user_account_control = samdb_result_uint(r->msgs[0], "userAccountControl", 0);
620 static NTSTATUS becomeDC_ldap1_server_object_1(struct libnet_BecomeDC_state *s)
623 struct ldb_result *r;
624 struct ldb_dn *basedn;
625 const char *server_reference_dn_str;
626 struct ldb_dn *server_reference_dn;
627 struct ldb_dn *computer_dn;
629 basedn = ldb_dn_new_fmt(s, s->ldap1.ldb, "CN=%s,CN=Servers,CN=%s,CN=Sites,%s",
630 s->dest_dsa.netbios_name,
631 s->dest_dsa.site_name,
632 s->forest.config_dn_str);
633 NT_STATUS_HAVE_NO_MEMORY(basedn);
635 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
636 "(objectClass=*)", NULL, &r);
638 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
639 /* if the object doesn't exist, we'll create it later */
641 } else if (ret != LDB_SUCCESS) {
642 return NT_STATUS_LDAP(ret);
643 } else if (r->count != 1) {
645 return NT_STATUS_INVALID_NETWORK_RESPONSE;
648 server_reference_dn_str = samdb_result_string(r->msgs[0], "serverReference", NULL);
649 if (server_reference_dn_str) {
650 server_reference_dn = ldb_dn_new(r, s->ldap1.ldb, server_reference_dn_str);
651 NT_STATUS_HAVE_NO_MEMORY(server_reference_dn);
653 computer_dn = ldb_dn_new(r, s->ldap1.ldb, s->dest_dsa.computer_dn_str);
654 NT_STATUS_HAVE_NO_MEMORY(computer_dn);
657 * if the server object belongs to another DC in another domain in the forest,
658 * we should not touch this object!
660 if (ldb_dn_compare(computer_dn, server_reference_dn) != 0) {
662 return NT_STATUS_OBJECT_NAME_COLLISION;
666 /* if the server object is already for the dest_dsa, then we don't need to create it */
667 s->dest_dsa.server_dn_str = samdb_result_string(r->msgs[0], "distinguishedName", NULL);
668 if (!s->dest_dsa.server_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
669 talloc_steal(s, s->dest_dsa.server_dn_str);
675 static NTSTATUS becomeDC_ldap1_server_object_2(struct libnet_BecomeDC_state *s)
678 struct ldb_result *r;
679 struct ldb_dn *basedn;
680 const char *server_reference_bl_dn_str;
681 static const char *attrs[] = {
686 /* if the server_dn_str has a valid value, we skip this lookup */
687 if (s->dest_dsa.server_dn_str) return NT_STATUS_OK;
689 basedn = ldb_dn_new(s, s->ldap1.ldb, s->dest_dsa.computer_dn_str);
690 NT_STATUS_HAVE_NO_MEMORY(basedn);
692 ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
693 "(objectClass=*)", attrs, &r);
695 if (ret != LDB_SUCCESS) {
696 return NT_STATUS_LDAP(ret);
697 } else if (r->count != 1) {
699 return NT_STATUS_INVALID_NETWORK_RESPONSE;
702 server_reference_bl_dn_str = samdb_result_string(r->msgs[0], "serverReferenceBL", NULL);
703 if (!server_reference_bl_dn_str) {
704 /* if no back link is present, we're done for this function */
709 /* if the server object is already for the dest_dsa, then we don't need to create it */
710 s->dest_dsa.server_dn_str = samdb_result_string(r->msgs[0], "serverReferenceBL", NULL);
711 if (s->dest_dsa.server_dn_str) {
712 /* if a back link is present, we know that the server object is present */
713 talloc_steal(s, s->dest_dsa.server_dn_str);
720 static NTSTATUS becomeDC_ldap1_server_object_add(struct libnet_BecomeDC_state *s)
723 struct ldb_message *msg;
726 /* if the server_dn_str has a valid value, we skip this lookup */
727 if (s->dest_dsa.server_dn_str) return NT_STATUS_OK;
729 msg = ldb_msg_new(s);
730 NT_STATUS_HAVE_NO_MEMORY(msg);
732 msg->dn = ldb_dn_new_fmt(msg, s->ldap1.ldb, "CN=%s,CN=Servers,CN=%s,CN=Sites,%s",
733 s->dest_dsa.netbios_name,
734 s->dest_dsa.site_name,
735 s->forest.config_dn_str);
736 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
738 ret = ldb_msg_add_string(msg, "objectClass", "server");
741 return NT_STATUS_NO_MEMORY;
743 ret = ldb_msg_add_string(msg, "systemFlags", "50000000");
746 return NT_STATUS_NO_MEMORY;
748 ret = ldb_msg_add_string(msg, "serverReference", s->dest_dsa.computer_dn_str);
751 return NT_STATUS_NO_MEMORY;
754 server_dn_str = ldb_dn_alloc_linearized(s, msg->dn);
755 NT_STATUS_HAVE_NO_MEMORY(server_dn_str);
757 ret = ldb_add(s->ldap1.ldb, msg);
759 if (ret != LDB_SUCCESS) {
760 talloc_free(server_dn_str);
761 return NT_STATUS_LDAP(ret);
764 s->dest_dsa.server_dn_str = server_dn_str;
769 static NTSTATUS becomeDC_ldap1_server_object_modify(struct libnet_BecomeDC_state *s)
772 struct ldb_message *msg;
775 /* make a 'modify' msg, and only for serverReference */
776 msg = ldb_msg_new(s);
777 NT_STATUS_HAVE_NO_MEMORY(msg);
778 msg->dn = ldb_dn_new(msg, s->ldap1.ldb, s->dest_dsa.server_dn_str);
779 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
781 ret = ldb_msg_add_string(msg, "serverReference", s->dest_dsa.computer_dn_str);
784 return NT_STATUS_NO_MEMORY;
787 /* mark all the message elements (should be just one)
788 as LDB_FLAG_MOD_ADD */
789 for (i=0;i<msg->num_elements;i++) {
790 msg->elements[i].flags = LDB_FLAG_MOD_ADD;
793 ret = ldb_modify(s->ldap1.ldb, msg);
794 if (ret == LDB_SUCCESS) {
797 } else if (ret == LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) {
798 /* retry with LDB_FLAG_MOD_REPLACE */
801 return NT_STATUS_LDAP(ret);
804 /* mark all the message elements (should be just one)
805 as LDB_FLAG_MOD_REPLACE */
806 for (i=0;i<msg->num_elements;i++) {
807 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
810 ret = ldb_modify(s->ldap1.ldb, msg);
812 if (ret != LDB_SUCCESS) {
813 return NT_STATUS_LDAP(ret);
819 static void becomeDC_drsuapi_connect_send(struct libnet_BecomeDC_state *s,
820 struct becomeDC_drsuapi *drsuapi,
821 void (*recv_fn)(struct composite_context *req));
822 static void becomeDC_drsuapi1_connect_recv(struct composite_context *req);
823 static void becomeDC_connect_ldap2(struct libnet_BecomeDC_state *s);
825 static void becomeDC_connect_ldap1(struct libnet_BecomeDC_state *s)
827 struct composite_context *c = s->creq;
829 c->status = becomeDC_ldap_connect(s, &s->ldap1);
830 if (!composite_is_ok(c)) return;
832 c->status = becomeDC_ldap1_rootdse(s);
833 if (!composite_is_ok(c)) return;
835 c->status = becomeDC_ldap1_config_behavior_version(s);
836 if (!composite_is_ok(c)) return;
838 c->status = becomeDC_ldap1_domain_behavior_version(s);
839 if (!composite_is_ok(c)) return;
841 c->status = becomeDC_ldap1_schema_object_version(s);
842 if (!composite_is_ok(c)) return;
844 c->status = becomeDC_ldap1_w2k3_update_revision(s);
845 if (!composite_is_ok(c)) return;
847 c->status = becomeDC_ldap1_infrastructure_fsmo(s);
848 if (!composite_is_ok(c)) return;
850 c->status = becomeDC_ldap1_rid_manager_fsmo(s);
851 if (!composite_is_ok(c)) return;
853 c->status = becomeDC_ldap1_site_object(s);
854 if (!composite_is_ok(c)) return;
856 c->status = becomeDC_ldap1_computer_object(s);
857 if (!composite_is_ok(c)) return;
859 c->status = becomeDC_ldap1_server_object_1(s);
860 if (!composite_is_ok(c)) return;
862 c->status = becomeDC_ldap1_server_object_2(s);
863 if (!composite_is_ok(c)) return;
865 c->status = becomeDC_ldap1_server_object_add(s);
866 if (!composite_is_ok(c)) return;
868 c->status = becomeDC_ldap1_server_object_modify(s);
869 if (!composite_is_ok(c)) return;
871 becomeDC_drsuapi_connect_send(s, &s->drsuapi1, becomeDC_drsuapi1_connect_recv);
874 static void becomeDC_drsuapi_connect_send(struct libnet_BecomeDC_state *s,
875 struct becomeDC_drsuapi *drsuapi,
876 void (*recv_fn)(struct composite_context *req))
878 struct composite_context *c = s->creq;
879 struct composite_context *creq;
884 binding_str = talloc_asprintf(s, "ncacn_ip_tcp:%s[krb5,seal]", s->source_dsa.dns_name);
885 if (composite_nomem(binding_str, c)) return;
887 c->status = dcerpc_parse_binding(s, binding_str, &drsuapi->binding);
888 talloc_free(binding_str);
889 if (!composite_is_ok(c)) return;
891 creq = dcerpc_pipe_connect_b_send(s, drsuapi->binding, &dcerpc_table_drsuapi,
892 s->libnet->cred, s->libnet->event_ctx);
893 composite_continue(c, creq, recv_fn, s);
896 static void becomeDC_drsuapi_bind_send(struct libnet_BecomeDC_state *s,
897 struct becomeDC_drsuapi *drsuapi,
898 void (*recv_fn)(struct rpc_request *req));
899 static void becomeDC_drsuapi1_bind_recv(struct rpc_request *req);
901 static void becomeDC_drsuapi1_connect_recv(struct composite_context *req)
903 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
904 struct libnet_BecomeDC_state);
905 struct composite_context *c = s->creq;
907 c->status = dcerpc_pipe_connect_b_recv(req, s, &s->drsuapi1.pipe);
908 if (!composite_is_ok(c)) return;
910 becomeDC_drsuapi_bind_send(s, &s->drsuapi1, becomeDC_drsuapi1_bind_recv);
913 static void becomeDC_drsuapi_bind_send(struct libnet_BecomeDC_state *s,
914 struct becomeDC_drsuapi *drsuapi,
915 void (*recv_fn)(struct rpc_request *req))
917 struct composite_context *c = s->creq;
918 struct rpc_request *req;
919 struct drsuapi_DsBindInfo28 *bind_info28;
921 GUID_from_string(DRSUAPI_DS_BIND_GUID_W2K3, &drsuapi->bind_guid);
923 bind_info28 = &drsuapi->local_info28;
924 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_BASE;
925 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION;
926 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI;
927 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2;
928 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS;
929 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1;
930 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION;
931 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE;
932 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2;
933 if (s->ads_options.domain_behavior_version == 2) {
934 /* TODO: find out how this is really triggered! */
935 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION;
937 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2;
938 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD;
939 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND;
940 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO;
941 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION;
942 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01;
943 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP;
944 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY;
945 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3;
946 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_00100000;
947 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2;
948 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6;
949 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS;
950 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8;
951 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5;
952 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6;
953 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3;
954 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7;
955 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT;
956 #if 0 /* we don't support XPRESS compression yet */
957 bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS;
959 bind_info28->site_guid = s->dest_dsa.site_guid;
960 if (s->ads_options.domain_behavior_version == 2) {
961 /* TODO: find out how this is really triggered! */
962 bind_info28->u1 = 528;
964 bind_info28->u1 = 516;
966 bind_info28->repl_epoch = 0;
968 drsuapi->bind_info_ctr.length = 28;
969 drsuapi->bind_info_ctr.info.info28 = *bind_info28;
971 drsuapi->bind_r.in.bind_guid = &drsuapi->bind_guid;
972 drsuapi->bind_r.in.bind_info = &drsuapi->bind_info_ctr;
973 drsuapi->bind_r.out.bind_handle = &drsuapi->bind_handle;
975 req = dcerpc_drsuapi_DsBind_send(drsuapi->pipe, s, &drsuapi->bind_r);
976 composite_continue_rpc(c, req, recv_fn, s);
979 static void becomeDC_drsuapi1_add_entry_send(struct libnet_BecomeDC_state *s);
981 static void becomeDC_drsuapi1_bind_recv(struct rpc_request *req)
983 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
984 struct libnet_BecomeDC_state);
985 struct composite_context *c = s->creq;
987 c->status = dcerpc_ndr_request_recv(req);
988 if (!composite_is_ok(c)) return;
990 if (!W_ERROR_IS_OK(s->drsuapi1.bind_r.out.result)) {
991 composite_error(c, werror_to_ntstatus(s->drsuapi1.bind_r.out.result));
995 ZERO_STRUCT(s->drsuapi1.remote_info28);
996 if (s->drsuapi1.bind_r.out.bind_info) {
997 switch (s->drsuapi1.bind_r.out.bind_info->length) {
999 struct drsuapi_DsBindInfo24 *info24;
1000 info24 = &s->drsuapi1.bind_r.out.bind_info->info.info24;
1001 s->drsuapi1.remote_info28.supported_extensions = info24->supported_extensions;
1002 s->drsuapi1.remote_info28.site_guid = info24->site_guid;
1003 s->drsuapi1.remote_info28.u1 = info24->u1;
1004 s->drsuapi1.remote_info28.repl_epoch = 0;
1008 s->drsuapi1.remote_info28 = s->drsuapi1.bind_r.out.bind_info->info.info28;
1013 becomeDC_drsuapi1_add_entry_send(s);
1016 static void becomeDC_drsuapi1_add_entry_recv(struct rpc_request *req);
1018 static void becomeDC_drsuapi1_add_entry_send(struct libnet_BecomeDC_state *s)
1020 struct composite_context *c = s->creq;
1021 struct rpc_request *req;
1022 struct drsuapi_DsAddEntry *r;
1023 struct drsuapi_DsReplicaObjectIdentifier *identifier;
1024 uint32_t num_attrs, i = 0;
1025 struct drsuapi_DsReplicaAttribute *attrs;
1026 struct dom_sid zero_sid;
1028 ZERO_STRUCT(zero_sid);
1030 /* choose a random invocationId */
1031 s->dest_dsa.invocation_id = GUID_random();
1033 r = talloc_zero(s, struct drsuapi_DsAddEntry);
1034 if (composite_nomem(r, c)) return;
1036 /* setup identifier */
1037 identifier = talloc(r, struct drsuapi_DsReplicaObjectIdentifier);
1038 if (composite_nomem(identifier, c)) return;
1039 identifier->guid = GUID_zero();
1040 identifier->sid = zero_sid;
1041 identifier->dn = talloc_asprintf(identifier, "CN=NTDS Settings,%s",
1042 s->dest_dsa.server_dn_str);
1043 if (composite_nomem(identifier->dn, c)) return;
1045 /* allocate attribute array */
1047 attrs = talloc_array(r, struct drsuapi_DsReplicaAttribute, num_attrs);
1048 if (composite_nomem(attrs, c)) return;
1050 /* ntSecurityDescriptor */
1052 struct drsuapi_DsAttributeValueSecurityDescriptor *vs;
1053 struct security_descriptor *v;
1054 struct dom_sid *domain_admins_sid;
1055 const char *domain_admins_sid_str;
1057 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueSecurityDescriptor, 1);
1058 if (composite_nomem(vs, c)) return;
1060 domain_admins_sid = dom_sid_add_rid(vs, s->domain.sid, DOMAIN_RID_ADMINS);
1061 if (composite_nomem(domain_admins_sid, c)) return;
1063 domain_admins_sid_str = dom_sid_string(domain_admins_sid, domain_admins_sid);
1064 if (composite_nomem(domain_admins_sid_str, c)) return;
1066 v = security_descriptor_create(vs,
1067 /* owner: domain admins */
1068 domain_admins_sid_str,
1069 /* owner group: domain admins */
1070 domain_admins_sid_str,
1071 /* authenticated users */
1072 SID_NT_AUTHENTICATED_USERS,
1073 SEC_ACE_TYPE_ACCESS_ALLOWED,
1074 SEC_STD_READ_CONTROL |
1077 SEC_ADS_LIST_OBJECT,
1080 domain_admins_sid_str,
1081 SEC_ACE_TYPE_ACCESS_ALLOWED,
1083 SEC_ADS_CREATE_CHILD |
1085 SEC_ADS_SELF_WRITE |
1087 SEC_ADS_WRITE_PROP |
1088 SEC_ADS_DELETE_TREE |
1089 SEC_ADS_LIST_OBJECT |
1090 SEC_ADS_CONTROL_ACCESS,
1094 SEC_ACE_TYPE_ACCESS_ALLOWED,
1096 SEC_ADS_CREATE_CHILD |
1097 SEC_ADS_DELETE_CHILD |
1099 SEC_ADS_SELF_WRITE |
1101 SEC_ADS_WRITE_PROP |
1102 SEC_ADS_DELETE_TREE |
1103 SEC_ADS_LIST_OBJECT |
1104 SEC_ADS_CONTROL_ACCESS,
1108 if (composite_nomem(v, c)) return;
1112 attrs[i].attid = DRSUAPI_ATTRIBUTE_ntSecurityDescriptor;
1113 attrs[i].value_ctr.security_descriptor.num_values = 1;
1114 attrs[i].value_ctr.security_descriptor.values = vs;
1119 /* objectClass: nTDSDSA */
1121 struct drsuapi_DsAttributeValueObjectClassId *vs;
1122 enum drsuapi_DsObjectClassId *v;
1124 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueObjectClassId, 1);
1125 if (composite_nomem(vs, c)) return;
1127 v = talloc_array(vs, enum drsuapi_DsObjectClassId, 1);
1128 if (composite_nomem(v, c)) return;
1130 /* value for nTDSDSA */
1133 vs[0].objectClassId = &v[0];
1135 attrs[i].attid = DRSUAPI_ATTRIBUTE_objectClass;
1136 attrs[i].value_ctr.object_class_id.num_values = 1;
1137 attrs[i].value_ctr.object_class_id.values = vs;
1142 /* objectCategory: CN=NTDS-DSA,CN=Schema,... */
1144 struct drsuapi_DsAttributeValueDNString *vs;
1145 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1147 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 1);
1148 if (composite_nomem(vs, c)) return;
1150 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 1);
1151 if (composite_nomem(v, c)) return;
1153 /* value for nTDSDSA */
1154 v[0].guid = GUID_zero();
1155 v[0].sid = zero_sid;
1156 v[0].dn = talloc_asprintf(v, "CN=NTDS-DSA,%s",
1157 s->forest.schema_dn_str);
1158 if (composite_nomem(v->dn, c)) return;
1160 vs[0].object = &v[0];
1162 attrs[i].attid = DRSUAPI_ATTRIBUTE_objectCategory;
1163 attrs[i].value_ctr.dn_string.num_values = 1;
1164 attrs[i].value_ctr.dn_string.values = vs;
1169 /* invocationId: random guid */
1171 struct drsuapi_DsAttributeValueGUID *vs;
1174 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueGUID, 1);
1175 if (composite_nomem(vs, c)) return;
1177 v = talloc_array(vs, struct GUID, 1);
1178 if (composite_nomem(v, c)) return;
1180 /* value for nTDSDSA */
1181 v[0] = s->dest_dsa.invocation_id;
1185 attrs[i].attid = DRSUAPI_ATTRIBUTE_invocationId;
1186 attrs[i].value_ctr.guid.num_values = 1;
1187 attrs[i].value_ctr.guid.values = vs;
1192 /* hasMasterNCs: ... */
1194 struct drsuapi_DsAttributeValueDNString *vs;
1195 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1197 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 3);
1198 if (composite_nomem(vs, c)) return;
1200 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 3);
1201 if (composite_nomem(v, c)) return;
1203 v[0].guid = GUID_zero();
1204 v[0].sid = zero_sid;
1205 v[0].dn = s->forest.config_dn_str;
1207 v[1].guid = GUID_zero();
1208 v[1].sid = zero_sid;
1209 v[1].dn = s->domain.dn_str;
1211 v[2].guid = GUID_zero();
1212 v[2].sid = zero_sid;
1213 v[2].dn = s->forest.schema_dn_str;
1215 vs[0].object = &v[0];
1216 vs[1].object = &v[1];
1217 vs[2].object = &v[2];
1219 attrs[i].attid = DRSUAPI_ATTRIBUTE_hasMasterNCs;
1220 attrs[i].value_ctr.dn_string.num_values = 3;
1221 attrs[i].value_ctr.dn_string.values = vs;
1226 /* msDS-hasMasterNCs: ... */
1228 struct drsuapi_DsAttributeValueDNString *vs;
1229 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1231 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 3);
1232 if (composite_nomem(vs, c)) return;
1234 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 3);
1235 if (composite_nomem(v, c)) return;
1237 v[0].guid = GUID_zero();
1238 v[0].sid = zero_sid;
1239 v[0].dn = s->forest.config_dn_str;
1241 v[1].guid = GUID_zero();
1242 v[1].sid = zero_sid;
1243 v[1].dn = s->domain.dn_str;
1245 v[2].guid = GUID_zero();
1246 v[2].sid = zero_sid;
1247 v[2].dn = s->forest.schema_dn_str;
1249 vs[0].object = &v[0];
1250 vs[1].object = &v[1];
1251 vs[2].object = &v[2];
1253 attrs[i].attid = DRSUAPI_ATTRIBUTE_msDS_hasMasterNCs;
1254 attrs[i].value_ctr.dn_string.num_values = 3;
1255 attrs[i].value_ctr.dn_string.values = vs;
1260 /* dMDLocation: CN=Schema,... */
1262 struct drsuapi_DsAttributeValueDNString *vs;
1263 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1265 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 1);
1266 if (composite_nomem(vs, c)) return;
1268 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 1);
1269 if (composite_nomem(v, c)) return;
1271 v[0].guid = GUID_zero();
1272 v[0].sid = zero_sid;
1273 v[0].dn = s->forest.schema_dn_str;
1275 vs[0].object = &v[0];
1277 attrs[i].attid = DRSUAPI_ATTRIBUTE_dMDLocation;
1278 attrs[i].value_ctr.dn_string.num_values = 1;
1279 attrs[i].value_ctr.dn_string.values = vs;
1284 /* msDS-HasDomainNCs: <domain_partition> */
1286 struct drsuapi_DsAttributeValueDNString *vs;
1287 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1289 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 1);
1290 if (composite_nomem(vs, c)) return;
1292 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 1);
1293 if (composite_nomem(v, c)) return;
1295 v[0].guid = GUID_zero();
1296 v[0].sid = zero_sid;
1297 v[0].dn = s->domain.dn_str;
1299 vs[0].object = &v[0];
1301 attrs[i].attid = DRSUAPI_ATTRIBUTE_msDS_HasDomainNCs;
1302 attrs[i].value_ctr.dn_string.num_values = 1;
1303 attrs[i].value_ctr.dn_string.values = vs;
1308 /* msDS-Behavior-Version */
1310 struct drsuapi_DsAttributeValueUINT32 *vs;
1313 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueUINT32, 1);
1314 if (composite_nomem(vs, c)) return;
1316 v = talloc_array(vs, uint32_t, 1);
1317 if (composite_nomem(v, c)) return;
1321 vs[0].value = &v[0];
1323 attrs[i].attid = DRSUAPI_ATTRIBUTE_msDS_Behavior_Version;
1324 attrs[i].value_ctr.uint32.num_values = 1;
1325 attrs[i].value_ctr.uint32.values = vs;
1332 struct drsuapi_DsAttributeValueUINT32 *vs;
1335 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueUINT32, 1);
1336 if (composite_nomem(vs, c)) return;
1338 v = talloc_array(vs, uint32_t, 1);
1339 if (composite_nomem(v, c)) return;
1341 v[0] = SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE;
1343 vs[0].value = &v[0];
1345 attrs[i].attid = DRSUAPI_ATTRIBUTE_systemFlags;
1346 attrs[i].value_ctr.uint32.num_values = 1;
1347 attrs[i].value_ctr.uint32.values = vs;
1352 /* serverReference: ... */
1354 struct drsuapi_DsAttributeValueDNString *vs;
1355 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1357 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 1);
1358 if (composite_nomem(vs, c)) return;
1360 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 1);
1361 if (composite_nomem(v, c)) return;
1363 v[0].guid = GUID_zero();
1364 v[0].sid = zero_sid;
1365 v[0].dn = s->dest_dsa.computer_dn_str;
1367 vs[0].object = &v[0];
1369 attrs[i].attid = DRSUAPI_ATTRIBUTE_serverReference;
1370 attrs[i].value_ctr.dn_string.num_values = 1;
1371 attrs[i].value_ctr.dn_string.values = vs;
1376 /* truncate the attribute list to the attribute count we have filled in */
1379 /* setup request structure */
1380 r->in.bind_handle = &s->drsuapi1.bind_handle;
1382 r->in.req.req2.first_object.next_object = NULL;
1383 r->in.req.req2.first_object.object.identifier = identifier;
1384 r->in.req.req2.first_object.object.unknown1 = 0x00000000;
1385 r->in.req.req2.first_object.object.attribute_ctr.num_attributes = num_attrs;
1386 r->in.req.req2.first_object.object.attribute_ctr.attributes = attrs;
1388 req = dcerpc_drsuapi_DsAddEntry_send(s->drsuapi1.pipe, r, r);
1389 composite_continue_rpc(c, req, becomeDC_drsuapi1_add_entry_recv, s);
1392 static void becomeDC_drsuapi1_add_entry_recv(struct rpc_request *req)
1394 struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
1395 struct libnet_BecomeDC_state);
1396 struct composite_context *c = s->creq;
1397 struct drsuapi_DsAddEntry *r = talloc_get_type(req->ndr.struct_ptr,
1398 struct drsuapi_DsAddEntry);
1400 c->status = dcerpc_ndr_request_recv(req);
1401 if (!composite_is_ok(c)) return;
1403 if (!W_ERROR_IS_OK(r->out.result)) {
1404 composite_error(c, werror_to_ntstatus(r->out.result));
1408 becomeDC_connect_ldap2(s);
1411 static NTSTATUS becomeDC_ldap2_modify_computer(struct libnet_BecomeDC_state *s)
1414 struct ldb_message *msg;
1416 uint32_t user_account_control = UF_SERVER_TRUST_ACCOUNT |
1417 UF_TRUSTED_FOR_DELEGATION;
1419 /* as the value is already as we want it to be, we're done */
1420 if (s->dest_dsa.user_account_control == user_account_control) {
1421 return NT_STATUS_OK;
1424 /* make a 'modify' msg, and only for serverReference */
1425 msg = ldb_msg_new(s);
1426 NT_STATUS_HAVE_NO_MEMORY(msg);
1427 msg->dn = ldb_dn_new(msg, s->ldap2.ldb, s->dest_dsa.computer_dn_str);
1428 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
1430 ret = ldb_msg_add_fmt(msg, "userAccountControl", "%u", user_account_control);
1433 return NT_STATUS_NO_MEMORY;
1436 /* mark all the message elements (should be just one)
1437 as LDB_FLAG_MOD_REPLACE */
1438 for (i=0;i<msg->num_elements;i++) {
1439 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
1442 ret = ldb_modify(s->ldap2.ldb, msg);
1444 if (ret != LDB_SUCCESS) {
1445 return NT_STATUS_LDAP(ret);
1448 s->dest_dsa.user_account_control = user_account_control;
1450 return NT_STATUS_OK;
1453 static NTSTATUS becomeDC_ldap2_move_computer(struct libnet_BecomeDC_state *s)
1456 struct ldb_result *r;
1457 struct ldb_dn *basedn;
1458 struct ldb_dn *old_dn;
1459 struct ldb_dn *new_dn;
1460 static const char *_1_1_attrs[] = {
1465 basedn = ldb_dn_new_fmt(s, s->ldap2.ldb, "<WKGUID=a361b2ffffd211d1aa4b00c04fd7d83a,%s>",
1467 NT_STATUS_HAVE_NO_MEMORY(basedn);
1469 ret = ldb_search(s->ldap2.ldb, basedn, LDB_SCOPE_BASE,
1470 "(objectClass=*)", _1_1_attrs, &r);
1471 talloc_free(basedn);
1472 if (ret != LDB_SUCCESS) {
1473 return NT_STATUS_LDAP(ret);
1474 } else if (r->count != 1) {
1476 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1479 old_dn = ldb_dn_new(r, s->ldap2.ldb, s->dest_dsa.computer_dn_str);
1480 NT_STATUS_HAVE_NO_MEMORY(old_dn);
1482 new_dn = r->msgs[0]->dn;
1484 if (!ldb_dn_add_child_fmt(new_dn, "CN=%s", s->dest_dsa.netbios_name)) {
1486 return NT_STATUS_NO_MEMORY;
1489 if (ldb_dn_compare(old_dn, new_dn) == 0) {
1490 /* we don't need to rename if the old and new dn match */
1492 return NT_STATUS_OK;
1495 ret = ldb_rename(s->ldap2.ldb, old_dn, new_dn);
1497 if (ret != LDB_SUCCESS) {
1498 return NT_STATUS_LDAP(ret);
1501 return NT_STATUS_OK;
1504 static void becomeDC_connect_ldap2(struct libnet_BecomeDC_state *s)
1506 struct composite_context *c = s->creq;
1508 c->status = becomeDC_ldap_connect(s, &s->ldap2);
1509 if (!composite_is_ok(c)) return;
1511 c->status = becomeDC_ldap2_modify_computer(s);
1512 if (!composite_is_ok(c)) return;
1514 c->status = becomeDC_ldap2_move_computer(s);
1515 if (!composite_is_ok(c)) return;
1517 composite_error(c, NT_STATUS_NOT_IMPLEMENTED);
1520 struct composite_context *libnet_BecomeDC_send(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_BecomeDC *r)
1522 struct composite_context *c;
1523 struct libnet_BecomeDC_state *s;
1526 c = composite_create(mem_ctx, ctx->event_ctx);
1527 if (c == NULL) return NULL;
1529 s = talloc_zero(c, struct libnet_BecomeDC_state);
1530 if (composite_nomem(s, c)) return c;
1531 c->private_data = s;
1536 s->domain.dns_name = talloc_strdup(s, r->in.domain_dns_name);
1537 if (composite_nomem(s->domain.dns_name, c)) return c;
1538 s->domain.netbios_name = talloc_strdup(s, r->in.domain_netbios_name);
1539 if (composite_nomem(s->domain.netbios_name, c)) return c;
1540 s->domain.sid = dom_sid_dup(s, r->in.domain_sid);
1541 if (composite_nomem(s->domain.sid, c)) return c;
1543 /* Source DSA input */
1544 s->source_dsa.address = talloc_strdup(s, r->in.source_dsa_address);
1545 if (composite_nomem(s->source_dsa.address, c)) return c;
1547 /* Destination DSA input */
1548 s->dest_dsa.netbios_name= talloc_strdup(s, r->in.dest_dsa_netbios_name);
1549 if (composite_nomem(s->dest_dsa.netbios_name, c)) return c;
1551 /* Destination DSA dns_name construction */
1552 tmp_name = strlower_talloc(s, s->dest_dsa.netbios_name);
1553 if (composite_nomem(tmp_name, c)) return c;
1554 s->dest_dsa.dns_name = talloc_asprintf_append(tmp_name, ".%s",
1555 s->domain.dns_name);
1556 if (composite_nomem(s->dest_dsa.dns_name, c)) return c;
1558 becomeDC_send_cldap(s);
1562 NTSTATUS libnet_BecomeDC_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, struct libnet_BecomeDC *r)
1566 status = composite_wait(c);
1568 ZERO_STRUCT(r->out);
1574 NTSTATUS libnet_BecomeDC(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_BecomeDC *r)
1577 struct composite_context *c;
1578 c = libnet_BecomeDC_send(ctx, mem_ctx, r);
1579 status = libnet_BecomeDC_recv(c, mem_ctx, r);