r20066: use the same sid "Domain Admins" for the security_descriptor
[jra/samba/.git] / source4 / 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 {
39                 struct cldap_socket *sock;
40                 struct cldap_netlogon io;
41                 struct nbt_cldap_netlogon_5 netlogon5;
42         } cldap;
43
44         struct becomeDC_ldap {
45                 struct ldb_context *ldb;
46                 const struct ldb_message *rootdse;
47         } ldap1, ldap2;
48
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;
59         } drsuapi1;
60
61         struct {
62                 /* input */
63                 const char *dns_name;
64                 const char *netbios_name;
65                 const struct dom_sid *sid;
66
67                 /* constructed */
68                 struct GUID guid;
69                 const char *dn_str;
70         } domain;
71
72         struct {
73                 /* constructed */
74                 const char *dns_name;
75                 const char *root_dn_str;
76                 const char *config_dn_str;
77                 const char *schema_dn_str;
78         } forest;
79
80         struct {
81                 /* input */
82                 const char *address;
83
84                 /* constructed */
85                 const char *dns_name;
86                 const char *netbios_name;
87                 const char *site_name;
88                 const char *server_dn_str;
89                 const char *ntds_dn_str;
90         } source_dsa;
91
92         struct {
93                 /* input */
94                 const char *netbios_name;
95
96                 /* constructed */
97                 const char *dns_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;
105         } dest_dsa;
106
107         struct {
108                 uint32_t domain_behavior_version;
109                 uint32_t config_behavior_version;
110                 uint32_t schema_object_version;
111                 uint32_t w2k3_update_revision;
112         } ads_options;
113
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;
120
121         struct becomeDC_fsmo rid_manager_fsmo;
122 };
123
124 static void becomeDC_connect_ldap1(struct libnet_BecomeDC_state *s);
125
126 static void becomeDC_recv_cldap(struct cldap_request *req)
127 {
128         struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
129                                           struct libnet_BecomeDC_state);
130         struct composite_context *c = s->creq;
131
132         c->status = cldap_netlogon_recv(req, s, &s->cldap.io);
133         if (!composite_is_ok(c)) return;
134
135         s->cldap.netlogon5 = s->cldap.io.out.netlogon.logon5;
136
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;
140
141         s->forest.dns_name              = s->cldap.netlogon5.forest;
142
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;
146
147         s->dest_dsa.site_name           = s->cldap.netlogon5.client_site;
148
149         becomeDC_connect_ldap1(s);
150 }
151
152 static void becomeDC_send_cldap(struct libnet_BecomeDC_state *s)
153 {
154         struct composite_context *c = s->creq;
155         struct cldap_request *req;
156
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;
165
166         s->cldap.sock = cldap_socket_init(s, s->libnet->event_ctx);
167         if (composite_nomem(s->cldap.sock, c)) return;
168
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;
173 }
174
175 static NTSTATUS becomeDC_ldap_connect(struct libnet_BecomeDC_state *s, struct becomeDC_ldap *ldap)
176 {
177         char *url;
178
179         url = talloc_asprintf(s, "ldap://%s/", s->source_dsa.dns_name);
180         NT_STATUS_HAVE_NO_MEMORY(url);
181
182         ldap->ldb = ldb_wrap_connect(s, url,
183                                      NULL,
184                                      s->libnet->cred,
185                                      0, NULL);
186         talloc_free(url);
187         if (ldap->ldb == NULL) {
188                 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
189         }
190
191         return NT_STATUS_OK;
192 }
193
194 static NTSTATUS becomeDC_ldap1_rootdse(struct libnet_BecomeDC_state *s)
195 {
196         int ret;
197         struct ldb_result *r;
198         struct ldb_dn *basedn;
199         static const char *attrs[] = {
200                 "*",
201                 NULL
202         };
203
204         basedn = ldb_dn_new(s, s->ldap1.ldb, NULL);
205         NT_STATUS_HAVE_NO_MEMORY(basedn);
206
207         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE, 
208                          "(objectClass=*)", attrs, &r);
209         talloc_free(basedn);
210         if (ret != LDB_SUCCESS) {
211                 return NT_STATUS_LDAP(ret);
212         } else if (r->count != 1) {
213                 talloc_free(r);
214                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
215         }
216         talloc_steal(s, r);
217
218         s->ldap1.rootdse = r->msgs[0];
219
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;
222
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;
229
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;
234
235         return NT_STATUS_OK;
236 }
237
238 static NTSTATUS becomeDC_ldap1_config_behavior_version(struct libnet_BecomeDC_state *s)
239 {
240         int ret;
241         struct ldb_result *r;
242         struct ldb_dn *basedn;
243         static const char *attrs[] = {
244                 "msDs-Behavior-Version",
245                 NULL
246         };
247
248         basedn = ldb_dn_new(s, s->ldap1.ldb, s->forest.config_dn_str);
249         NT_STATUS_HAVE_NO_MEMORY(basedn);
250
251         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_ONELEVEL,
252                          "(cn=Partitions)", attrs, &r);
253         talloc_free(basedn);
254         if (ret != LDB_SUCCESS) {
255                 return NT_STATUS_LDAP(ret);
256         } else if (r->count != 1) {
257                 talloc_free(r);
258                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
259         }
260
261         s->ads_options.config_behavior_version = ldb_msg_find_attr_as_uint(r->msgs[0], "msDs-Behavior-Version", 0);
262
263         talloc_free(r);
264         return NT_STATUS_OK;
265 }
266
267 static NTSTATUS becomeDC_ldap1_domain_behavior_version(struct libnet_BecomeDC_state *s)
268 {
269         int ret;
270         struct ldb_result *r;
271         struct ldb_dn *basedn;
272         static const char *attrs[] = {
273                 "msDs-Behavior-Version",
274                 NULL
275         };
276
277         basedn = ldb_dn_new(s, s->ldap1.ldb, s->domain.dn_str);
278         NT_STATUS_HAVE_NO_MEMORY(basedn);
279
280         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
281                          "(objectClass=*)", attrs, &r);
282         talloc_free(basedn);
283         if (ret != LDB_SUCCESS) {
284                 return NT_STATUS_LDAP(ret);
285         } else if (r->count != 1) {
286                 talloc_free(r);
287                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
288         }
289
290         s->ads_options.domain_behavior_version = ldb_msg_find_attr_as_uint(r->msgs[0], "msDs-Behavior-Version", 0);
291
292         talloc_free(r);
293         return NT_STATUS_OK;
294 }
295
296 static NTSTATUS becomeDC_ldap1_schema_object_version(struct libnet_BecomeDC_state *s)
297 {
298         int ret;
299         struct ldb_result *r;
300         struct ldb_dn *basedn;
301         static const char *attrs[] = {
302                 "objectVersion",
303                 NULL
304         };
305
306         basedn = ldb_dn_new(s, s->ldap1.ldb, s->forest.schema_dn_str);
307         NT_STATUS_HAVE_NO_MEMORY(basedn);
308
309         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
310                          "(objectClass=*)", attrs, &r);
311         talloc_free(basedn);
312         if (ret != LDB_SUCCESS) {
313                 return NT_STATUS_LDAP(ret);
314         } else if (r->count != 1) {
315                 talloc_free(r);
316                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
317         }
318
319         s->ads_options.schema_object_version = ldb_msg_find_attr_as_uint(r->msgs[0], "objectVersion", 0);
320
321         talloc_free(r);
322         return NT_STATUS_OK;
323 }
324
325 static NTSTATUS becomeDC_ldap1_w2k3_update_revision(struct libnet_BecomeDC_state *s)
326 {
327         int ret;
328         struct ldb_result *r;
329         struct ldb_dn *basedn;
330         static const char *attrs[] = {
331                 "revision",
332                 NULL
333         };
334
335         basedn = ldb_dn_new_fmt(s, s->ldap1.ldb, "CN=Windows2003Update,CN=DomainUpdates,CN=System,%s",
336                                 s->domain.dn_str);
337         NT_STATUS_HAVE_NO_MEMORY(basedn);
338
339         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
340                          "(objectClass=*)", attrs, &r);
341         talloc_free(basedn);
342         if (ret != LDB_SUCCESS) {
343                 return NT_STATUS_LDAP(ret);
344         } else if (r->count != 1) {
345                 talloc_free(r);
346                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
347         }
348
349         s->ads_options.w2k3_update_revision = ldb_msg_find_attr_as_uint(r->msgs[0], "revision", 0);
350
351         talloc_free(r);
352         return NT_STATUS_OK;
353 }
354
355 static NTSTATUS becomeDC_ldap1_infrastructure_fsmo(struct libnet_BecomeDC_state *s)
356 {
357         int ret;
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[] = {
363                 "1.1",
364                 NULL
365         };
366         static const char *fsmo_attrs[] = {
367                 "fSMORoleOwner",
368                 NULL
369         };
370         static const char *dns_attrs[] = {
371                 "dnsHostName",
372                 NULL
373         };
374         static const char *guid_attrs[] = {
375                 "objectGUID",
376                 NULL
377         };
378
379         basedn = ldb_dn_new_fmt(s, s->ldap1.ldb, "<WKGUID=2fbac1870ade11d297c400c04fd8d5cd,%s>",
380                                 s->domain.dn_str);
381         NT_STATUS_HAVE_NO_MEMORY(basedn);
382
383         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
384                          "(objectClass=*)", _1_1_attrs, &r);
385         talloc_free(basedn);
386         if (ret != LDB_SUCCESS) {
387                 return NT_STATUS_LDAP(ret);
388         } else if (r->count != 1) {
389                 talloc_free(r);
390                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
391         }
392
393         basedn = talloc_steal(s, r->msgs[0]->dn);
394         talloc_free(r);
395
396         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
397                          "(objectClass=*)", fsmo_attrs, &r);
398         talloc_free(basedn);
399         if (ret != LDB_SUCCESS) {
400                 return NT_STATUS_LDAP(ret);
401         } else if (r->count != 1) {
402                 talloc_free(r);
403                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
404         }
405
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);
409
410         talloc_free(r);
411
412         ntds_dn = ldb_dn_new(s, s->ldap1.ldb, s->infrastructure_fsmo.ntds_dn_str);
413         NT_STATUS_HAVE_NO_MEMORY(ntds_dn);
414
415         server_dn = ldb_dn_get_parent(s, ntds_dn);
416         NT_STATUS_HAVE_NO_MEMORY(server_dn);
417
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);
420
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) {
426                 talloc_free(r);
427                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
428         }
429
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);
433
434         talloc_free(r);
435
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) {
441                 talloc_free(r);
442                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
443         }
444
445         s->infrastructure_fsmo.ntds_guid = samdb_result_guid(r->msgs[0], "objectGUID");
446
447         talloc_free(r);
448
449         return NT_STATUS_OK;
450 }
451
452 static NTSTATUS becomeDC_ldap1_rid_manager_fsmo(struct libnet_BecomeDC_state *s)
453 {
454         int ret;
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",
462                 NULL
463         };
464         static const char *fsmo_attrs[] = {
465                 "fSMORoleOwner",
466                 NULL
467         };
468         static const char *dns_attrs[] = {
469                 "dnsHostName",
470                 NULL
471         };
472         static const char *guid_attrs[] = {
473                 "objectGUID",
474                 NULL
475         };
476
477         basedn = ldb_dn_new(s, s->ldap1.ldb, s->domain.dn_str);
478         NT_STATUS_HAVE_NO_MEMORY(basedn);
479
480         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
481                          "(objectClass=*)", rid_attrs, &r);
482         talloc_free(basedn);
483         if (ret != LDB_SUCCESS) {
484                 return NT_STATUS_LDAP(ret);
485         } else if (r->count != 1) {
486                 talloc_free(r);
487                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
488         }
489
490         reference_dn_str        = samdb_result_string(r->msgs[0], "rIDManagerReference", NULL);
491         if (!reference_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
492
493         basedn = ldb_dn_new(s, s->ldap1.ldb, reference_dn_str);
494         NT_STATUS_HAVE_NO_MEMORY(basedn);
495
496         talloc_free(r);
497
498         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE,
499                          "(objectClass=*)", fsmo_attrs, &r);
500         talloc_free(basedn);
501         if (ret != LDB_SUCCESS) {
502                 return NT_STATUS_LDAP(ret);
503         } else if (r->count != 1) {
504                 talloc_free(r);
505                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
506         }
507
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);
511
512         talloc_free(r);
513
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);
516
517         server_dn = ldb_dn_get_parent(s, ntds_dn);
518         NT_STATUS_HAVE_NO_MEMORY(server_dn);
519
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);
522
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) {
528                 talloc_free(r);
529                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
530         }
531
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);
535
536         talloc_free(r);
537
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) {
543                 talloc_free(r);
544                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
545         }
546
547         s->rid_manager_fsmo.ntds_guid = samdb_result_guid(r->msgs[0], "objectGUID");
548
549         talloc_free(r);
550
551         return NT_STATUS_OK;
552 }
553
554 static NTSTATUS becomeDC_ldap1_site_object(struct libnet_BecomeDC_state *s)
555 {
556         int ret;
557         struct ldb_result *r;
558         struct ldb_dn *basedn;
559
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);
564
565         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE, 
566                          "(objectClass=*)", NULL, &r);
567         talloc_free(basedn);
568         if (ret != LDB_SUCCESS) {
569                 return NT_STATUS_LDAP(ret);
570         } else if (r->count != 1) {
571                 talloc_free(r);
572                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
573         }
574
575         s->dest_dsa.site_guid = samdb_result_guid(r->msgs[0], "objectGUID");
576
577         talloc_free(r);
578         return NT_STATUS_OK;
579 }
580
581 static NTSTATUS becomeDC_ldap1_computer_object(struct libnet_BecomeDC_state *s)
582 {
583         int ret;
584         struct ldb_result *r;
585         struct ldb_dn *basedn;
586         char *filter;
587         static const char *attrs[] = {
588                 "distinguishedName",
589                 "userAccountControl",
590                 NULL
591         };
592
593         basedn = ldb_dn_new(s, s->ldap1.ldb, s->domain.dn_str);
594         NT_STATUS_HAVE_NO_MEMORY(basedn);
595
596         filter = talloc_asprintf(basedn, "(&(|(objectClass=user)(objectClass=computer))(sAMAccountName=%s$))",
597                                  s->dest_dsa.netbios_name);
598         NT_STATUS_HAVE_NO_MEMORY(filter);
599
600         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_SUBTREE, 
601                          filter, attrs, &r);
602         talloc_free(basedn);
603         if (ret != LDB_SUCCESS) {
604                 return NT_STATUS_LDAP(ret);
605         } else if (r->count != 1) {
606                 talloc_free(r);
607                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
608         }
609
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);
613
614         s->dest_dsa.user_account_control = samdb_result_uint(r->msgs[0], "userAccountControl", 0);
615
616         talloc_free(r);
617         return NT_STATUS_OK;
618 }
619
620 static NTSTATUS becomeDC_ldap1_server_object_1(struct libnet_BecomeDC_state *s)
621 {
622         int ret;
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;
628
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);
634
635         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE, 
636                          "(objectClass=*)", NULL, &r);
637         talloc_free(basedn);
638         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
639                 /* if the object doesn't exist, we'll create it later */
640                 return NT_STATUS_OK;
641         } else if (ret != LDB_SUCCESS) {
642                 return NT_STATUS_LDAP(ret);
643         } else if (r->count != 1) {
644                 talloc_free(r);
645                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
646         }
647
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);
652
653                 computer_dn             = ldb_dn_new(r, s->ldap1.ldb, s->dest_dsa.computer_dn_str);
654                 NT_STATUS_HAVE_NO_MEMORY(computer_dn);
655
656                 /*
657                  * if the server object belongs to another DC in another domain in the forest,
658                  * we should not touch this object!
659                  */
660                 if (ldb_dn_compare(computer_dn, server_reference_dn) != 0) {
661                         talloc_free(r);
662                         return NT_STATUS_OBJECT_NAME_COLLISION;
663                 }
664         }
665
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);
670
671         talloc_free(r);
672         return NT_STATUS_OK;
673 }
674
675 static NTSTATUS becomeDC_ldap1_server_object_2(struct libnet_BecomeDC_state *s)
676 {
677         int ret;
678         struct ldb_result *r;
679         struct ldb_dn *basedn;
680         const char *server_reference_bl_dn_str;
681         static const char *attrs[] = {
682                 "serverReferenceBL",
683                 NULL
684         };
685
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;
688
689         basedn = ldb_dn_new(s, s->ldap1.ldb, s->dest_dsa.computer_dn_str);
690         NT_STATUS_HAVE_NO_MEMORY(basedn);
691
692         ret = ldb_search(s->ldap1.ldb, basedn, LDB_SCOPE_BASE, 
693                          "(objectClass=*)", attrs, &r);
694         talloc_free(basedn);
695         if (ret != LDB_SUCCESS) {
696                 return NT_STATUS_LDAP(ret);
697         } else if (r->count != 1) {
698                 talloc_free(r);
699                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
700         }
701
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 */
705                 talloc_free(r);
706                 return NT_STATUS_OK;
707         }
708
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);
714         }
715
716         talloc_free(r);
717         return NT_STATUS_OK;
718 }
719
720 static NTSTATUS becomeDC_ldap1_server_object_add(struct libnet_BecomeDC_state *s)
721 {
722         int ret;
723         struct ldb_message *msg;
724         char *server_dn_str;
725
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;
728
729         msg = ldb_msg_new(s);
730         NT_STATUS_HAVE_NO_MEMORY(msg);
731
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);
737
738         ret = ldb_msg_add_string(msg, "objectClass", "server");
739         if (ret != 0) {
740                 talloc_free(msg);
741                 return NT_STATUS_NO_MEMORY;
742         }
743         ret = ldb_msg_add_string(msg, "systemFlags", "50000000");
744         if (ret != 0) {
745                 talloc_free(msg);
746                 return NT_STATUS_NO_MEMORY;
747         }
748         ret = ldb_msg_add_string(msg, "serverReference", s->dest_dsa.computer_dn_str);
749         if (ret != 0) {
750                 talloc_free(msg);
751                 return NT_STATUS_NO_MEMORY;
752         }
753
754         server_dn_str = ldb_dn_alloc_linearized(s, msg->dn);
755         NT_STATUS_HAVE_NO_MEMORY(server_dn_str);
756
757         ret = ldb_add(s->ldap1.ldb, msg);
758         talloc_free(msg);
759         if (ret != LDB_SUCCESS) {
760                 talloc_free(server_dn_str);
761                 return NT_STATUS_LDAP(ret);
762         }
763
764         s->dest_dsa.server_dn_str = server_dn_str;
765
766         return NT_STATUS_OK;
767 }
768
769 static NTSTATUS becomeDC_ldap1_server_object_modify(struct libnet_BecomeDC_state *s)
770 {
771         int ret;
772         struct ldb_message *msg;
773         uint32_t i;
774
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);
780
781         ret = ldb_msg_add_string(msg, "serverReference", s->dest_dsa.computer_dn_str);
782         if (ret != 0) {
783                 talloc_free(msg);
784                 return NT_STATUS_NO_MEMORY;
785         }
786
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;
791         }
792
793         ret = ldb_modify(s->ldap1.ldb, msg);
794         if (ret == LDB_SUCCESS) {
795                 talloc_free(msg);
796                 return NT_STATUS_OK;
797         } else if (ret == LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) {
798                 /* retry with LDB_FLAG_MOD_REPLACE */
799         } else {
800                 talloc_free(msg);
801                 return NT_STATUS_LDAP(ret);
802         }
803
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;
808         }
809
810         ret = ldb_modify(s->ldap1.ldb, msg);
811         talloc_free(msg);
812         if (ret != LDB_SUCCESS) {
813                 return NT_STATUS_LDAP(ret);
814         }
815
816         return NT_STATUS_OK;
817 }
818
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);
824
825 static void becomeDC_connect_ldap1(struct libnet_BecomeDC_state *s)
826 {
827         struct composite_context *c = s->creq;
828
829         c->status = becomeDC_ldap_connect(s, &s->ldap1);
830         if (!composite_is_ok(c)) return;
831
832         c->status = becomeDC_ldap1_rootdse(s);
833         if (!composite_is_ok(c)) return;
834
835         c->status = becomeDC_ldap1_config_behavior_version(s);
836         if (!composite_is_ok(c)) return;
837
838         c->status = becomeDC_ldap1_domain_behavior_version(s);
839         if (!composite_is_ok(c)) return;
840
841         c->status = becomeDC_ldap1_schema_object_version(s);
842         if (!composite_is_ok(c)) return;
843
844         c->status = becomeDC_ldap1_w2k3_update_revision(s);
845         if (!composite_is_ok(c)) return;
846
847         c->status = becomeDC_ldap1_infrastructure_fsmo(s);
848         if (!composite_is_ok(c)) return;
849
850         c->status = becomeDC_ldap1_rid_manager_fsmo(s);
851         if (!composite_is_ok(c)) return;
852
853         c->status = becomeDC_ldap1_site_object(s);
854         if (!composite_is_ok(c)) return;
855
856         c->status = becomeDC_ldap1_computer_object(s);
857         if (!composite_is_ok(c)) return;
858
859         c->status = becomeDC_ldap1_server_object_1(s);
860         if (!composite_is_ok(c)) return;
861
862         c->status = becomeDC_ldap1_server_object_2(s);
863         if (!composite_is_ok(c)) return;
864
865         c->status = becomeDC_ldap1_server_object_add(s);
866         if (!composite_is_ok(c)) return;
867
868         c->status = becomeDC_ldap1_server_object_modify(s);
869         if (!composite_is_ok(c)) return;
870
871         becomeDC_drsuapi_connect_send(s, &s->drsuapi1, becomeDC_drsuapi1_connect_recv);
872 }
873
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))
877 {
878         struct composite_context *c = s->creq;
879         struct composite_context *creq;
880         char *binding_str;
881
882         drsuapi->s = s;
883
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;
886
887         c->status = dcerpc_parse_binding(s, binding_str, &drsuapi->binding);
888         talloc_free(binding_str);
889         if (!composite_is_ok(c)) return;
890
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);
894 }
895
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);
900
901 static void becomeDC_drsuapi1_connect_recv(struct composite_context *req)
902 {
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;
906
907         c->status = dcerpc_pipe_connect_b_recv(req, s, &s->drsuapi1.pipe);
908         if (!composite_is_ok(c)) return;
909
910         becomeDC_drsuapi_bind_send(s, &s->drsuapi1, becomeDC_drsuapi1_bind_recv);
911 }
912
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))
916 {
917         struct composite_context *c = s->creq;
918         struct rpc_request *req;
919         struct drsuapi_DsBindInfo28 *bind_info28;
920
921         GUID_from_string(DRSUAPI_DS_BIND_GUID_W2K3, &drsuapi->bind_guid);
922
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;
936         }
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;
958 #endif
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;
963         } else {
964                 bind_info28->u1                         = 516;
965         }
966         bind_info28->repl_epoch                 = 0;
967
968         drsuapi->bind_info_ctr.length           = 28;
969         drsuapi->bind_info_ctr.info.info28      = *bind_info28;
970
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;
974
975         req = dcerpc_drsuapi_DsBind_send(drsuapi->pipe, s, &drsuapi->bind_r);
976         composite_continue_rpc(c, req, recv_fn, s);
977 }
978
979 static void becomeDC_drsuapi1_add_entry_send(struct libnet_BecomeDC_state *s);
980
981 static void becomeDC_drsuapi1_bind_recv(struct rpc_request *req)
982 {
983         struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
984                                           struct libnet_BecomeDC_state);
985         struct composite_context *c = s->creq;
986
987         c->status = dcerpc_ndr_request_recv(req);
988         if (!composite_is_ok(c)) return;
989
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));
992                 return;
993         }
994
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) {
998                 case 24: {
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;
1005                         break;
1006                 }
1007                 case 28:
1008                         s->drsuapi1.remote_info28 = s->drsuapi1.bind_r.out.bind_info->info.info28;
1009                         break;
1010                 }
1011         }
1012
1013         becomeDC_drsuapi1_add_entry_send(s);
1014 }
1015
1016 static void becomeDC_drsuapi1_add_entry_recv(struct rpc_request *req);
1017
1018 static void becomeDC_drsuapi1_add_entry_send(struct libnet_BecomeDC_state *s)
1019 {
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;
1027
1028         ZERO_STRUCT(zero_sid);
1029
1030         /* choose a random invocationId */
1031         s->dest_dsa.invocation_id = GUID_random();
1032
1033         r = talloc_zero(s, struct drsuapi_DsAddEntry);
1034         if (composite_nomem(r, c)) return;
1035
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;
1044
1045         /* allocate attribute array */
1046         num_attrs       = 11;
1047         attrs           = talloc_array(r, struct drsuapi_DsReplicaAttribute, num_attrs);
1048         if (composite_nomem(attrs, c)) return;
1049
1050         /* ntSecurityDescriptor */
1051         {
1052                 struct drsuapi_DsAttributeValueSecurityDescriptor *vs;
1053                 struct security_descriptor *v;
1054                 struct dom_sid *domain_admins_sid;
1055                 const char *domain_admins_sid_str;
1056
1057                 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueSecurityDescriptor, 1);
1058                 if (composite_nomem(vs, c)) return;
1059
1060                 domain_admins_sid = dom_sid_add_rid(vs, s->domain.sid, DOMAIN_RID_ADMINS);
1061                 if (composite_nomem(domain_admins_sid, c)) return;
1062
1063                 domain_admins_sid_str = dom_sid_string(domain_admins_sid, domain_admins_sid);
1064                 if (composite_nomem(domain_admins_sid_str, c)) return;
1065
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 |
1075                                                SEC_ADS_LIST |
1076                                                SEC_ADS_READ_PROP |
1077                                                SEC_ADS_LIST_OBJECT,
1078                                                0,
1079                                                /* domain admins */
1080                                                domain_admins_sid_str,
1081                                                SEC_ACE_TYPE_ACCESS_ALLOWED,
1082                                                SEC_STD_REQUIRED |
1083                                                SEC_ADS_CREATE_CHILD |
1084                                                SEC_ADS_LIST |
1085                                                SEC_ADS_SELF_WRITE |
1086                                                SEC_ADS_READ_PROP |
1087                                                SEC_ADS_WRITE_PROP |
1088                                                SEC_ADS_DELETE_TREE |
1089                                                SEC_ADS_LIST_OBJECT |
1090                                                SEC_ADS_CONTROL_ACCESS,
1091                                                0,
1092                                                /* system */
1093                                                SID_NT_SYSTEM,
1094                                                SEC_ACE_TYPE_ACCESS_ALLOWED,
1095                                                SEC_STD_REQUIRED |
1096                                                SEC_ADS_CREATE_CHILD |
1097                                                SEC_ADS_DELETE_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                                                /* end */
1107                                                NULL);
1108                 if (composite_nomem(v, c)) return;
1109
1110                 vs[0].sd                = v;
1111
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;
1115
1116                 i++;
1117         }
1118
1119         /* objectClass: nTDSDSA */
1120         {
1121                 struct drsuapi_DsAttributeValueObjectClassId *vs;
1122                 enum drsuapi_DsObjectClassId *v;
1123
1124                 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueObjectClassId, 1);
1125                 if (composite_nomem(vs, c)) return;
1126
1127                 v = talloc_array(vs, enum drsuapi_DsObjectClassId, 1);
1128                 if (composite_nomem(v, c)) return;
1129
1130                 /* value for nTDSDSA */
1131                 v[0]                    = 0x0017002F;
1132
1133                 vs[0].objectClassId     = &v[0];
1134
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;
1138
1139                 i++;
1140         }
1141
1142         /* objectCategory: CN=NTDS-DSA,CN=Schema,... */
1143         {
1144                 struct drsuapi_DsAttributeValueDNString *vs;
1145                 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1146
1147                 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 1);
1148                 if (composite_nomem(vs, c)) return;
1149
1150                 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 1);
1151                 if (composite_nomem(v, c)) return;
1152
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;
1159
1160                 vs[0].object            = &v[0];
1161
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;
1165
1166                 i++;
1167         }
1168
1169         /* invocationId: random guid */
1170         {
1171                 struct drsuapi_DsAttributeValueGUID *vs;
1172                 struct GUID *v;
1173
1174                 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueGUID, 1);
1175                 if (composite_nomem(vs, c)) return;
1176
1177                 v = talloc_array(vs, struct GUID, 1);
1178                 if (composite_nomem(v, c)) return;
1179
1180                 /* value for nTDSDSA */
1181                 v[0]                    = s->dest_dsa.invocation_id;
1182
1183                 vs[0].guid              = &v[0];
1184
1185                 attrs[i].attid                                  = DRSUAPI_ATTRIBUTE_invocationId;
1186                 attrs[i].value_ctr.guid.num_values              = 1;
1187                 attrs[i].value_ctr.guid.values                  = vs;
1188
1189                 i++;
1190         }
1191
1192         /* hasMasterNCs: ... */
1193         {
1194                 struct drsuapi_DsAttributeValueDNString *vs;
1195                 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1196
1197                 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 3);
1198                 if (composite_nomem(vs, c)) return;
1199
1200                 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 3);
1201                 if (composite_nomem(v, c)) return;
1202
1203                 v[0].guid               = GUID_zero();
1204                 v[0].sid                = zero_sid;
1205                 v[0].dn                 = s->forest.config_dn_str;
1206
1207                 v[1].guid               = GUID_zero();
1208                 v[1].sid                = zero_sid;
1209                 v[1].dn                 = s->domain.dn_str;
1210
1211                 v[2].guid               = GUID_zero();
1212                 v[2].sid                = zero_sid;
1213                 v[2].dn                 = s->forest.schema_dn_str;
1214
1215                 vs[0].object            = &v[0];
1216                 vs[1].object            = &v[1];
1217                 vs[2].object            = &v[2];
1218
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;
1222
1223                 i++;
1224         }
1225
1226         /* msDS-hasMasterNCs: ... */
1227         {
1228                 struct drsuapi_DsAttributeValueDNString *vs;
1229                 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1230
1231                 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 3);
1232                 if (composite_nomem(vs, c)) return;
1233
1234                 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 3);
1235                 if (composite_nomem(v, c)) return;
1236
1237                 v[0].guid               = GUID_zero();
1238                 v[0].sid                = zero_sid;
1239                 v[0].dn                 = s->forest.config_dn_str;
1240
1241                 v[1].guid               = GUID_zero();
1242                 v[1].sid                = zero_sid;
1243                 v[1].dn                 = s->domain.dn_str;
1244
1245                 v[2].guid               = GUID_zero();
1246                 v[2].sid                = zero_sid;
1247                 v[2].dn                 = s->forest.schema_dn_str;
1248
1249                 vs[0].object            = &v[0];
1250                 vs[1].object            = &v[1];
1251                 vs[2].object            = &v[2];
1252
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;
1256
1257                 i++;
1258         }
1259
1260         /* dMDLocation: CN=Schema,... */
1261         {
1262                 struct drsuapi_DsAttributeValueDNString *vs;
1263                 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1264
1265                 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 1);
1266                 if (composite_nomem(vs, c)) return;
1267
1268                 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 1);
1269                 if (composite_nomem(v, c)) return;
1270
1271                 v[0].guid               = GUID_zero();
1272                 v[0].sid                = zero_sid;
1273                 v[0].dn                 = s->forest.schema_dn_str;
1274
1275                 vs[0].object            = &v[0];
1276
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;
1280
1281                 i++;
1282         }
1283
1284         /* msDS-HasDomainNCs: <domain_partition> */
1285         {
1286                 struct drsuapi_DsAttributeValueDNString *vs;
1287                 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1288
1289                 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 1);
1290                 if (composite_nomem(vs, c)) return;
1291
1292                 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 1);
1293                 if (composite_nomem(v, c)) return;
1294
1295                 v[0].guid               = GUID_zero();
1296                 v[0].sid                = zero_sid;
1297                 v[0].dn                 = s->domain.dn_str;
1298
1299                 vs[0].object            = &v[0];
1300
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;
1304
1305                 i++;
1306         }
1307
1308         /* msDS-Behavior-Version */
1309         {
1310                 struct drsuapi_DsAttributeValueUINT32 *vs;
1311                 uint32_t *v;
1312
1313                 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueUINT32, 1);
1314                 if (composite_nomem(vs, c)) return;
1315
1316                 v = talloc_array(vs, uint32_t, 1);
1317                 if (composite_nomem(v, c)) return;
1318
1319                 v[0]                    = 0x00000002;
1320
1321                 vs[0].value             = &v[0];
1322
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;
1326
1327                 i++;
1328         }
1329
1330         /* systemFlags */
1331         {
1332                 struct drsuapi_DsAttributeValueUINT32 *vs;
1333                 uint32_t *v;
1334
1335                 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueUINT32, 1);
1336                 if (composite_nomem(vs, c)) return;
1337
1338                 v = talloc_array(vs, uint32_t, 1);
1339                 if (composite_nomem(v, c)) return;
1340
1341                 v[0]                    = SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE;
1342
1343                 vs[0].value             = &v[0];
1344
1345                 attrs[i].attid                                  = DRSUAPI_ATTRIBUTE_systemFlags;
1346                 attrs[i].value_ctr.uint32.num_values            = 1;
1347                 attrs[i].value_ctr.uint32.values                = vs;
1348
1349                 i++;
1350         }
1351
1352         /* serverReference: ... */
1353         {
1354                 struct drsuapi_DsAttributeValueDNString *vs;
1355                 struct drsuapi_DsReplicaObjectIdentifier3 *v;
1356
1357                 vs = talloc_array(attrs, struct drsuapi_DsAttributeValueDNString, 1);
1358                 if (composite_nomem(vs, c)) return;
1359
1360                 v = talloc_array(vs, struct drsuapi_DsReplicaObjectIdentifier3, 1);
1361                 if (composite_nomem(v, c)) return;
1362
1363                 v[0].guid               = GUID_zero();
1364                 v[0].sid                = zero_sid;
1365                 v[0].dn                 = s->dest_dsa.computer_dn_str;
1366
1367                 vs[0].object            = &v[0];
1368
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;
1372
1373                 i++;
1374         }
1375
1376         /* truncate the attribute list to the attribute count we have filled in */
1377         num_attrs = i;
1378
1379         /* setup request structure */
1380         r->in.bind_handle                                               = &s->drsuapi1.bind_handle;
1381         r->in.level                                                     = 2;
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;
1387
1388         req = dcerpc_drsuapi_DsAddEntry_send(s->drsuapi1.pipe, r, r);
1389         composite_continue_rpc(c, req, becomeDC_drsuapi1_add_entry_recv, s);
1390 }
1391
1392 static void becomeDC_drsuapi1_add_entry_recv(struct rpc_request *req)
1393 {
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);
1399
1400         c->status = dcerpc_ndr_request_recv(req);
1401         if (!composite_is_ok(c)) return;
1402
1403         if (!W_ERROR_IS_OK(r->out.result)) {
1404                 composite_error(c, werror_to_ntstatus(r->out.result));
1405                 return;
1406         }
1407
1408         becomeDC_connect_ldap2(s);
1409 }
1410
1411 static NTSTATUS becomeDC_ldap2_modify_computer(struct libnet_BecomeDC_state *s)
1412 {
1413         int ret;
1414         struct ldb_message *msg;
1415         uint32_t i;
1416         uint32_t user_account_control = UF_SERVER_TRUST_ACCOUNT |
1417                                         UF_TRUSTED_FOR_DELEGATION;
1418
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;
1422         }
1423
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);
1429
1430         ret = ldb_msg_add_fmt(msg, "userAccountControl", "%u", user_account_control);
1431         if (ret != 0) {
1432                 talloc_free(msg);
1433                 return NT_STATUS_NO_MEMORY;
1434         }
1435
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;
1440         }
1441
1442         ret = ldb_modify(s->ldap2.ldb, msg);
1443         talloc_free(msg);
1444         if (ret != LDB_SUCCESS) {
1445                 return NT_STATUS_LDAP(ret);
1446         }
1447
1448         s->dest_dsa.user_account_control = user_account_control;
1449
1450         return NT_STATUS_OK;
1451 }
1452
1453 static NTSTATUS becomeDC_ldap2_move_computer(struct libnet_BecomeDC_state *s)
1454 {
1455         int ret;
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[] = {
1461                 "1.1",
1462                 NULL
1463         };
1464
1465         basedn = ldb_dn_new_fmt(s, s->ldap2.ldb, "<WKGUID=a361b2ffffd211d1aa4b00c04fd7d83a,%s>",
1466                                 s->domain.dn_str);
1467         NT_STATUS_HAVE_NO_MEMORY(basedn);
1468
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) {
1475                 talloc_free(r);
1476                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1477         }
1478
1479         old_dn = ldb_dn_new(r, s->ldap2.ldb, s->dest_dsa.computer_dn_str);
1480         NT_STATUS_HAVE_NO_MEMORY(old_dn);
1481
1482         new_dn = r->msgs[0]->dn;
1483
1484         if (!ldb_dn_add_child_fmt(new_dn, "CN=%s", s->dest_dsa.netbios_name)) {
1485                 talloc_free(r);
1486                 return NT_STATUS_NO_MEMORY;
1487         }
1488
1489         if (ldb_dn_compare(old_dn, new_dn) == 0) {
1490                 /* we don't need to rename if the old and new dn match */
1491                 talloc_free(r);
1492                 return NT_STATUS_OK;
1493         }
1494
1495         ret = ldb_rename(s->ldap2.ldb, old_dn, new_dn);
1496         talloc_free(r);
1497         if (ret != LDB_SUCCESS) {
1498                 return NT_STATUS_LDAP(ret);
1499         }
1500
1501         return NT_STATUS_OK;
1502 }
1503
1504 static void becomeDC_connect_ldap2(struct libnet_BecomeDC_state *s)
1505 {
1506         struct composite_context *c = s->creq;
1507
1508         c->status = becomeDC_ldap_connect(s, &s->ldap2);
1509         if (!composite_is_ok(c)) return;
1510
1511         c->status = becomeDC_ldap2_modify_computer(s);
1512         if (!composite_is_ok(c)) return;
1513
1514         c->status = becomeDC_ldap2_move_computer(s);
1515         if (!composite_is_ok(c)) return;
1516
1517         composite_error(c, NT_STATUS_NOT_IMPLEMENTED);
1518 }
1519
1520 struct composite_context *libnet_BecomeDC_send(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_BecomeDC *r)
1521 {
1522         struct composite_context *c;
1523         struct libnet_BecomeDC_state *s;
1524         char *tmp_name;
1525
1526         c = composite_create(mem_ctx, ctx->event_ctx);
1527         if (c == NULL) return NULL;
1528
1529         s = talloc_zero(c, struct libnet_BecomeDC_state);
1530         if (composite_nomem(s, c)) return c;
1531         c->private_data = s;
1532         s->creq         = c;
1533         s->libnet       = ctx;
1534
1535         /* Domain input */
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;
1542
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;
1546
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;
1550
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;
1557
1558         becomeDC_send_cldap(s);
1559         return c;
1560 }
1561
1562 NTSTATUS libnet_BecomeDC_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, struct libnet_BecomeDC *r)
1563 {
1564         NTSTATUS status;
1565
1566         status = composite_wait(c);
1567
1568         ZERO_STRUCT(r->out);
1569
1570         talloc_free(c);
1571         return status;
1572 }
1573
1574 NTSTATUS libnet_BecomeDC(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_BecomeDC *r)
1575 {
1576         NTSTATUS status;
1577         struct composite_context *c;
1578         c = libnet_BecomeDC_send(ctx, mem_ctx, r);
1579         status = libnet_BecomeDC_recv(c, mem_ctx, r);
1580         return status;
1581 }