r20073: update the computer_dn_str after ldb_rename()
[jelmer/samba4-debian.git] / source / libnet / libnet_become_dc.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Copyright (C) Stefan Metzmacher      2006
5
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.
10
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.
15
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.
19 */
20
21 #include "includes.h"
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
33 struct libnet_BecomeDC_state {
34         struct composite_context *creq;
35
36         struct libnet_context *libnet;
37
38         struct dom_sid zero_sid;
39
40         struct {
41                 struct cldap_socket *sock;
42                 struct cldap_netlogon io;
43                 struct nbt_cldap_netlogon_5 netlogon5;
44         } cldap;
45
46         struct becomeDC_ldap {
47                 struct ldb_context *ldb;
48                 const struct ldb_message *rootdse;
49         } ldap1, ldap2;
50
51         struct becomeDC_drsuapi {
52                 struct libnet_BecomeDC_state *s;
53                 struct dcerpc_binding *binding;
54                 struct dcerpc_pipe *pipe;
55                 struct drsuapi_DsBind bind_r;
56                 struct GUID bind_guid;
57                 struct drsuapi_DsBindInfoCtr bind_info_ctr;
58                 struct drsuapi_DsBindInfo28 local_info28;
59                 struct drsuapi_DsBindInfo28 remote_info28;
60                 struct policy_handle bind_handle;
61         } drsuapi1, drsuapi2, drsuapi3;
62
63         struct {
64                 /* input */
65                 const char *dns_name;
66                 const char *netbios_name;
67                 const struct dom_sid *sid;
68
69                 /* constructed */
70                 struct GUID guid;
71                 const char *dn_str;
72         } domain;
73
74         struct {
75                 /* constructed */
76                 const char *dns_name;
77                 const char *root_dn_str;
78                 const char *config_dn_str;
79                 const char *schema_dn_str;
80         } forest;
81
82         struct {
83                 /* input */
84                 const char *address;
85
86                 /* constructed */
87                 const char *dns_name;
88                 const char *netbios_name;
89                 const char *site_name;
90                 const char *server_dn_str;
91                 const char *ntds_dn_str;
92         } source_dsa;
93
94         struct {
95                 /* input */
96                 const char *netbios_name;
97
98                 /* constructed */
99                 const char *dns_name;
100                 const char *site_name;
101                 struct GUID site_guid;
102                 const char *computer_dn_str;
103                 const char *server_dn_str;
104                 const char *ntds_dn_str;
105                 struct GUID ntds_guid;
106                 struct GUID invocation_id;
107                 uint32_t user_account_control;
108         } dest_dsa;
109
110         struct {
111                 uint32_t domain_behavior_version;
112                 uint32_t config_behavior_version;
113                 uint32_t schema_object_version;
114                 uint32_t w2k3_update_revision;
115         } ads_options;
116
117         struct becomeDC_fsmo {
118                 const char *dns_name;
119                 const char *server_dn_str;
120                 const char *ntds_dn_str;
121                 struct GUID ntds_guid;
122         } infrastructure_fsmo;
123
124         struct becomeDC_fsmo rid_manager_fsmo;
125 };
126
127 static void becomeDC_connect_ldap1(struct libnet_BecomeDC_state *s);
128
129 static void becomeDC_recv_cldap(struct cldap_request *req)
130 {
131         struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
132                                           struct libnet_BecomeDC_state);
133         struct composite_context *c = s->creq;
134
135         c->status = cldap_netlogon_recv(req, s, &s->cldap.io);
136         if (!composite_is_ok(c)) return;
137
138         s->cldap.netlogon5 = s->cldap.io.out.netlogon.logon5;
139
140         s->domain.dns_name              = s->cldap.netlogon5.dns_domain;
141         s->domain.netbios_name          = s->cldap.netlogon5.domain;
142         s->domain.guid                  = s->cldap.netlogon5.domain_uuid;
143
144         s->forest.dns_name              = s->cldap.netlogon5.forest;
145
146         s->source_dsa.dns_name          = s->cldap.netlogon5.pdc_dns_name;
147         s->source_dsa.netbios_name      = s->cldap.netlogon5.pdc_name;
148         s->source_dsa.site_name         = s->cldap.netlogon5.server_site;
149
150         s->dest_dsa.site_name           = s->cldap.netlogon5.client_site;
151
152         becomeDC_connect_ldap1(s);
153 }
154
155 static void becomeDC_send_cldap(struct libnet_BecomeDC_state *s)
156 {
157         struct composite_context *c = s->creq;
158         struct cldap_request *req;
159
160         s->cldap.io.in.dest_address     = s->source_dsa.address;
161         s->cldap.io.in.realm            = s->domain.dns_name;
162         s->cldap.io.in.host             = s->dest_dsa.netbios_name;
163         s->cldap.io.in.user             = NULL;
164         s->cldap.io.in.domain_guid      = NULL;
165         s->cldap.io.in.domain_sid       = NULL;
166         s->cldap.io.in.acct_control     = -1;
167         s->cldap.io.in.version          = 6;
168
169         s->cldap.sock = cldap_socket_init(s, s->libnet->event_ctx);
170         if (composite_nomem(s->cldap.sock, c)) return;
171
172         req = cldap_netlogon_send(s->cldap.sock, &s->cldap.io);
173         if (composite_nomem(req, c)) return;
174         req->async.fn           = becomeDC_recv_cldap;
175         req->async.private      = s;
176 }
177
178 static NTSTATUS becomeDC_ldap_connect(struct libnet_BecomeDC_state *s, struct becomeDC_ldap *ldap)
179 {
180         char *url;
181
182         url = talloc_asprintf(s, "ldap://%s/", s->source_dsa.dns_name);
183         NT_STATUS_HAVE_NO_MEMORY(url);
184
185         ldap->ldb = ldb_wrap_connect(s, url,
186                                      NULL,
187                                      s->libnet->cred,
188                                      0, NULL);
189         talloc_free(url);
190         if (ldap->ldb == NULL) {
191                 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
192         }
193
194         return NT_STATUS_OK;
195 }
196
197 static NTSTATUS becomeDC_ldap1_rootdse(struct libnet_BecomeDC_state *s)
198 {
199         int ret;
200         struct ldb_result *r;
201         struct ldb_dn *basedn;
202         static const char *attrs[] = {
203                 "*",
204                 NULL
205         };
206
207         basedn = ldb_dn_new(s, s->ldap1.ldb, NULL);
208         NT_STATUS_HAVE_NO_MEMORY(basedn);
209
210         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE, 
211                          "(objectClass=*)", attrs, &r);
212         talloc_free(basedn);
213         if (ret != LDB_SUCCESS) {
214                 return NT_STATUS_LDAP(ret);
215         } else if (r->count != 1) {
216                 talloc_free(r);
217                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
218         }
219         talloc_steal(s, r);
220
221         s->ldap1.rootdse = r->msgs[0];
222
223         s->domain.dn_str        = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "defaultNamingContext", NULL);
224         if (!s->domain.dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
225
226         s->forest.root_dn_str   = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "rootDomainNamingContext", NULL);
227         if (!s->forest.root_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
228         s->forest.config_dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "configurationNamingContext", NULL);
229         if (!s->forest.config_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
230         s->forest.schema_dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "schemaNamingContext", NULL);
231         if (!s->forest.schema_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
232
233         s->source_dsa.server_dn_str     = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "serverName", NULL);
234         if (!s->source_dsa.server_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
235         s->source_dsa.ntds_dn_str       = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "dsServiceName", NULL);
236         if (!s->source_dsa.ntds_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
237
238         return NT_STATUS_OK;
239 }
240
241 static NTSTATUS becomeDC_ldap1_config_behavior_version(struct libnet_BecomeDC_state *s)
242 {
243         int ret;
244         struct ldb_result *r;
245         struct ldb_dn *basedn;
246         static const char *attrs[] = {
247                 "msDs-Behavior-Version",
248                 NULL
249         };
250
251         basedn = ldb_dn_new(s, s->ldap1.ldb, s->forest.config_dn_str);
252         NT_STATUS_HAVE_NO_MEMORY(basedn);
253
254         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_ONELEVEL,
255                          "(cn=Partitions)", attrs, &r);
256         talloc_free(basedn);
257         if (ret != LDB_SUCCESS) {
258                 return NT_STATUS_LDAP(ret);
259         } else if (r->count != 1) {
260                 talloc_free(r);
261                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
262         }
263
264         s->ads_options.config_behavior_version = ldb_msg_find_attr_as_uint(r->msgs[0], "msDs-Behavior-Version", 0);
265
266         talloc_free(r);
267         return NT_STATUS_OK;
268 }
269
270 static NTSTATUS becomeDC_ldap1_domain_behavior_version(struct libnet_BecomeDC_state *s)
271 {
272         int ret;
273         struct ldb_result *r;
274         struct ldb_dn *basedn;
275         static const char *attrs[] = {
276                 "msDs-Behavior-Version",
277                 NULL
278         };
279
280         basedn = ldb_dn_new(s, s->ldap1.ldb, s->domain.dn_str);
281         NT_STATUS_HAVE_NO_MEMORY(basedn);
282
283         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
284                          "(objectClass=*)", attrs, &r);
285         talloc_free(basedn);
286         if (ret != LDB_SUCCESS) {
287                 return NT_STATUS_LDAP(ret);
288         } else if (r->count != 1) {
289                 talloc_free(r);
290                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
291         }
292
293         s->ads_options.domain_behavior_version = ldb_msg_find_attr_as_uint(r->msgs[0], "msDs-Behavior-Version", 0);
294
295         talloc_free(r);
296         return NT_STATUS_OK;
297 }
298
299 static NTSTATUS becomeDC_ldap1_schema_object_version(struct libnet_BecomeDC_state *s)
300 {
301         int ret;
302         struct ldb_result *r;
303         struct ldb_dn *basedn;
304         static const char *attrs[] = {
305                 "objectVersion",
306                 NULL
307         };
308
309         basedn = ldb_dn_new(s, s->ldap1.ldb, s->forest.schema_dn_str);
310         NT_STATUS_HAVE_NO_MEMORY(basedn);
311
312         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
313                          "(objectClass=*)", attrs, &r);
314         talloc_free(basedn);
315         if (ret != LDB_SUCCESS) {
316                 return NT_STATUS_LDAP(ret);
317         } else if (r->count != 1) {
318                 talloc_free(r);
319                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
320         }
321
322         s->ads_options.schema_object_version = ldb_msg_find_attr_as_uint(r->msgs[0], "objectVersion", 0);
323
324         talloc_free(r);
325         return NT_STATUS_OK;
326 }
327
328 static NTSTATUS becomeDC_ldap1_w2k3_update_revision(struct libnet_BecomeDC_state *s)
329 {
330         int ret;
331         struct ldb_result *r;
332         struct ldb_dn *basedn;
333         static const char *attrs[] = {
334                 "revision",
335                 NULL
336         };
337
338         basedn = ldb_dn_new_fmt(s, s->ldap1.ldb, "CN=Windows2003Update,CN=DomainUpdates,CN=System,%s",
339                                 s->domain.dn_str);
340         NT_STATUS_HAVE_NO_MEMORY(basedn);
341
342         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
343                          "(objectClass=*)", attrs, &r);
344         talloc_free(basedn);
345         if (ret != LDB_SUCCESS) {
346                 return NT_STATUS_LDAP(ret);
347         } else if (r->count != 1) {
348                 talloc_free(r);
349                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
350         }
351
352         s->ads_options.w2k3_update_revision = ldb_msg_find_attr_as_uint(r->msgs[0], "revision", 0);
353
354         talloc_free(r);
355         return NT_STATUS_OK;
356 }
357
358 static NTSTATUS becomeDC_ldap1_infrastructure_fsmo(struct libnet_BecomeDC_state *s)
359 {
360         int ret;
361         struct ldb_result *r;
362         struct ldb_dn *basedn;
363         struct ldb_dn *ntds_dn;
364         struct ldb_dn *server_dn;
365         static const char *_1_1_attrs[] = {
366                 "1.1",
367                 NULL
368         };
369         static const char *fsmo_attrs[] = {
370                 "fSMORoleOwner",
371                 NULL
372         };
373         static const char *dns_attrs[] = {
374                 "dnsHostName",
375                 NULL
376         };
377         static const char *guid_attrs[] = {
378                 "objectGUID",
379                 NULL
380         };
381
382         basedn = ldb_dn_new_fmt(s, s->ldap1.ldb, "<WKGUID=2fbac1870ade11d297c400c04fd8d5cd,%s>",
383                                 s->domain.dn_str);
384         NT_STATUS_HAVE_NO_MEMORY(basedn);
385
386         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
387                          "(objectClass=*)", _1_1_attrs, &r);
388         talloc_free(basedn);
389         if (ret != LDB_SUCCESS) {
390                 return NT_STATUS_LDAP(ret);
391         } else if (r->count != 1) {
392                 talloc_free(r);
393                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
394         }
395
396         basedn = talloc_steal(s, r->msgs[0]->dn);
397         talloc_free(r);
398
399         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
400                          "(objectClass=*)", fsmo_attrs, &r);
401         talloc_free(basedn);
402         if (ret != LDB_SUCCESS) {
403                 return NT_STATUS_LDAP(ret);
404         } else if (r->count != 1) {
405                 talloc_free(r);
406                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
407         }
408
409         s->infrastructure_fsmo.ntds_dn_str      = samdb_result_string(r->msgs[0], "fSMORoleOwner", NULL);
410         if (!s->infrastructure_fsmo.ntds_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
411         talloc_steal(s, s->infrastructure_fsmo.ntds_dn_str);
412
413         talloc_free(r);
414
415         ntds_dn = ldb_dn_new(s, s->ldap1.ldb, s->infrastructure_fsmo.ntds_dn_str);
416         NT_STATUS_HAVE_NO_MEMORY(ntds_dn);
417
418         server_dn = ldb_dn_get_parent(s, ntds_dn);
419         NT_STATUS_HAVE_NO_MEMORY(server_dn);
420
421         s->infrastructure_fsmo.server_dn_str = ldb_dn_alloc_linearized(s, server_dn);
422         NT_STATUS_HAVE_NO_MEMORY(s->infrastructure_fsmo.server_dn_str);
423
424         ret = ldb_search(s->ldap1.ldb, server_dn, LDB_SCOPE_BASE,
425                          "(objectClass=*)", dns_attrs, &r);
426         if (ret != LDB_SUCCESS) {
427                 return NT_STATUS_LDAP(ret);
428         } else if (r->count != 1) {
429                 talloc_free(r);
430                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
431         }
432
433         s->infrastructure_fsmo.dns_name = samdb_result_string(r->msgs[0], "dnsHostName", NULL);
434         if (!s->infrastructure_fsmo.dns_name) return NT_STATUS_INVALID_NETWORK_RESPONSE;
435         talloc_steal(s, s->infrastructure_fsmo.dns_name);
436
437         talloc_free(r);
438
439         ret = ldb_search(s->ldap1.ldb, ntds_dn, LDB_SCOPE_BASE,
440                          "(objectClass=*)", guid_attrs, &r);
441         if (ret != LDB_SUCCESS) {
442                 return NT_STATUS_LDAP(ret);
443         } else if (r->count != 1) {
444                 talloc_free(r);
445                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
446         }
447
448         s->infrastructure_fsmo.ntds_guid = samdb_result_guid(r->msgs[0], "objectGUID");
449
450         talloc_free(r);
451
452         return NT_STATUS_OK;
453 }
454
455 static NTSTATUS becomeDC_ldap1_rid_manager_fsmo(struct libnet_BecomeDC_state *s)
456 {
457         int ret;
458         struct ldb_result *r;
459         struct ldb_dn *basedn;
460         const char *reference_dn_str;
461         struct ldb_dn *ntds_dn;
462         struct ldb_dn *server_dn;
463         static const char *rid_attrs[] = {
464                 "rIDManagerReference",
465                 NULL
466         };
467         static const char *fsmo_attrs[] = {
468                 "fSMORoleOwner",
469                 NULL
470         };
471         static const char *dns_attrs[] = {
472                 "dnsHostName",
473                 NULL
474         };
475         static const char *guid_attrs[] = {
476                 "objectGUID",
477                 NULL
478         };
479
480         basedn = ldb_dn_new(s, s->ldap1.ldb, s->domain.dn_str);
481         NT_STATUS_HAVE_NO_MEMORY(basedn);
482
483         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
484                          "(objectClass=*)", rid_attrs, &r);
485         talloc_free(basedn);
486         if (ret != LDB_SUCCESS) {
487                 return NT_STATUS_LDAP(ret);
488         } else if (r->count != 1) {
489                 talloc_free(r);
490                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
491         }
492
493         reference_dn_str        = samdb_result_string(r->msgs[0], "rIDManagerReference", NULL);
494         if (!reference_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
495
496         basedn = ldb_dn_new(s, s->ldap1.ldb, reference_dn_str);
497         NT_STATUS_HAVE_NO_MEMORY(basedn);
498
499         talloc_free(r);
500
501         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
502                          "(objectClass=*)", fsmo_attrs, &r);
503         talloc_free(basedn);
504         if (ret != LDB_SUCCESS) {
505                 return NT_STATUS_LDAP(ret);
506         } else if (r->count != 1) {
507                 talloc_free(r);
508                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
509         }
510
511         s->rid_manager_fsmo.ntds_dn_str = samdb_result_string(r->msgs[0], "fSMORoleOwner", NULL);
512         if (!s->rid_manager_fsmo.ntds_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
513         talloc_steal(s, s->rid_manager_fsmo.ntds_dn_str);
514
515         talloc_free(r);
516
517         ntds_dn = ldb_dn_new(s, s->ldap1.ldb, s->rid_manager_fsmo.ntds_dn_str);
518         NT_STATUS_HAVE_NO_MEMORY(ntds_dn);
519
520         server_dn = ldb_dn_get_parent(s, ntds_dn);
521         NT_STATUS_HAVE_NO_MEMORY(server_dn);
522
523         s->rid_manager_fsmo.server_dn_str = ldb_dn_alloc_linearized(s, server_dn);
524         NT_STATUS_HAVE_NO_MEMORY(s->rid_manager_fsmo.server_dn_str);
525
526         ret = ldb_search(s->ldap1.ldb, server_dn, LDB_SCOPE_BASE,
527                          "(objectClass=*)", dns_attrs, &r);
528         if (ret != LDB_SUCCESS) {
529                 return NT_STATUS_LDAP(ret);
530         } else if (r->count != 1) {
531                 talloc_free(r);
532                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
533         }
534
535         s->rid_manager_fsmo.dns_name    = samdb_result_string(r->msgs[0], "dnsHostName", NULL);
536         if (!s->rid_manager_fsmo.dns_name) return NT_STATUS_INVALID_NETWORK_RESPONSE;
537         talloc_steal(s, s->rid_manager_fsmo.dns_name);
538
539         talloc_free(r);
540
541         ret = ldb_search(s->ldap1.ldb, ntds_dn, LDB_SCOPE_BASE,
542                          "(objectClass=*)", guid_attrs, &r);
543         if (ret != LDB_SUCCESS) {
544                 return NT_STATUS_LDAP(ret);
545         } else if (r->count != 1) {
546                 talloc_free(r);
547                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
548         }
549
550         s->rid_manager_fsmo.ntds_guid = samdb_result_guid(r->msgs[0], "objectGUID");
551
552         talloc_free(r);
553
554         return NT_STATUS_OK;
555 }
556
557 static NTSTATUS becomeDC_ldap1_site_object(struct libnet_BecomeDC_state *s)
558 {
559         int ret;
560         struct ldb_result *r;
561         struct ldb_dn *basedn;
562
563         basedn = ldb_dn_new_fmt(s, s->ldap1.ldb, "CN=%s,CN=Sites,%s",
564                                 s->dest_dsa.site_name,
565                                 s->forest.config_dn_str);
566         NT_STATUS_HAVE_NO_MEMORY(basedn);
567
568         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE, 
569                          "(objectClass=*)", NULL, &r);
570         talloc_free(basedn);
571         if (ret != LDB_SUCCESS) {
572                 return NT_STATUS_LDAP(ret);
573         } else if (r->count != 1) {
574                 talloc_free(r);
575                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
576         }
577
578         s->dest_dsa.site_guid = samdb_result_guid(r->msgs[0], "objectGUID");
579
580         talloc_free(r);
581         return NT_STATUS_OK;
582 }
583
584 static NTSTATUS becomeDC_ldap1_computer_object(struct libnet_BecomeDC_state *s)
585 {
586         int ret;
587         struct ldb_result *r;
588         struct ldb_dn *basedn;
589         char *filter;
590         static const char *attrs[] = {
591                 "distinguishedName",
592                 "userAccountControl",
593                 NULL
594         };
595
596         basedn = ldb_dn_new(s, s->ldap1.ldb, s->domain.dn_str);
597         NT_STATUS_HAVE_NO_MEMORY(basedn);
598
599         filter = talloc_asprintf(basedn, "(&(|(objectClass=user)(objectClass=computer))(sAMAccountName=%s$))",
600                                  s->dest_dsa.netbios_name);
601         NT_STATUS_HAVE_NO_MEMORY(filter);
602
603         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_SUBTREE, 
604                          filter, attrs, &r);
605         talloc_free(basedn);
606         if (ret != LDB_SUCCESS) {
607                 return NT_STATUS_LDAP(ret);
608         } else if (r->count != 1) {
609                 talloc_free(r);
610                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
611         }
612
613         s->dest_dsa.computer_dn_str     = samdb_result_string(r->msgs[0], "distinguishedName", NULL);
614         if (!s->dest_dsa.computer_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
615         talloc_steal(s, s->dest_dsa.computer_dn_str);
616
617         s->dest_dsa.user_account_control = samdb_result_uint(r->msgs[0], "userAccountControl", 0);
618
619         talloc_free(r);
620         return NT_STATUS_OK;
621 }
622
623 static NTSTATUS becomeDC_ldap1_server_object_1(struct libnet_BecomeDC_state *s)
624 {
625         int ret;
626         struct ldb_result *r;
627         struct ldb_dn *basedn;
628         const char *server_reference_dn_str;
629         struct ldb_dn *server_reference_dn;
630         struct ldb_dn *computer_dn;
631
632         basedn = ldb_dn_new_fmt(s, s->ldap1.ldb, "CN=%s,CN=Servers,CN=%s,CN=Sites,%s",
633                                 s->dest_dsa.netbios_name,
634                                 s->dest_dsa.site_name,
635                                 s->forest.config_dn_str);
636         NT_STATUS_HAVE_NO_MEMORY(basedn);
637
638         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE, 
639                          "(objectClass=*)", NULL, &r);
640         talloc_free(basedn);
641         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
642                 /* if the object doesn't exist, we'll create it later */
643                 return NT_STATUS_OK;
644         } else if (ret != LDB_SUCCESS) {
645                 return NT_STATUS_LDAP(ret);
646         } else if (r->count != 1) {
647                 talloc_free(r);
648                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
649         }
650
651         server_reference_dn_str = samdb_result_string(r->msgs[0], "serverReference", NULL);
652         if (server_reference_dn_str) {
653                 server_reference_dn     = ldb_dn_new(r, s->ldap1.ldb, server_reference_dn_str);
654                 NT_STATUS_HAVE_NO_MEMORY(server_reference_dn);
655
656                 computer_dn             = ldb_dn_new(r, s->ldap1.ldb, s->dest_dsa.computer_dn_str);
657                 NT_STATUS_HAVE_NO_MEMORY(computer_dn);
658
659                 /*
660                  * if the server object belongs to another DC in another domain in the forest,
661                  * we should not touch this object!
662                  */
663                 if (ldb_dn_compare(computer_dn, server_reference_dn) != 0) {
664                         talloc_free(r);
665                         return NT_STATUS_OBJECT_NAME_COLLISION;
666                 }
667         }
668
669         /* if the server object is already for the dest_dsa, then we don't need to create it */
670         s->dest_dsa.server_dn_str       = samdb_result_string(r->msgs[0], "distinguishedName", NULL);
671         if (!s->dest_dsa.server_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
672         talloc_steal(s, s->dest_dsa.server_dn_str);
673
674         talloc_free(r);
675         return NT_STATUS_OK;
676 }
677
678 static NTSTATUS becomeDC_ldap1_server_object_2(struct libnet_BecomeDC_state *s)
679 {
680         int ret;
681         struct ldb_result *r;
682         struct ldb_dn *basedn;
683         const char *server_reference_bl_dn_str;
684         static const char *attrs[] = {
685                 "serverReferenceBL",
686                 NULL
687         };
688
689         /* if the server_dn_str has a valid value, we skip this lookup */
690         if (s->dest_dsa.server_dn_str) return NT_STATUS_OK;
691
692         basedn = ldb_dn_new(s, s->ldap1.ldb, s->dest_dsa.computer_dn_str);
693         NT_STATUS_HAVE_NO_MEMORY(basedn);
694
695         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE, 
696                          "(objectClass=*)", attrs, &r);
697         talloc_free(basedn);
698         if (ret != LDB_SUCCESS) {
699                 return NT_STATUS_LDAP(ret);
700         } else if (r->count != 1) {
701                 talloc_free(r);
702                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
703         }
704
705         server_reference_bl_dn_str = samdb_result_string(r->msgs[0], "serverReferenceBL", NULL);
706         if (!server_reference_bl_dn_str) {
707                 /* if no back link is present, we're done for this function */
708                 talloc_free(r);
709                 return NT_STATUS_OK;
710         }
711
712         /* if the server object is already for the dest_dsa, then we don't need to create it */
713         s->dest_dsa.server_dn_str       = samdb_result_string(r->msgs[0], "serverReferenceBL", NULL);
714         if (s->dest_dsa.server_dn_str) {
715                 /* if a back link is present, we know that the server object is present */
716                 talloc_steal(s, s->dest_dsa.server_dn_str);
717         }
718
719         talloc_free(r);
720         return NT_STATUS_OK;
721 }
722
723 static NTSTATUS becomeDC_ldap1_server_object_add(struct libnet_BecomeDC_state *s)
724 {
725         int ret;
726         struct ldb_message *msg;
727         char *server_dn_str;
728
729         /* if the server_dn_str has a valid value, we skip this lookup */
730         if (s->dest_dsa.server_dn_str) return NT_STATUS_OK;
731
732         msg = ldb_msg_new(s);
733         NT_STATUS_HAVE_NO_MEMORY(msg);
734
735         msg->dn = ldb_dn_new_fmt(msg, s->ldap1.ldb, "CN=%s,CN=Servers,CN=%s,CN=Sites,%s",
736                                  s->dest_dsa.netbios_name,
737                                  s->dest_dsa.site_name,
738                                  s->forest.config_dn_str);
739         NT_STATUS_HAVE_NO_MEMORY(msg->dn);
740
741         ret = ldb_msg_add_string(msg, "objectClass", "server");
742         if (ret != 0) {
743                 talloc_free(msg);
744                 return NT_STATUS_NO_MEMORY;
745         }
746         ret = ldb_msg_add_string(msg, "systemFlags", "50000000");
747         if (ret != 0) {
748                 talloc_free(msg);
749                 return NT_STATUS_NO_MEMORY;
750         }
751         ret = ldb_msg_add_string(msg, "serverReference", s->dest_dsa.computer_dn_str);
752         if (ret != 0) {
753                 talloc_free(msg);
754                 return NT_STATUS_NO_MEMORY;
755         }
756
757         server_dn_str = ldb_dn_alloc_linearized(s, msg->dn);
758         NT_STATUS_HAVE_NO_MEMORY(server_dn_str);
759
760         ret = ldb_add(s->ldap1.ldb, msg);
761         talloc_free(msg);
762         if (ret != LDB_SUCCESS) {
763                 talloc_free(server_dn_str);
764                 return NT_STATUS_LDAP(ret);
765         }
766
767         s->dest_dsa.server_dn_str = server_dn_str;
768
769         return NT_STATUS_OK;
770 }
771
772 static NTSTATUS becomeDC_ldap1_server_object_modify(struct libnet_BecomeDC_state *s)
773 {
774         int ret;
775         struct ldb_message *msg;
776         uint32_t i;
777
778         /* make a 'modify' msg, and only for serverReference */
779         msg = ldb_msg_new(s);
780         NT_STATUS_HAVE_NO_MEMORY(msg);
781         msg->dn = ldb_dn_new(msg, s->ldap1.ldb, s->dest_dsa.server_dn_str);
782         NT_STATUS_HAVE_NO_MEMORY(msg->dn);
783
784         ret = ldb_msg_add_string(msg, "serverReference", s->dest_dsa.computer_dn_str);
785         if (ret != 0) {
786                 talloc_free(msg);
787                 return NT_STATUS_NO_MEMORY;
788         }
789
790         /* mark all the message elements (should be just one)
791            as LDB_FLAG_MOD_ADD */
792         for (i=0;i<msg->num_elements;i++) {
793                 msg->elements[i].flags = LDB_FLAG_MOD_ADD;
794         }
795
796         ret = ldb_modify(s->ldap1.ldb, msg);
797         if (ret == LDB_SUCCESS) {
798                 talloc_free(msg);
799                 return NT_STATUS_OK;
800         } else if (ret == LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) {
801                 /* retry with LDB_FLAG_MOD_REPLACE */
802         } else {
803                 talloc_free(msg);
804                 return NT_STATUS_LDAP(ret);
805         }
806
807         /* mark all the message elements (should be just one)
808            as LDB_FLAG_MOD_REPLACE */
809         for (i=0;i<msg->num_elements;i++) {
810                 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
811         }
812
813         ret = ldb_modify(s->ldap1.ldb, msg);
814         talloc_free(msg);
815         if (ret != LDB_SUCCESS) {
816                 return NT_STATUS_LDAP(ret);
817         }
818
819         return NT_STATUS_OK;
820 }
821
822 static void becomeDC_drsuapi_connect_send(struct libnet_BecomeDC_state *s,
823                                           struct becomeDC_drsuapi *drsuapi,
824                                           void (*recv_fn)(struct composite_context *req));
825 static void becomeDC_drsuapi1_connect_recv(struct composite_context *req);
826 static void becomeDC_connect_ldap2(struct libnet_BecomeDC_state *s);
827
828 static void becomeDC_connect_ldap1(struct libnet_BecomeDC_state *s)
829 {
830         struct composite_context *c = s->creq;
831
832         c->status = becomeDC_ldap_connect(s, &s->ldap1);
833         if (!composite_is_ok(c)) return;
834
835         c->status = becomeDC_ldap1_rootdse(s);
836         if (!composite_is_ok(c)) return;
837
838         c->status = becomeDC_ldap1_config_behavior_version(s);
839         if (!composite_is_ok(c)) return;
840
841         c->status = becomeDC_ldap1_domain_behavior_version(s);
842         if (!composite_is_ok(c)) return;
843
844         c->status = becomeDC_ldap1_schema_object_version(s);
845         if (!composite_is_ok(c)) return;
846
847         c->status = becomeDC_ldap1_w2k3_update_revision(s);
848         if (!composite_is_ok(c)) return;
849
850         c->status = becomeDC_ldap1_infrastructure_fsmo(s);
851         if (!composite_is_ok(c)) return;
852
853         c->status = becomeDC_ldap1_rid_manager_fsmo(s);
854         if (!composite_is_ok(c)) return;
855
856         c->status = becomeDC_ldap1_site_object(s);
857         if (!composite_is_ok(c)) return;
858
859         c->status = becomeDC_ldap1_computer_object(s);
860         if (!composite_is_ok(c)) return;
861
862         c->status = becomeDC_ldap1_server_object_1(s);
863         if (!composite_is_ok(c)) return;
864
865         c->status = becomeDC_ldap1_server_object_2(s);
866         if (!composite_is_ok(c)) return;
867
868         c->status = becomeDC_ldap1_server_object_add(s);
869         if (!composite_is_ok(c)) return;
870
871         c->status = becomeDC_ldap1_server_object_modify(s);
872         if (!composite_is_ok(c)) return;
873
874         becomeDC_drsuapi_connect_send(s, &s->drsuapi1, becomeDC_drsuapi1_connect_recv);
875 }
876
877 static void becomeDC_drsuapi_connect_send(struct libnet_BecomeDC_state *s,
878                                           struct becomeDC_drsuapi *drsuapi,
879                                           void (*recv_fn)(struct composite_context *req))
880 {
881         struct composite_context *c = s->creq;
882         struct composite_context *creq;
883         char *binding_str;
884
885         drsuapi->s = s;
886
887         if (!drsuapi->binding) {
888                 binding_str = talloc_asprintf(s, "ncacn_ip_tcp:%s[krb5,seal]", s->source_dsa.dns_name);
889                 if (composite_nomem(binding_str, c)) return;
890
891                 c->status = dcerpc_parse_binding(s, binding_str, &drsuapi->binding);
892                 talloc_free(binding_str);
893                 if (!composite_is_ok(c)) return;
894         }
895
896         creq = dcerpc_pipe_connect_b_send(s, drsuapi->binding, &dcerpc_table_drsuapi,
897                                           s->libnet->cred, s->libnet->event_ctx);
898         composite_continue(c, creq, recv_fn, s);
899 }
900
901 static void becomeDC_drsuapi_bind_send(struct libnet_BecomeDC_state *s,
902                                        struct becomeDC_drsuapi *drsuapi,
903                                        void (*recv_fn)(struct rpc_request *req));
904 static void becomeDC_drsuapi1_bind_recv(struct rpc_request *req);
905
906 static void becomeDC_drsuapi1_connect_recv(struct composite_context *req)
907 {
908         struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
909                                           struct libnet_BecomeDC_state);
910         struct composite_context *c = s->creq;
911
912         c->status = dcerpc_pipe_connect_b_recv(req, s, &s->drsuapi1.pipe);
913         if (!composite_is_ok(c)) return;
914
915         becomeDC_drsuapi_bind_send(s, &s->drsuapi1, becomeDC_drsuapi1_bind_recv);
916 }
917
918 static void becomeDC_drsuapi_bind_send(struct libnet_BecomeDC_state *s,
919                                        struct becomeDC_drsuapi *drsuapi,
920                                        void (*recv_fn)(struct rpc_request *req))
921 {
922         struct composite_context *c = s->creq;
923         struct rpc_request *req;
924         struct drsuapi_DsBindInfo28 *bind_info28;
925
926         GUID_from_string(DRSUAPI_DS_BIND_GUID_W2K3, &drsuapi->bind_guid);
927
928         bind_info28                             = &drsuapi->local_info28;
929         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_BASE;
930         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION;
931         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI;
932         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2;
933         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS;
934         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1;
935         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION;
936         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE;
937         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2;
938         if (s->ads_options.domain_behavior_version == 2) {
939                 /* TODO: find out how this is really triggered! */
940                 bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION;
941         }
942         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2;
943         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD;
944         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND;
945         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO;
946         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION;
947         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01;
948         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP;
949         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY;
950         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3;
951         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_00100000;
952         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2;
953         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6;
954         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS;
955         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8;
956         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5;
957         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6;
958         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3;
959         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7;
960         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT;
961 #if 0 /* we don't support XPRESS compression yet */
962         bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS;
963 #endif
964         bind_info28->site_guid                  = s->dest_dsa.site_guid;
965         if (s->ads_options.domain_behavior_version == 2) {
966                 /* TODO: find out how this is really triggered! */
967                 bind_info28->u1                         = 528;
968         } else {
969                 bind_info28->u1                         = 516;
970         }
971         bind_info28->repl_epoch                 = 0;
972
973         drsuapi->bind_info_ctr.length           = 28;
974         drsuapi->bind_info_ctr.info.info28      = *bind_info28;
975
976         drsuapi->bind_r.in.bind_guid = &drsuapi->bind_guid;
977         drsuapi->bind_r.in.bind_info = &drsuapi->bind_info_ctr;
978         drsuapi->bind_r.out.bind_handle = &drsuapi->bind_handle;
979
980         req = dcerpc_drsuapi_DsBind_send(drsuapi->pipe, s, &drsuapi->bind_r);
981         composite_continue_rpc(c, req, recv_fn, s);
982 }
983
984 static WERROR becomeDC_drsuapi_bind_recv(struct libnet_BecomeDC_state *s,
985                                          struct becomeDC_drsuapi *drsuapi)
986 {
987         if (!W_ERROR_IS_OK(drsuapi->bind_r.out.result)) {
988                 return drsuapi->bind_r.out.result;
989         }
990
991         ZERO_STRUCT(drsuapi->remote_info28);
992         if (drsuapi->bind_r.out.bind_info) {
993                 switch (drsuapi->bind_r.out.bind_info->length) {
994                 case 24: {
995                         struct drsuapi_DsBindInfo24 *info24;
996                         info24 = &drsuapi->bind_r.out.bind_info->info.info24;
997                         drsuapi->remote_info28.supported_extensions     = info24->supported_extensions;
998                         drsuapi->remote_info28.site_guid                = info24->site_guid;
999                         drsuapi->remote_info28.u1                       = info24->u1;
1000                         drsuapi->remote_info28.repl_epoch               = 0;
1001                         break;
1002                 }
1003                 case 28:
1004                         drsuapi->remote_info28 = drsuapi->bind_r.out.bind_info->info.info28;
1005                         break;
1006                 }
1007         }
1008
1009         return WERR_OK;
1010 }
1011
1012 static void becomeDC_drsuapi1_add_entry_send(struct libnet_BecomeDC_state *s);
1013
1014 static void becomeDC_drsuapi1_bind_recv(struct rpc_request *req)
1015 {
1016         struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
1017                                           struct libnet_BecomeDC_state);
1018         struct composite_context *c = s->creq;
1019         WERROR status;
1020
1021         c->status = dcerpc_ndr_request_recv(req);
1022         if (!composite_is_ok(c)) return;
1023
1024         status = becomeDC_drsuapi_bind_recv(s, &s->drsuapi1);
1025         if (!W_ERROR_IS_OK(status)) {
1026                 composite_error(c, werror_to_ntstatus(status));
1027                 return;
1028         }
1029
1030         becomeDC_drsuapi1_add_entry_send(s);
1031 }
1032
1033 static void becomeDC_drsuapi1_add_entry_recv(struct rpc_request *req);
1034
1035 static void becomeDC_drsuapi1_add_entry_send(struct libnet_BecomeDC_state *s)
1036 {
1037         struct composite_context *c = s->creq;
1038         struct rpc_request *req;
1039         struct drsuapi_DsAddEntry *r;
1040         struct drsuapi_DsReplicaObjectIdentifier *identifier;
1041         uint32_t num_attrs, i = 0;
1042         struct drsuapi_DsReplicaAttribute *attrs;
1043
1044         /* choose a random invocationId */
1045         s->dest_dsa.invocation_id = GUID_random();
1046
1047         r = talloc_zero(s, struct drsuapi_DsAddEntry);
1048         if (composite_nomem(r, c)) return;
1049
1050         /* setup identifier */
1051         identifier              = talloc(r, struct drsuapi_DsReplicaObjectIdentifier);
1052         if (composite_nomem(identifier, c)) return;
1053         identifier->guid        = GUID_zero();
1054         identifier->sid         = s->zero_sid;
1055         identifier->dn          = talloc_asprintf(identifier, "CN=NTDS Settings,%s",
1056                                                   s->dest_dsa.server_dn_str);
1057         if (composite_nomem(identifier->dn, c)) return;
1058
1059         /* allocate attribute array */
1060         num_attrs       = 11;
1061         attrs           = talloc_array(r, struct drsuapi_DsReplicaAttribute, num_attrs);
1062         if (composite_nomem(attrs, c)) return;
1063
1064         /* ntSecurityDescriptor */
1065         {
1066                 struct drsuapi_DsAttributeValueSecurityDescriptor *vs;
1067                 struct security_descriptor *v;
1068                 struct dom_sid *domain_admins_sid;
1069                 const char *domain_admins_sid_str;
1070
1071                 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueSecurityDescriptor, 1);
1072                 if (composite_nomem(vs, c)) return;
1073
1074                 domain_admins_sid = dom_sid_add_rid(vs, s->domain.sid, DOMAIN_RID_ADMINS);
1075                 if (composite_nomem(domain_admins_sid, c)) return;
1076
1077                 domain_admins_sid_str = dom_sid_string(domain_admins_sid, domain_admins_sid);
1078                 if (composite_nomem(domain_admins_sid_str, c)) return;
1079
1080                 v = security_descriptor_create(vs,
1081                                                /* owner: domain admins */
1082                                                domain_admins_sid_str,
1083                                                /* owner group: domain admins */
1084                                                domain_admins_sid_str,
1085                                                /* authenticated users */
1086                                                SID_NT_AUTHENTICATED_USERS,
1087                                                SEC_ACE_TYPE_ACCESS_ALLOWED,
1088                                                SEC_STD_READ_CONTROL |
1089                                                SEC_ADS_LIST |
1090                                                SEC_ADS_READ_PROP |
1091                                                SEC_ADS_LIST_OBJECT,
1092                                                0,
1093                                                /* domain admins */
1094                                                domain_admins_sid_str,
1095                                                SEC_ACE_TYPE_ACCESS_ALLOWED,
1096                                                SEC_STD_REQUIRED |
1097                                                SEC_ADS_CREATE_CHILD |
1098                                                SEC_ADS_LIST |
1099                                                SEC_ADS_SELF_WRITE |
1100                                                SEC_ADS_READ_PROP |
1101                                                SEC_ADS_WRITE_PROP |
1102                                                SEC_ADS_DELETE_TREE |
1103                                                SEC_ADS_LIST_OBJECT |
1104                                                SEC_ADS_CONTROL_ACCESS,
1105                                                0,
1106                                                /* system */
1107                                                SID_NT_SYSTEM,
1108                                                SEC_ACE_TYPE_ACCESS_ALLOWED,
1109                                                SEC_STD_REQUIRED |
1110                                                SEC_ADS_CREATE_CHILD |
1111                                                SEC_ADS_DELETE_CHILD |
1112                                                SEC_ADS_LIST |
1113                                                SEC_ADS_SELF_WRITE |
1114                                                SEC_ADS_READ_PROP |
1115                                                SEC_ADS_WRITE_PROP |
1116                                                SEC_ADS_DELETE_TREE |
1117                                                SEC_ADS_LIST_OBJECT |
1118                                                SEC_ADS_CONTROL_ACCESS,
1119                                                0,
1120                                                /* end */
1121                                                NULL);
1122                 if (composite_nomem(v, c)) return;
1123
1124                 vs[0].sd                = v;
1125
1126                 attrs[i].attid                                          = DRSUAPI_ATTRIBUTE_ntSecurityDescriptor;
1127                 attrs[i].value_ctr.security_descriptor.num_values       = 1;
1128                 attrs[i].value_ctr.security_descriptor.values           = vs;
1129
1130                 i++;
1131         }
1132
1133         /* objectClass: nTDSDSA */
1134         {
1135                 struct drsuapi_DsAttributeValueObjectClassId *vs;
1136                 enum drsuapi_DsObjectClassId *v;
1137
1138                 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueObjectClassId, 1);
1139                 if (composite_nomem(vs, c)) return;
1140
1141                 v = talloc_array(vs, enum drsuapi_DsObjectClassId, 1);
1142                 if (composite_nomem(v, c)) return;
1143
1144                 /* value for nTDSDSA */
1145                 v[0]                    = 0x0017002F;
1146
1147                 vs[0].objectClassId     = &v[0];
1148
1149                 attrs[i].attid                                  = DRSUAPI_ATTRIBUTE_objectClass;
1150                 attrs[i].value_ctr.object_class_id.num_values   = 1;
1151                 attrs[i].value_ctr.object_class_id.values       = vs;
1152
1153                 i++;
1154         }
1155
1156         /* objectCategory: CN=NTDS-DSA,CN=Schema,... */
1157         {
1158                 struct drsuapi_DsAttributeValueDNString *vs;
1159                 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1160
1161                 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 1);
1162                 if (composite_nomem(vs, c)) return;
1163
1164                 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 1);
1165                 if (composite_nomem(v, c)) return;
1166
1167                 /* value for nTDSDSA */
1168                 v[0].guid               = GUID_zero();
1169                 v[0].sid                = s->zero_sid;
1170                 v[0].dn                 = talloc_asprintf(v, "CN=NTDS-DSA,%s",
1171                                                           s->forest.schema_dn_str);
1172                 if (composite_nomem(v->dn, c)) return;
1173
1174                 vs[0].object            = &v[0];
1175
1176                 attrs[i].attid                                  = DRSUAPI_ATTRIBUTE_objectCategory;
1177                 attrs[i].value_ctr.dn_string.num_values         = 1;
1178                 attrs[i].value_ctr.dn_string.values             = vs;
1179
1180                 i++;
1181         }
1182
1183         /* invocationId: random guid */
1184         {
1185                 struct drsuapi_DsAttributeValueGUID *vs;
1186                 struct GUID *v;
1187
1188                 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueGUID, 1);
1189                 if (composite_nomem(vs, c)) return;
1190
1191                 v = talloc_array(vs, struct GUID, 1);
1192                 if (composite_nomem(v, c)) return;
1193
1194                 /* value for nTDSDSA */
1195                 v[0]                    = s->dest_dsa.invocation_id;
1196
1197                 vs[0].guid              = &v[0];
1198
1199                 attrs[i].attid                                  = DRSUAPI_ATTRIBUTE_invocationId;
1200                 attrs[i].value_ctr.guid.num_values              = 1;
1201                 attrs[i].value_ctr.guid.values                  = vs;
1202
1203                 i++;
1204         }
1205
1206         /* hasMasterNCs: ... */
1207         {
1208                 struct drsuapi_DsAttributeValueDNString *vs;
1209                 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1210
1211                 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 3);
1212                 if (composite_nomem(vs, c)) return;
1213
1214                 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 3);
1215                 if (composite_nomem(v, c)) return;
1216
1217                 v[0].guid               = GUID_zero();
1218                 v[0].sid                = s->zero_sid;
1219                 v[0].dn                 = s->forest.config_dn_str;
1220
1221                 v[1].guid               = GUID_zero();
1222                 v[1].sid                = s->zero_sid;
1223                 v[1].dn                 = s->domain.dn_str;
1224
1225                 v[2].guid               = GUID_zero();
1226                 v[2].sid                = s->zero_sid;
1227                 v[2].dn                 = s->forest.schema_dn_str;
1228
1229                 vs[0].object            = &v[0];
1230                 vs[1].object            = &v[1];
1231                 vs[2].object            = &v[2];
1232
1233                 attrs[i].attid                                  = DRSUAPI_ATTRIBUTE_hasMasterNCs;
1234                 attrs[i].value_ctr.dn_string.num_values         = 3;
1235                 attrs[i].value_ctr.dn_string.values             = vs;
1236
1237                 i++;
1238         }
1239
1240         /* msDS-hasMasterNCs: ... */
1241         {
1242                 struct drsuapi_DsAttributeValueDNString *vs;
1243                 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1244
1245                 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 3);
1246                 if (composite_nomem(vs, c)) return;
1247
1248                 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 3);
1249                 if (composite_nomem(v, c)) return;
1250
1251                 v[0].guid               = GUID_zero();
1252                 v[0].sid                = s->zero_sid;
1253                 v[0].dn                 = s->forest.config_dn_str;
1254
1255                 v[1].guid               = GUID_zero();
1256                 v[1].sid                = s->zero_sid;
1257                 v[1].dn                 = s->domain.dn_str;
1258
1259                 v[2].guid               = GUID_zero();
1260                 v[2].sid                = s->zero_sid;
1261                 v[2].dn                 = s->forest.schema_dn_str;
1262
1263                 vs[0].object            = &v[0];
1264                 vs[1].object            = &v[1];
1265                 vs[2].object            = &v[2];
1266
1267                 attrs[i].attid                                  = DRSUAPI_ATTRIBUTE_msDS_hasMasterNCs;
1268                 attrs[i].value_ctr.dn_string.num_values         = 3;
1269                 attrs[i].value_ctr.dn_string.values             = vs;
1270
1271                 i++;
1272         }
1273
1274         /* dMDLocation: CN=Schema,... */
1275         {
1276                 struct drsuapi_DsAttributeValueDNString *vs;
1277                 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1278
1279                 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 1);
1280                 if (composite_nomem(vs, c)) return;
1281
1282                 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 1);
1283                 if (composite_nomem(v, c)) return;
1284
1285                 v[0].guid               = GUID_zero();
1286                 v[0].sid                = s->zero_sid;
1287                 v[0].dn                 = s->forest.schema_dn_str;
1288
1289                 vs[0].object            = &v[0];
1290
1291                 attrs[i].attid                                  = DRSUAPI_ATTRIBUTE_dMDLocation;
1292                 attrs[i].value_ctr.dn_string.num_values         = 1;
1293                 attrs[i].value_ctr.dn_string.values             = vs;
1294
1295                 i++;
1296         }
1297
1298         /* msDS-HasDomainNCs: <domain_partition> */
1299         {
1300                 struct drsuapi_DsAttributeValueDNString *vs;
1301                 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1302
1303                 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 1);
1304                 if (composite_nomem(vs, c)) return;
1305
1306                 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 1);
1307                 if (composite_nomem(v, c)) return;
1308
1309                 v[0].guid               = GUID_zero();
1310                 v[0].sid                = s->zero_sid;
1311                 v[0].dn                 = s->domain.dn_str;
1312
1313                 vs[0].object            = &v[0];
1314
1315                 attrs[i].attid                                  = DRSUAPI_ATTRIBUTE_msDS_HasDomainNCs;
1316                 attrs[i].value_ctr.dn_string.num_values         = 1;
1317                 attrs[i].value_ctr.dn_string.values             = vs;
1318
1319                 i++;
1320         }
1321
1322         /* msDS-Behavior-Version */
1323         {
1324                 struct drsuapi_DsAttributeValueUINT32 *vs;
1325                 uint32_t *v;
1326
1327                 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueUINT32, 1);
1328                 if (composite_nomem(vs, c)) return;
1329
1330                 v = talloc_array(vs, uint32_t, 1);
1331                 if (composite_nomem(v, c)) return;
1332
1333                 v[0]                    = 0x00000002;
1334
1335                 vs[0].value             = &v[0];
1336
1337                 attrs[i].attid                                  = DRSUAPI_ATTRIBUTE_msDS_Behavior_Version;
1338                 attrs[i].value_ctr.uint32.num_values            = 1;
1339                 attrs[i].value_ctr.uint32.values                = vs;
1340
1341                 i++;
1342         }
1343
1344         /* systemFlags */
1345         {
1346                 struct drsuapi_DsAttributeValueUINT32 *vs;
1347                 uint32_t *v;
1348
1349                 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueUINT32, 1);
1350                 if (composite_nomem(vs, c)) return;
1351
1352                 v = talloc_array(vs, uint32_t, 1);
1353                 if (composite_nomem(v, c)) return;
1354
1355                 v[0]                    = SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE;
1356
1357                 vs[0].value             = &v[0];
1358
1359                 attrs[i].attid                                  = DRSUAPI_ATTRIBUTE_systemFlags;
1360                 attrs[i].value_ctr.uint32.num_values            = 1;
1361                 attrs[i].value_ctr.uint32.values                = vs;
1362
1363                 i++;
1364         }
1365
1366         /* serverReference: ... */
1367         {
1368                 struct drsuapi_DsAttributeValueDNString *vs;
1369                 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1370
1371                 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 1);
1372                 if (composite_nomem(vs, c)) return;
1373
1374                 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 1);
1375                 if (composite_nomem(v, c)) return;
1376
1377                 v[0].guid               = GUID_zero();
1378                 v[0].sid                = s->zero_sid;
1379                 v[0].dn                 = s->dest_dsa.computer_dn_str;
1380
1381                 vs[0].object            = &v[0];
1382
1383                 attrs[i].attid                                  = DRSUAPI_ATTRIBUTE_serverReference;
1384                 attrs[i].value_ctr.dn_string.num_values         = 1;
1385                 attrs[i].value_ctr.dn_string.values             = vs;
1386
1387                 i++;
1388         }
1389
1390         /* truncate the attribute list to the attribute count we have filled in */
1391         num_attrs = i;
1392
1393         /* setup request structure */
1394         r->in.bind_handle                                               = &s->drsuapi1.bind_handle;
1395         r->in.level                                                     = 2;
1396         r->in.req.req2.first_object.next_object                         = NULL;
1397         r->in.req.req2.first_object.object.identifier                   = identifier;
1398         r->in.req.req2.first_object.object.unknown1                     = 0x00000000;   
1399         r->in.req.req2.first_object.object.attribute_ctr.num_attributes = num_attrs;
1400         r->in.req.req2.first_object.object.attribute_ctr.attributes     = attrs;
1401
1402         req = dcerpc_drsuapi_DsAddEntry_send(s->drsuapi1.pipe, r, r);
1403         composite_continue_rpc(c, req, becomeDC_drsuapi1_add_entry_recv, s);
1404 }
1405
1406 static void becomeDC_drsuapi2_connect_recv(struct composite_context *req);
1407
1408 static void becomeDC_drsuapi1_add_entry_recv(struct rpc_request *req)
1409 {
1410         struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
1411                                           struct libnet_BecomeDC_state);
1412         struct composite_context *c = s->creq;
1413         struct drsuapi_DsAddEntry *r = talloc_get_type(req->ndr.struct_ptr,
1414                                        struct drsuapi_DsAddEntry);
1415
1416         c->status = dcerpc_ndr_request_recv(req);
1417         if (!composite_is_ok(c)) return;
1418
1419         if (!W_ERROR_IS_OK(r->out.result)) {
1420                 composite_error(c, werror_to_ntstatus(r->out.result));
1421                 return;
1422         }
1423
1424         if (r->out.level == 3) {
1425                 if (r->out.ctr.ctr3.count != 1) {
1426                         WERROR status;
1427
1428                         if (r->out.ctr.ctr3.level != 1) {
1429                                 composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
1430                                 return;
1431                         }
1432
1433                         if (!r->out.ctr.ctr3.error) {
1434                                 composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
1435                                 return;
1436                         }
1437
1438                         status = r->out.ctr.ctr3.error->info1.status;
1439
1440                         if (!r->out.ctr.ctr3.error->info1.info) {
1441                                 composite_error(c, werror_to_ntstatus(status));
1442                                 return;
1443                         }
1444
1445                         /* see if we can get a more detailed error */
1446                         switch (r->out.ctr.ctr3.error->info1.level) {
1447                         case 1:
1448                                 status = r->out.ctr.ctr3.error->info1.info->error1.status;
1449                                 break;
1450                         case 4:
1451                         case 5:
1452                         case 6:
1453                         case 7:
1454                                 status = r->out.ctr.ctr3.error->info1.info->errorX.status;
1455                                 break;
1456                         }
1457
1458                         composite_error(c, werror_to_ntstatus(status));
1459                         return;
1460                 }
1461
1462                 s->dest_dsa.ntds_guid   = r->out.ctr.ctr3.objects[0].guid;
1463         } else if (r->out.level == 2) {
1464                 if (r->out.ctr.ctr2.count != 1) {
1465                         composite_error(c, werror_to_ntstatus(r->out.ctr.ctr2.error.status));
1466                         return;
1467                 }
1468
1469                 s->dest_dsa.ntds_guid   = r->out.ctr.ctr2.objects[0].guid;
1470         } else {
1471                 composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
1472                 return;
1473         }
1474
1475         becomeDC_drsuapi_connect_send(s, &s->drsuapi2, becomeDC_drsuapi2_connect_recv);
1476 }
1477
1478 static void becomeDC_drsuapi2_bind_recv(struct rpc_request *req);
1479
1480 static void becomeDC_drsuapi2_connect_recv(struct composite_context *req)
1481 {
1482         struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
1483                                           struct libnet_BecomeDC_state);
1484         struct composite_context *c = s->creq;
1485
1486         c->status = dcerpc_pipe_connect_b_recv(req, s, &s->drsuapi2.pipe);
1487         if (!composite_is_ok(c)) return;
1488
1489         becomeDC_drsuapi_bind_send(s, &s->drsuapi2, becomeDC_drsuapi2_bind_recv);
1490 }
1491
1492 static void becomeDC_drsuapi3_connect_recv(struct composite_context *req);
1493
1494 static void becomeDC_drsuapi2_bind_recv(struct rpc_request *req)
1495 {
1496         struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
1497                                           struct libnet_BecomeDC_state);
1498         struct composite_context *c = s->creq;
1499         WERROR status;
1500
1501         c->status = dcerpc_ndr_request_recv(req);
1502         if (!composite_is_ok(c)) return;
1503
1504         status = becomeDC_drsuapi_bind_recv(s, &s->drsuapi2);
1505         if (!W_ERROR_IS_OK(status)) {
1506                 composite_error(c, werror_to_ntstatus(status));
1507                 return;
1508         }
1509
1510         /* this avoids the epmapper lookup on the 2nd connection */
1511         s->drsuapi3.binding = s->drsuapi2.binding;
1512
1513         becomeDC_drsuapi_connect_send(s, &s->drsuapi3, becomeDC_drsuapi3_connect_recv);
1514 }
1515
1516 static void becomeDC_drsuapi3_connect_recv(struct composite_context *req)
1517 {
1518         struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
1519                                           struct libnet_BecomeDC_state);
1520         struct composite_context *c = s->creq;
1521
1522         c->status = dcerpc_pipe_connect_b_recv(req, s, &s->drsuapi3.pipe);
1523         if (!composite_is_ok(c)) return;
1524
1525         becomeDC_connect_ldap2(s);
1526 }
1527
1528 static NTSTATUS becomeDC_ldap2_modify_computer(struct libnet_BecomeDC_state *s)
1529 {
1530         int ret;
1531         struct ldb_message *msg;
1532         uint32_t i;
1533         uint32_t user_account_control = UF_SERVER_TRUST_ACCOUNT |
1534                                         UF_TRUSTED_FOR_DELEGATION;
1535
1536         /* as the value is already as we want it to be, we're done */
1537         if (s->dest_dsa.user_account_control == user_account_control) {
1538                 return NT_STATUS_OK;
1539         }
1540
1541         /* make a 'modify' msg, and only for serverReference */
1542         msg = ldb_msg_new(s);
1543         NT_STATUS_HAVE_NO_MEMORY(msg);
1544         msg->dn = ldb_dn_new(msg, s->ldap2.ldb, s->dest_dsa.computer_dn_str);
1545         NT_STATUS_HAVE_NO_MEMORY(msg->dn);
1546
1547         ret = ldb_msg_add_fmt(msg, "userAccountControl", "%u", user_account_control);
1548         if (ret != 0) {
1549                 talloc_free(msg);
1550                 return NT_STATUS_NO_MEMORY;
1551         }
1552
1553         /* mark all the message elements (should be just one)
1554            as LDB_FLAG_MOD_REPLACE */
1555         for (i=0;i<msg->num_elements;i++) {
1556                 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
1557         }
1558
1559         ret = ldb_modify(s->ldap2.ldb, msg);
1560         talloc_free(msg);
1561         if (ret != LDB_SUCCESS) {
1562                 return NT_STATUS_LDAP(ret);
1563         }
1564
1565         s->dest_dsa.user_account_control = user_account_control;
1566
1567         return NT_STATUS_OK;
1568 }
1569
1570 static NTSTATUS becomeDC_ldap2_move_computer(struct libnet_BecomeDC_state *s)
1571 {
1572         int ret;
1573         struct ldb_result *r;
1574         struct ldb_dn *basedn;
1575         struct ldb_dn *old_dn;
1576         struct ldb_dn *new_dn;
1577         static const char *_1_1_attrs[] = {
1578                 "1.1",
1579                 NULL
1580         };
1581
1582         basedn = ldb_dn_new_fmt(s, s->ldap2.ldb, "<WKGUID=a361b2ffffd211d1aa4b00c04fd7d83a,%s>",
1583                                 s->domain.dn_str);
1584         NT_STATUS_HAVE_NO_MEMORY(basedn);
1585
1586         ret = ldb_search(s->ldap2.ldb, basedn, LDB_SCOPE_BASE,
1587                          "(objectClass=*)", _1_1_attrs, &r);
1588         talloc_free(basedn);
1589         if (ret != LDB_SUCCESS) {
1590                 return NT_STATUS_LDAP(ret);
1591         } else if (r->count != 1) {
1592                 talloc_free(r);
1593                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1594         }
1595
1596         old_dn = ldb_dn_new(r, s->ldap2.ldb, s->dest_dsa.computer_dn_str);
1597         NT_STATUS_HAVE_NO_MEMORY(old_dn);
1598
1599         new_dn = r->msgs[0]->dn;
1600
1601         if (!ldb_dn_add_child_fmt(new_dn, "CN=%s", s->dest_dsa.netbios_name)) {
1602                 talloc_free(r);
1603                 return NT_STATUS_NO_MEMORY;
1604         }
1605
1606         if (ldb_dn_compare(old_dn, new_dn) == 0) {
1607                 /* we don't need to rename if the old and new dn match */
1608                 talloc_free(r);
1609                 return NT_STATUS_OK;
1610         }
1611
1612         ret = ldb_rename(s->ldap2.ldb, old_dn, new_dn);
1613         if (ret != LDB_SUCCESS) {
1614                 talloc_free(r);
1615                 return NT_STATUS_LDAP(ret);
1616         }
1617
1618         s->dest_dsa.computer_dn_str = ldb_dn_alloc_linearized(s, new_dn);
1619         NT_STATUS_HAVE_NO_MEMORY(s->dest_dsa.computer_dn_str);
1620
1621         talloc_free(r);
1622
1623         return NT_STATUS_OK;
1624 }
1625
1626 static void becomeDC_connect_ldap2(struct libnet_BecomeDC_state *s)
1627 {
1628         struct composite_context *c = s->creq;
1629
1630         c->status = becomeDC_ldap_connect(s, &s->ldap2);
1631         if (!composite_is_ok(c)) return;
1632
1633         c->status = becomeDC_ldap2_modify_computer(s);
1634         if (!composite_is_ok(c)) return;
1635
1636         c->status = becomeDC_ldap2_move_computer(s);
1637         if (!composite_is_ok(c)) return;
1638
1639         composite_error(c, NT_STATUS_NOT_IMPLEMENTED);
1640 }
1641
1642 struct composite_context *libnet_BecomeDC_send(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_BecomeDC *r)
1643 {
1644         struct composite_context *c;
1645         struct libnet_BecomeDC_state *s;
1646         char *tmp_name;
1647
1648         c = composite_create(mem_ctx, ctx->event_ctx);
1649         if (c == NULL) return NULL;
1650
1651         s = talloc_zero(c, struct libnet_BecomeDC_state);
1652         if (composite_nomem(s, c)) return c;
1653         c->private_data = s;
1654         s->creq         = c;
1655         s->libnet       = ctx;
1656
1657         /* Domain input */
1658         s->domain.dns_name      = talloc_strdup(s, r->in.domain_dns_name);
1659         if (composite_nomem(s->domain.dns_name, c)) return c;
1660         s->domain.netbios_name  = talloc_strdup(s, r->in.domain_netbios_name);
1661         if (composite_nomem(s->domain.netbios_name, c)) return c;
1662         s->domain.sid           = dom_sid_dup(s, r->in.domain_sid);
1663         if (composite_nomem(s->domain.sid, c)) return c;
1664
1665         /* Source DSA input */
1666         s->source_dsa.address   = talloc_strdup(s, r->in.source_dsa_address);
1667         if (composite_nomem(s->source_dsa.address, c)) return c;
1668
1669         /* Destination DSA input */
1670         s->dest_dsa.netbios_name= talloc_strdup(s, r->in.dest_dsa_netbios_name);
1671         if (composite_nomem(s->dest_dsa.netbios_name, c)) return c;
1672
1673         /* Destination DSA dns_name construction */
1674         tmp_name                = strlower_talloc(s, s->dest_dsa.netbios_name);
1675         if (composite_nomem(tmp_name, c)) return c;
1676         s->dest_dsa.dns_name    = talloc_asprintf_append(tmp_name, ".%s",
1677                                                          s->domain.dns_name);
1678         if (composite_nomem(s->dest_dsa.dns_name, c)) return c;
1679
1680         becomeDC_send_cldap(s);
1681         return c;
1682 }
1683
1684 NTSTATUS libnet_BecomeDC_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, struct libnet_BecomeDC *r)
1685 {
1686         NTSTATUS status;
1687
1688         status = composite_wait(c);
1689
1690         ZERO_STRUCT(r->out);
1691
1692         talloc_free(c);
1693         return status;
1694 }
1695
1696 NTSTATUS libnet_BecomeDC(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_BecomeDC *r)
1697 {
1698         NTSTATUS status;
1699         struct composite_context *c;
1700         c = libnet_BecomeDC_send(ctx, mem_ctx, r);
1701         status = libnet_BecomeDC_recv(c, mem_ctx, r);
1702         return status;
1703 }