~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/libnet/libnet_become_dc.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   Unix SMB/CIFS implementation.
 
3
 
 
4
   Copyright (C) Stefan Metzmacher <metze@samba.org> 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 3 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, see <http://www.gnu.org/licenses/>.
 
18
*/
 
19
 
 
20
#include "includes.h"
 
21
#include "libnet/libnet.h"
 
22
#include "libcli/composite/composite.h"
 
23
#include "libcli/cldap/cldap.h"
 
24
#include "lib/ldb/include/ldb.h"
 
25
#include "lib/ldb/include/ldb_errors.h"
 
26
#include "lib/ldb_wrap.h"
 
27
#include "dsdb/samdb/samdb.h"
 
28
#include "dsdb/common/flags.h"
 
29
#include "librpc/gen_ndr/ndr_drsuapi_c.h"
 
30
#include "libcli/security/security.h"
 
31
#include "librpc/gen_ndr/ndr_misc.h"
 
32
#include "librpc/gen_ndr/ndr_security.h"
 
33
#include "librpc/gen_ndr/ndr_nbt.h"
 
34
#include "librpc/gen_ndr/ndr_drsuapi.h"
 
35
#include "auth/gensec/gensec.h"
 
36
#include "param/param.h"
 
37
 
 
38
/*****************************************************************************
 
39
 * Windows 2003 (w2k3) does the following steps when changing the server role
 
40
 * from domain member to domain controller
 
41
 *
 
42
 * We mostly do the same.
 
43
 *****************************************************************************/
 
44
 
 
45
/*
 
46
 * lookup DC:
 
47
 * - using nbt name<1C> request and a samlogon mailslot request
 
48
 * or
 
49
 * - using a DNS SRV _ldap._tcp.dc._msdcs. request and a CLDAP netlogon request
 
50
 *
 
51
 * see: becomeDC_recv_cldap() and becomeDC_send_cldap()
 
52
 */
 
53
 
 
54
/*
 
55
 * Open 1st LDAP connection to the DC using admin credentials
 
56
 *
 
57
 * see: becomeDC_connect_ldap1() and becomeDC_ldap_connect()
 
58
 */
 
59
 
 
60
/*
 
61
 * LDAP search 1st LDAP connection:
 
62
 *
 
63
 * see: becomeDC_ldap1_rootdse()
 
64
 *
 
65
 * Request:
 
66
 *      basedn: ""
 
67
 *      scope:  base
 
68
 *      filter: (objectClass=*)
 
69
 *      attrs:  *
 
70
 * Result:
 
71
 *      ""
 
72
 *              currentTime:            20061202155100.0Z
 
73
 *              subschemaSubentry:      CN=Aggregate,CN=Schema,CN=Configuration,<domain_partition>
 
74
 *              dsServiceName:          CN=<netbios_name>,CN=Servers,CN=<site_name>,CN=Sites,CN=Configuration,<domain_partition>
 
75
 *              namingContexts:         <domain_partition>
 
76
 *                                      CN=Configuration,<domain_partition>
 
77
 *                                      CN=Schema,CN=Configuration,<domain_partition>
 
78
 *              defaultNamingContext:   <domain_partition>
 
79
 *              schemaNamingContext:    CN=Schema,CN=Configuration,<domain_partition>
 
80
 *              configurationNamingContext:CN=Configuration,<domain_partition>
 
81
 *              rootDomainNamingContext:<domain_partition>
 
82
 *              supportedControl:       ...
 
83
 *              supportedLDAPVersion:   3
 
84
 *                                      2
 
85
 *              supportedLDAPPolicies:  ...
 
86
 *              highestCommitedUSN:     ...
 
87
 *              supportedSASLMechanisms:GSSAPI
 
88
 *                                      GSS-SPNEGO
 
89
 *                                      EXTERNAL
 
90
 *                                      DIGEST-MD5
 
91
 *              dnsHostName:            <dns_host_name>
 
92
 *              ldapServiceName:        <domain_dns_name>:<netbios_name>$@<REALM>
 
93
 *              serverName:             CN=Servers,CN=<site_name>,CN=Sites,CN=Configuration,<domain_partition>
 
94
 *              supportedCapabilities:  ...
 
95
 *              isSyncronized:          TRUE
 
96
 *              isGlobalCatalogReady:   TRUE
 
97
 *              domainFunctionality:    0
 
98
 *              forestFunctionality:    0
 
99
 *              domainControllerFunctionality: 2
 
100
 */
 
101
 
 
102
/*
 
103
 * LDAP search 1st LDAP connection:
 
104
 *
 
105
 * see: becomeDC_ldap1_crossref_behavior_version()
 
106
 *
 
107
 * Request:
 
108
 *      basedn: CN=Configuration,<domain_partition>
 
109
 *      scope:  one
 
110
 *      filter: (cn=Partitions)
 
111
 *      attrs:  msDS-Behavior-Version
 
112
 * Result:
 
113
 *      CN=Partitions,CN=Configuration,<domain_partition>
 
114
 *              msDS-Behavior-Version:  0
 
115
 */
 
116
 
 
117
/*
 
118
 * LDAP search 1st LDAP connection:
 
119
 *
 
120
 * NOTE: this seems to be a bug! as the messageID of the LDAP message is corrupted!
 
121
 *
 
122
 * not implemented here
 
123
 * 
 
124
 * Request:
 
125
 *      basedn: CN=Schema,CN=Configuration,<domain_partition>
 
126
 *      scope:  one
 
127
 *      filter: (cn=Partitions)
 
128
 *      attrs:  msDS-Behavior-Version
 
129
 * Result:
 
130
 *      <none>
 
131
 *
 
132
 */
 
133
 
 
134
/*
 
135
 * LDAP search 1st LDAP connection:
 
136
 *
 
137
 * see: becomeDC_ldap1_domain_behavior_version()
 
138
 * 
 
139
 * Request:
 
140
 *      basedn: <domain_partition>
 
141
 *      scope:  base
 
142
 *      filter: (objectClass=*)
 
143
 *      attrs:  msDS-Behavior-Version
 
144
 * Result:
 
145
 *      <domain_partition>
 
146
 *              msDS-Behavior-Version:  0
 
147
 */
 
148
 
 
149
/*
 
150
 * LDAP search 1st LDAP connection:
 
151
 * 
 
152
 * see: becomeDC_ldap1_schema_object_version()
 
153
 *
 
154
 * Request:
 
155
 *      basedn: CN=Schema,CN=Configuration,<domain_partition>
 
156
 *      scope:  base
 
157
 *      filter: (objectClass=*)
 
158
 *      attrs:  objectVersion
 
159
 * Result:
 
160
 *      CN=Schema,CN=Configuration,<domain_partition>
 
161
 *              objectVersion:  30
 
162
 */
 
163
 
 
164
/*
 
165
 * LDAP search 1st LDAP connection:
 
166
 * 
 
167
 * not implemented, because the information is already there
 
168
 *
 
169
 * Request:
 
170
 *      basedn: ""
 
171
 *      scope:  base
 
172
 *      filter: (objectClass=*)
 
173
 *      attrs:  defaultNamingContext
 
174
 *              dnsHostName
 
175
 * Result:
 
176
 *      ""
 
177
 *              defaultNamingContext:   <domain_partition>
 
178
 *              dnsHostName:            <dns_host_name>
 
179
 */
 
180
 
 
181
/*
 
182
 * LDAP search 1st LDAP connection:
 
183
 *
 
184
 * see: becomeDC_ldap1_infrastructure_fsmo()
 
185
 * 
 
186
 * Request:
 
187
 *      basedn: <WKGUID=2fbac1870ade11d297c400c04fd8d5cd,domain_partition>
 
188
 *      scope:  base
 
189
 *      filter: (objectClass=*)
 
190
 *      attrs:  1.1
 
191
 * Result:
 
192
 *      CN=Infrastructure,<domain_partition>
 
193
 */
 
194
 
 
195
/*
 
196
 * LDAP search 1st LDAP connection:
 
197
 *
 
198
 * see: becomeDC_ldap1_w2k3_update_revision()
 
199
 *
 
200
 * Request:
 
201
 *      basedn: CN=Windows2003Update,CN=DomainUpdates,CN=System,<domain_partition>
 
202
 *      scope:  base
 
203
 *      filter: (objectClass=*)
 
204
 *      attrs:  revision
 
205
 * Result:
 
206
 *      CN=Windows2003Update,CN=DomainUpdates,CN=System,<domain_partition>
 
207
 *              revision:       8
 
208
 */
 
209
 
 
210
/*
 
211
 * LDAP search 1st LDAP connection:
 
212
 *
 
213
 * see: becomeDC_ldap1_infrastructure_fsmo()
 
214
 *
 
215
 * Request:
 
216
 *      basedn: CN=Infrastructure,<domain_partition>
 
217
 *      scope:  base
 
218
 *      filter: (objectClass=*)
 
219
 *      attrs:  fSMORoleOwner
 
220
 * Result:
 
221
 *      CN=Infrastructure,<domain_partition>
 
222
 *              fSMORoleOwner:  CN=NTDS Settings,<infrastructure_fsmo_server_object>
 
223
 */
 
224
 
 
225
/*
 
226
 * LDAP search 1st LDAP connection:
 
227
 *
 
228
 * see: becomeDC_ldap1_infrastructure_fsmo()
 
229
 *
 
230
 * Request:
 
231
 *      basedn: <infrastructure_fsmo_server_object>
 
232
 *      scope:  base
 
233
 *      filter: (objectClass=*)
 
234
 *      attrs:  dnsHostName
 
235
 * Result:
 
236
 *      <infrastructure_fsmo_server_object>
 
237
 *              dnsHostName:    <dns_host_name>
 
238
 */
 
239
 
 
240
/*
 
241
 * LDAP search 1st LDAP connection:
 
242
 *
 
243
 * see: becomeDC_ldap1_infrastructure_fsmo()
 
244
 *
 
245
 * Request:
 
246
 *      basedn: CN=NTDS Settings,<infrastructure_fsmo_server_object>
 
247
 *      scope:  base
 
248
 *      filter: (objectClass=*)
 
249
 *      attrs:  objectGUID
 
250
 * Result:
 
251
 *      CN=NTDS Settings,<infrastructure_fsmo_server_object>
 
252
 *              objectGUID:     <object_guid>
 
253
 */
 
254
 
 
255
/*
 
256
 * LDAP search 1st LDAP connection:
 
257
 * 
 
258
 * see: becomeDC_ldap1_rid_manager_fsmo()
 
259
 *
 
260
 * Request:
 
261
 *      basedn: <domain_partition>
 
262
 *      scope:  base
 
263
 *      filter: (objectClass=*)
 
264
 *      attrs:  rIDManagerReference
 
265
 * Result:
 
266
 *      <domain_partition>
 
267
 *              rIDManagerReference:    CN=RID Manager$,CN=System,<domain_partition>
 
268
 */
 
269
 
 
270
/*
 
271
 * LDAP search 1st LDAP connection:
 
272
 * 
 
273
 * see: becomeDC_ldap1_rid_manager_fsmo()
 
274
 *
 
275
 * Request:
 
276
 *      basedn: CN=RID Manager$,CN=System,<domain_partition>
 
277
 *      scope:  base
 
278
 *      filter: (objectClass=*)
 
279
 *      attrs:  fSMORoleOwner
 
280
 * Result:
 
281
 *      CN=Infrastructure,<domain_partition>
 
282
 *              fSMORoleOwner:  CN=NTDS Settings,<rid_manager_fsmo_server_object>
 
283
 */
 
284
 
 
285
/*
 
286
 * LDAP search 1st LDAP connection:
 
287
 *
 
288
 * see: becomeDC_ldap1_rid_manager_fsmo()
 
289
 *
 
290
 * Request:
 
291
 *      basedn: <rid_manager_fsmo_server_object>
 
292
 *      scope:  base
 
293
 *      filter: (objectClass=*)
 
294
 *      attrs:  dnsHostName
 
295
 * Result:
 
296
 *      <rid_manager_fsmo_server_object>
 
297
 *              dnsHostName:    <dns_host_name>
 
298
 */
 
299
 
 
300
/*
 
301
 * LDAP search 1st LDAP connection:
 
302
 *
 
303
 * see: becomeDC_ldap1_rid_manager_fsmo()
 
304
 *
 
305
 * Request:
 
306
 *      basedn: CN=NTDS Settings,<rid_manager_fsmo_server_object>
 
307
 *      scope:  base
 
308
 *      filter: (objectClass=*)
 
309
 *      attrs:  msDs-ReplicationEpoch
 
310
 * Result:
 
311
 *      CN=NTDS Settings,<rid_manager_fsmo_server_object>
 
312
 */
 
313
 
 
314
/*
 
315
 * LDAP search 1st LDAP connection:
 
316
 *
 
317
 * see: becomeDC_ldap1_site_object()
 
318
 *
 
319
 * Request:
 
320
 *      basedn: CN=<new_dc_site_name>,CN=Sites,CN=Configuration,<domain_partition>
 
321
 *      scope:  base
 
322
 *      filter: (objectClass=*)
 
323
 *      attrs:
 
324
 * Result:
 
325
 *      CN=<new_dc_site_name>,CN=Sites,CN=Configuration,<domain_partition>
 
326
 *              objectClass:    top
 
327
 *                              site
 
328
 *              cn:             <new_dc_site_name>
 
329
 *              distinguishedName:CN=<new_dc_site_name>,CN=Sites,CN=Configuration,<domain_partition>
 
330
 *              instanceType:   4
 
331
 *              whenCreated:    ...
 
332
 *              whenChanged:    ...
 
333
 *              uSNCreated:     ...
 
334
 *              uSNChanged:     ...
 
335
 *              showInAdvancedViewOnly: TRUE
 
336
 *              name:           <new_dc_site_name>
 
337
 *              objectGUID:     <object_guid>
 
338
 *              systemFlags:    1107296256 <0x42000000>
 
339
 *              objectCategory: CN=Site,C=Schema,CN=Configuration,<domain_partition>
 
340
 */
 
341
 
 
342
/***************************************************************
 
343
 * Add this stage we call the check_options() callback function
 
344
 * of the caller, to see if he wants us to continue
 
345
 *
 
346
 * see: becomeDC_check_options()
 
347
 ***************************************************************/
 
348
 
 
349
/*
 
350
 * LDAP search 1st LDAP connection:
 
351
 *
 
352
 * see: becomeDC_ldap1_computer_object()
 
353
 *
 
354
 * Request:
 
355
 *      basedn: <domain_partition>
 
356
 *      scope:  sub
 
357
 *      filter: (&(|(objectClass=user)(objectClass=computer))(sAMAccountName=<new_dc_account_name>))
 
358
 *      attrs:  distinguishedName
 
359
 *              userAccountControl
 
360
 * Result:
 
361
 *      CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
 
362
 *              distinguishedName:      CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
 
363
 *              userAccoountControl:    4096 <0x1000>
 
364
 */
 
365
 
 
366
/*
 
367
 * LDAP search 1st LDAP connection:
 
368
 *
 
369
 * see: becomeDC_ldap1_server_object_1()
 
370
 *
 
371
 * Request:
 
372
 *      basedn: CN=<new_dc_netbios_name>,CN=Servers,CN=<new_dc_site_name>,CN=Sites,CN=Configuration,<domain_partition>
 
373
 *      scope:  base
 
374
 *      filter: (objectClass=*)
 
375
 *      attrs:
 
376
 * Result:
 
377
 *      <noSuchObject>
 
378
 *      <matchedDN:CN=Servers,CN=<new_dc_site_name>,CN=Sites,CN=Configuration,<domain_partition>>
 
379
 */
 
380
 
 
381
/*
 
382
 * LDAP search 1st LDAP connection:
 
383
 *
 
384
 * see: becomeDC_ldap1_server_object_2()
 
385
 * 
 
386
 * Request:
 
387
 *      basedn: CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
 
388
 *      scope:  base
 
389
 *      filter: (objectClass=*)
 
390
 *      attrs:  serverReferenceBL
 
391
 *      typesOnly: TRUE!!!
 
392
 * Result:
 
393
 *      CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
 
394
 */
 
395
 
 
396
/*
 
397
 * LDAP add 1st LDAP connection:
 
398
 * 
 
399
 * see: becomeDC_ldap1_server_object_add()
 
400
 *
 
401
 * Request:
 
402
 *      CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
 
403
 *      objectClass:    server
 
404
 *      systemFlags:    50000000 <0x2FAF080>
 
405
 *      serverReference:CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
 
406
 * Result:
 
407
 *      <success>
 
408
 */
 
409
 
 
410
/*
 
411
 * LDAP search 1st LDAP connection:
 
412
 *
 
413
 * not implemented, maybe we can add that later
 
414
 *
 
415
 * Request:
 
416
 *      basedn: CN=NTDS Settings,CN=<new_dc_netbios_name>,CN=Servers,CN=<new_dc_site_name>,CN=Sites,CN=Configuration,<domain_partition>
 
417
 *      scope:  base
 
418
 *      filter: (objectClass=*)
 
419
 *      attrs:
 
420
 * Result:
 
421
 *      <noSuchObject>
 
422
 *      <matchedDN:CN=<new_dc_netbios_name>,CN=Servers,CN=<new_dc_site_name>,CN=Sites,CN=Configuration,<domain_partition>>
 
423
 */
 
424
 
 
425
/*
 
426
 * LDAP search 1st LDAP connection:
 
427
 *
 
428
 * not implemented because it gives no new information
 
429
 * 
 
430
 * Request:
 
431
 *      basedn: CN=Partitions,CN=Configuration,<domain_partition>
 
432
 *      scope:  sub
 
433
 *      filter: (nCName=<domain_partition>)
 
434
 *      attrs:  nCName
 
435
 *              dnsRoot
 
436
 *      controls: LDAP_SERVER_EXTENDED_DN_OID:critical=false
 
437
 * Result:
 
438
 *      <GUID=<hex_guid>>;CN=<domain_netbios_name>,CN=Partitions,<domain_partition>>
 
439
 *              nCName:         <GUID=<hex_guid>>;<SID=<hex_sid>>;<domain_partition>>
 
440
 *              dnsRoot:        <domain_dns_name>
 
441
 */
 
442
 
 
443
/*
 
444
 * LDAP modify 1st LDAP connection:
 
445
 *
 
446
 * see: becomeDC_ldap1_server_object_modify()
 
447
 * 
 
448
 * Request (add):
 
449
 *      CN=<new_dc_netbios_name>,CN=Servers,CN=<new_dc_site_name>,CN=Sites,CN=Configuration,<domain_partition>>
 
450
 *      serverReference:CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
 
451
 * Result:
 
452
 *      <attributeOrValueExist>
 
453
 */
 
454
 
 
455
/*
 
456
 * LDAP modify 1st LDAP connection:
 
457
 *
 
458
 * see: becomeDC_ldap1_server_object_modify()
 
459
 *
 
460
 * Request (replace):
 
461
 *      CN=<new_dc_netbios_name>,CN=Servers,CN=<new_dc_site_name>,CN=Sites,CN=Configuration,<domain_partition>>
 
462
 *      serverReference:CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
 
463
 * Result:
 
464
 *      <success>
 
465
 */
 
466
 
 
467
/*
 
468
 * Open 1st DRSUAPI connection to the DC using admin credentials
 
469
 * DsBind with DRSUAPI_DS_BIND_GUID_W2K3 ("6afab99c-6e26-464a-975f-f58f105218bc")
 
470
 * (w2k3 does 2 DsBind() calls here..., where is first is unused and contains garbage at the end)
 
471
 *
 
472
 * see: becomeDC_drsuapi_connect_send(), becomeDC_drsuapi1_connect_recv(),
 
473
 *      becomeDC_drsuapi_bind_send(), becomeDC_drsuapi_bind_recv() and becomeDC_drsuapi1_bind_recv()
 
474
 */
 
475
 
 
476
/*
 
477
 * DsAddEntry to create the CN=NTDS Settings,CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name, ...
 
478
 * on the 1st DRSUAPI connection
 
479
 *
 
480
 * see: becomeDC_drsuapi1_add_entry_send() and becomeDC_drsuapi1_add_entry_recv()
 
481
 */
 
482
 
 
483
/***************************************************************
 
484
 * Add this stage we call the prepare_db() callback function
 
485
 * of the caller, to see if he wants us to continue
 
486
 *
 
487
 * see: becomeDC_prepare_db()
 
488
 ***************************************************************/
 
489
 
 
490
/*
 
491
 * Open 2nd and 3rd DRSUAPI connection to the DC using admin credentials
 
492
 * - a DsBind with DRSUAPI_DS_BIND_GUID_W2K3 ("6afab99c-6e26-464a-975f-f58f105218bc")
 
493
 *   on the 2nd connection
 
494
 *
 
495
 * see: becomeDC_drsuapi_connect_send(), becomeDC_drsuapi2_connect_recv(),
 
496
 *      becomeDC_drsuapi_bind_send(), becomeDC_drsuapi_bind_recv(), becomeDC_drsuapi2_bind_recv()
 
497
 *      and becomeDC_drsuapi3_connect_recv()
 
498
 */
 
499
 
 
500
/*
 
501
 * replicate CN=Schema,CN=Configuration,...
 
502
 * on the 3rd DRSUAPI connection and the bind_handle from the 2nd connection
 
503
 *
 
504
 * see: becomeDC_drsuapi_pull_partition_send(), becomeDC_drsuapi_pull_partition_recv(),
 
505
 *      becomeDC_drsuapi3_pull_schema_send() and becomeDC_drsuapi3_pull_schema_recv()
 
506
 *
 
507
 ***************************************************************
 
508
 * Add this stage we call the schema_chunk() callback function
 
509
 * for each replication message
 
510
 ***************************************************************/
 
511
 
 
512
/*
 
513
 * replicate CN=Configuration,...
 
514
 * on the 3rd DRSUAPI connection and the bind_handle from the 2nd connection
 
515
 *
 
516
 * see: becomeDC_drsuapi_pull_partition_send(), becomeDC_drsuapi_pull_partition_recv(),
 
517
 *      becomeDC_drsuapi3_pull_config_send() and becomeDC_drsuapi3_pull_config_recv()
 
518
 *
 
519
 ***************************************************************
 
520
 * Add this stage we call the config_chunk() callback function
 
521
 * for each replication message
 
522
 ***************************************************************/
 
523
 
 
524
/*
 
525
 * LDAP unbind on the 1st LDAP connection
 
526
 *
 
527
 * not implemented, because it's not needed...
 
528
 */
 
529
 
 
530
/*
 
531
 * Open 2nd LDAP connection to the DC using admin credentials
 
532
 *
 
533
 * see: becomeDC_connect_ldap2() and becomeDC_ldap_connect()
 
534
 */
 
535
 
 
536
/*
 
537
 * LDAP search 2nd LDAP connection:
 
538
 * 
 
539
 * not implemented because it gives no new information
 
540
 * same as becomeDC_ldap1_computer_object()
 
541
 *
 
542
 * Request:
 
543
 *      basedn: <domain_partition>
 
544
 *      scope:  sub
 
545
 *      filter: (&(|(objectClass=user)(objectClass=computer))(sAMAccountName=<new_dc_account_name>))
 
546
 *      attrs:  distinguishedName
 
547
 *              userAccountControl
 
548
 * Result:
 
549
 *      CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
 
550
 *              distinguishedName:      CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
 
551
 *              userAccoountControl:    4096 <0x00001000>
 
552
 */
 
553
 
 
554
/*
 
555
 * LDAP search 2nd LDAP connection:
 
556
 * 
 
557
 * not implemented because it gives no new information
 
558
 * same as becomeDC_ldap1_computer_object()
 
559
 *
 
560
 * Request:
 
561
 *      basedn: CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
 
562
 *      scope:  base
 
563
 *      filter: (objectClass=*)
 
564
 *      attrs:  userAccountControl
 
565
 * Result:
 
566
 *      CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
 
567
 *              userAccoountControl:    4096 <0x00001000>
 
568
 */
 
569
 
 
570
/*
 
571
 * LDAP modify 2nd LDAP connection:
 
572
 *
 
573
 * see: becomeDC_ldap2_modify_computer()
 
574
 *
 
575
 * Request (replace):
 
576
 *      CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
 
577
 *      userAccoountControl:    532480 <0x82000>
 
578
 * Result:
 
579
 *      <success>
 
580
 */
 
581
 
 
582
/*
 
583
 * LDAP search 2nd LDAP connection:
 
584
 *
 
585
 * see: becomeDC_ldap2_move_computer()
 
586
 * 
 
587
 * Request:
 
588
 *      basedn: <WKGUID=2fbac1870ade11d297c400c04fd8d5cd,<domain_partition>>
 
589
 *      scope:  base
 
590
 *      filter: (objectClass=*)
 
591
 *      attrs:  1.1
 
592
 * Result:
 
593
 *      CN=Domain Controllers,<domain_partition>
 
594
 */
 
595
 
 
596
/*
 
597
 * LDAP search 2nd LDAP connection:
 
598
 *
 
599
 * not implemented because it gives no new information
 
600
 * 
 
601
 * Request:
 
602
 *      basedn: CN=Domain Controllers,<domain_partition>
 
603
 *      scope:  base
 
604
 *      filter: (objectClass=*)
 
605
 *      attrs:  distinguishedName
 
606
 * Result:
 
607
 *      CN=Domain Controller,<domain_partition>
 
608
 *              distinguishedName:      CN=Domain Controllers,<domain_partition>
 
609
 */
 
610
 
 
611
/*
 
612
 * LDAP modifyRDN 2nd LDAP connection:
 
613
 *
 
614
 * see: becomeDC_ldap2_move_computer()
 
615
 * 
 
616
 * Request:
 
617
 *      entry:          CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
 
618
 *      newrdn:         CN=<new_dc_netbios_name>
 
619
 *      deleteoldrdn:   TRUE
 
620
 *      newparent:      CN=Domain Controllers,<domain_partition>
 
621
 * Result:
 
622
 *      <success>
 
623
 */
 
624
 
 
625
/*
 
626
 * LDAP unbind on the 2nd LDAP connection
 
627
 *
 
628
 * not implemented, because it's not needed...
 
629
 */
 
630
 
 
631
/*
 
632
 * replicate Domain Partition
 
633
 * on the 3rd DRSUAPI connection and the bind_handle from the 2nd connection
 
634
 *
 
635
 * see: becomeDC_drsuapi_pull_partition_send(), becomeDC_drsuapi_pull_partition_recv(),
 
636
 *      becomeDC_drsuapi3_pull_domain_send() and becomeDC_drsuapi3_pull_domain_recv()
 
637
 *
 
638
 ***************************************************************
 
639
 * Add this stage we call the domain_chunk() callback function
 
640
 * for each replication message
 
641
 ***************************************************************/
 
642
 
 
643
/* call DsReplicaUpdateRefs() for all partitions like this:
 
644
 *     req1: struct drsuapi_DsReplicaUpdateRefsRequest1
 
645
 *
 
646
 *                 naming_context: struct drsuapi_DsReplicaObjectIdentifier
 
647
 *                     __ndr_size               : 0x000000ae (174)
 
648
 *                     __ndr_size_sid           : 0x00000000 (0)
 
649
 *                     guid                     : 00000000-0000-0000-0000-000000000000
 
650
 *                     sid                      : S-0-0
 
651
 *                     dn                       : 'CN=Schema,CN=Configuration,DC=w2k3,DC=vmnet1,DC=vm,DC=base'
 
652
 *
 
653
 *                 dest_dsa_dns_name        : '4a0df188-a0b8-47ea-bbe5-e614723f16dd._msdcs.w2k3.vmnet1.vm.base'
 
654
 *           dest_dsa_guid            : 4a0df188-a0b8-47ea-bbe5-e614723f16dd
 
655
 *           options                  : 0x0000001c (28)
 
656
 *                 0: DRSUAPI_DS_REPLICA_UPDATE_ASYNCHRONOUS_OPERATION
 
657
 *                 0: DRSUAPI_DS_REPLICA_UPDATE_WRITEABLE
 
658
 *                 1: DRSUAPI_DS_REPLICA_UPDATE_ADD_REFERENCE
 
659
 *                 1: DRSUAPI_DS_REPLICA_UPDATE_DELETE_REFERENCE
 
660
 *                 1: DRSUAPI_DS_REPLICA_UPDATE_0x00000010
 
661
 *
 
662
 * 4a0df188-a0b8-47ea-bbe5-e614723f16dd is the objectGUID the DsAddEntry() returned for the
 
663
 * CN=NTDS Settings,CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name, ...
 
664
 * on the 2nd!!! DRSUAPI connection
 
665
 *
 
666
 * see: becomeDC_drsuapi_update_refs_send(), becomeDC_drsuapi2_update_refs_schema_recv(),
 
667
 *      becomeDC_drsuapi2_update_refs_config_recv() and becomeDC_drsuapi2_update_refs_domain_recv()
 
668
 */
 
669
 
 
670
/*
 
671
 * Windows does opens the 4th and 5th DRSUAPI connection...
 
672
 * and does a DsBind() with the objectGUID from DsAddEntry() as bind_guid
 
673
 * on the 4th connection
 
674
 *
 
675
 * and then 2 full replications of the domain partition on the 5th connection
 
676
 * with the bind_handle from the 4th connection
 
677
 *
 
678
 * not implemented because it gives no new information
 
679
 */
 
680
 
 
681
struct libnet_BecomeDC_state {
 
682
        struct composite_context *creq;
 
683
 
 
684
        struct libnet_context *libnet;
 
685
 
 
686
        struct dom_sid zero_sid;
 
687
 
 
688
        struct {
 
689
                struct cldap_socket *sock;
 
690
                struct cldap_netlogon io;
 
691
                struct NETLOGON_SAM_LOGON_RESPONSE_EX netlogon;
 
692
        } cldap;
 
693
 
 
694
        struct becomeDC_ldap {
 
695
                struct ldb_context *ldb;
 
696
                const struct ldb_message *rootdse;
 
697
        } ldap1, ldap2;
 
698
 
 
699
        struct becomeDC_drsuapi {
 
700
                struct libnet_BecomeDC_state *s;
 
701
                struct dcerpc_binding *binding;
 
702
                struct dcerpc_pipe *pipe;
 
703
                DATA_BLOB gensec_skey;
 
704
                struct drsuapi_DsBind bind_r;
 
705
                struct GUID bind_guid;
 
706
                struct drsuapi_DsBindInfoCtr bind_info_ctr;
 
707
                struct drsuapi_DsBindInfo28 local_info28;
 
708
                struct drsuapi_DsBindInfo28 remote_info28;
 
709
                struct policy_handle bind_handle;
 
710
        } drsuapi1, drsuapi2, drsuapi3;
 
711
 
 
712
        struct libnet_BecomeDC_Domain domain;
 
713
        struct libnet_BecomeDC_Forest forest;
 
714
        struct libnet_BecomeDC_SourceDSA source_dsa;
 
715
        struct libnet_BecomeDC_DestDSA dest_dsa;
 
716
 
 
717
        struct libnet_BecomeDC_Partition schema_part, config_part, domain_part;
 
718
 
 
719
        struct becomeDC_fsmo {
 
720
                const char *dns_name;
 
721
                const char *server_dn_str;
 
722
                const char *ntds_dn_str;
 
723
                struct GUID ntds_guid;
 
724
        } infrastructure_fsmo;
 
725
 
 
726
        struct becomeDC_fsmo rid_manager_fsmo;
 
727
 
 
728
        struct libnet_BecomeDC_CheckOptions _co;
 
729
        struct libnet_BecomeDC_PrepareDB _pp;
 
730
        struct libnet_BecomeDC_StoreChunk _sc;
 
731
        struct libnet_BecomeDC_Callbacks callbacks;
 
732
};
 
733
 
 
734
static void becomeDC_recv_cldap(struct cldap_request *req);
 
735
 
 
736
static void becomeDC_send_cldap(struct libnet_BecomeDC_state *s)
 
737
{
 
738
        struct composite_context *c = s->creq;
 
739
        struct cldap_request *req;
 
740
 
 
741
        s->cldap.io.in.dest_address     = s->source_dsa.address;
 
742
        s->cldap.io.in.dest_port        = lp_cldap_port(s->libnet->lp_ctx);
 
743
        s->cldap.io.in.realm            = s->domain.dns_name;
 
744
        s->cldap.io.in.host             = s->dest_dsa.netbios_name;
 
745
        s->cldap.io.in.user             = NULL;
 
746
        s->cldap.io.in.domain_guid      = NULL;
 
747
        s->cldap.io.in.domain_sid       = NULL;
 
748
        s->cldap.io.in.acct_control     = -1;
 
749
        s->cldap.io.in.version          = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
 
750
        s->cldap.io.in.map_response     = true;
 
751
 
 
752
        s->cldap.sock = cldap_socket_init(s, s->libnet->event_ctx, 
 
753
                                          lp_iconv_convenience(s->libnet->lp_ctx));
 
754
        if (composite_nomem(s->cldap.sock, c)) return;
 
755
 
 
756
        req = cldap_netlogon_send(s->cldap.sock, &s->cldap.io);
 
757
        if (composite_nomem(req, c)) return;
 
758
        req->async.fn           = becomeDC_recv_cldap;
 
759
        req->async.private_data = s;
 
760
}
 
761
 
 
762
static void becomeDC_connect_ldap1(struct libnet_BecomeDC_state *s);
 
763
 
 
764
static void becomeDC_recv_cldap(struct cldap_request *req)
 
765
{
 
766
        struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
 
767
                                          struct libnet_BecomeDC_state);
 
768
        struct composite_context *c = s->creq;
 
769
 
 
770
        c->status = cldap_netlogon_recv(req, s, &s->cldap.io);
 
771
        if (!composite_is_ok(c)) return;
 
772
 
 
773
        s->cldap.netlogon = s->cldap.io.out.netlogon.data.nt5_ex;
 
774
 
 
775
        s->domain.dns_name              = s->cldap.netlogon.dns_domain;
 
776
        s->domain.netbios_name          = s->cldap.netlogon.domain;
 
777
        s->domain.guid                  = s->cldap.netlogon.domain_uuid;
 
778
 
 
779
        s->forest.dns_name              = s->cldap.netlogon.forest;
 
780
 
 
781
        s->source_dsa.dns_name          = s->cldap.netlogon.pdc_dns_name;
 
782
        s->source_dsa.netbios_name      = s->cldap.netlogon.pdc_name;
 
783
        s->source_dsa.site_name         = s->cldap.netlogon.server_site;
 
784
 
 
785
        s->dest_dsa.site_name           = s->cldap.netlogon.client_site;
 
786
 
 
787
        becomeDC_connect_ldap1(s);
 
788
}
 
789
 
 
790
static NTSTATUS becomeDC_ldap_connect(struct libnet_BecomeDC_state *s, 
 
791
                                      struct becomeDC_ldap *ldap)
 
792
{
 
793
        char *url;
 
794
 
 
795
        url = talloc_asprintf(s, "ldap://%s/", s->source_dsa.dns_name);
 
796
        NT_STATUS_HAVE_NO_MEMORY(url);
 
797
 
 
798
        ldap->ldb = ldb_wrap_connect(s, s->libnet->event_ctx, s->libnet->lp_ctx, url,
 
799
                                     NULL,
 
800
                                     s->libnet->cred,
 
801
                                     0, NULL);
 
802
        talloc_free(url);
 
803
        if (ldap->ldb == NULL) {
 
804
                return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
 
805
        }
 
806
 
 
807
        return NT_STATUS_OK;
 
808
}
 
809
 
 
810
static NTSTATUS becomeDC_ldap1_rootdse(struct libnet_BecomeDC_state *s)
 
811
{
 
812
        int ret;
 
813
        struct ldb_result *r;
 
814
        struct ldb_dn *basedn;
 
815
        static const char *attrs[] = {
 
816
                "*",
 
817
                NULL
 
818
        };
 
819
 
 
820
        basedn = ldb_dn_new(s, s->ldap1.ldb, NULL);
 
821
        NT_STATUS_HAVE_NO_MEMORY(basedn);
 
822
 
 
823
        ret = ldb_search(s->ldap1.ldb, s, &r, basedn, LDB_SCOPE_BASE, attrs,
 
824
                         "(objectClass=*)");
 
825
        talloc_free(basedn);
 
826
        if (ret != LDB_SUCCESS) {
 
827
                return NT_STATUS_LDAP(ret);
 
828
        } else if (r->count != 1) {
 
829
                talloc_free(r);
 
830
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
831
        }
 
832
 
 
833
        s->ldap1.rootdse = r->msgs[0];
 
834
 
 
835
        s->domain.dn_str        = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "defaultNamingContext", NULL);
 
836
        if (!s->domain.dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
837
 
 
838
        s->forest.root_dn_str   = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "rootDomainNamingContext", NULL);
 
839
        if (!s->forest.root_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
840
        s->forest.config_dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "configurationNamingContext", NULL);
 
841
        if (!s->forest.config_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
842
        s->forest.schema_dn_str = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "schemaNamingContext", NULL);
 
843
        if (!s->forest.schema_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
844
 
 
845
        s->source_dsa.server_dn_str     = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "serverName", NULL);
 
846
        if (!s->source_dsa.server_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
847
        s->source_dsa.ntds_dn_str       = ldb_msg_find_attr_as_string(s->ldap1.rootdse, "dsServiceName", NULL);
 
848
        if (!s->source_dsa.ntds_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
849
 
 
850
        return NT_STATUS_OK;
 
851
}
 
852
 
 
853
static NTSTATUS becomeDC_ldap1_crossref_behavior_version(struct libnet_BecomeDC_state *s)
 
854
{
 
855
        int ret;
 
856
        struct ldb_result *r;
 
857
        struct ldb_dn *basedn;
 
858
        static const char *attrs[] = {
 
859
                "msDs-Behavior-Version",
 
860
                NULL
 
861
        };
 
862
 
 
863
        basedn = ldb_dn_new(s, s->ldap1.ldb, s->forest.config_dn_str);
 
864
        NT_STATUS_HAVE_NO_MEMORY(basedn);
 
865
 
 
866
        ret = ldb_search(s->ldap1.ldb, s, &r, basedn, LDB_SCOPE_ONELEVEL, attrs,
 
867
                         "(cn=Partitions)");
 
868
        talloc_free(basedn);
 
869
        if (ret != LDB_SUCCESS) {
 
870
                return NT_STATUS_LDAP(ret);
 
871
        } else if (r->count != 1) {
 
872
                talloc_free(r);
 
873
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
874
        }
 
875
 
 
876
        s->forest.crossref_behavior_version = ldb_msg_find_attr_as_uint(r->msgs[0], "msDs-Behavior-Version", 0);
 
877
 
 
878
        talloc_free(r);
 
879
        return NT_STATUS_OK;
 
880
}
 
881
 
 
882
static NTSTATUS becomeDC_ldap1_domain_behavior_version(struct libnet_BecomeDC_state *s)
 
883
{
 
884
        int ret;
 
885
        struct ldb_result *r;
 
886
        struct ldb_dn *basedn;
 
887
        static const char *attrs[] = {
 
888
                "msDs-Behavior-Version",
 
889
                NULL
 
890
        };
 
891
 
 
892
        basedn = ldb_dn_new(s, s->ldap1.ldb, s->domain.dn_str);
 
893
        NT_STATUS_HAVE_NO_MEMORY(basedn);
 
894
 
 
895
        ret = ldb_search(s->ldap1.ldb, s, &r, basedn, LDB_SCOPE_BASE, attrs,
 
896
                         "(objectClass=*)");
 
897
        talloc_free(basedn);
 
898
        if (ret != LDB_SUCCESS) {
 
899
                return NT_STATUS_LDAP(ret);
 
900
        } else if (r->count != 1) {
 
901
                talloc_free(r);
 
902
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
903
        }
 
904
 
 
905
        s->domain.behavior_version = ldb_msg_find_attr_as_uint(r->msgs[0], "msDs-Behavior-Version", 0);
 
906
 
 
907
        talloc_free(r);
 
908
        return NT_STATUS_OK;
 
909
}
 
910
 
 
911
static NTSTATUS becomeDC_ldap1_schema_object_version(struct libnet_BecomeDC_state *s)
 
912
{
 
913
        int ret;
 
914
        struct ldb_result *r;
 
915
        struct ldb_dn *basedn;
 
916
        static const char *attrs[] = {
 
917
                "objectVersion",
 
918
                NULL
 
919
        };
 
920
 
 
921
        basedn = ldb_dn_new(s, s->ldap1.ldb, s->forest.schema_dn_str);
 
922
        NT_STATUS_HAVE_NO_MEMORY(basedn);
 
923
 
 
924
        ret = ldb_search(s->ldap1.ldb, s, &r, basedn, LDB_SCOPE_BASE, attrs,
 
925
                         "(objectClass=*)");
 
926
        talloc_free(basedn);
 
927
        if (ret != LDB_SUCCESS) {
 
928
                return NT_STATUS_LDAP(ret);
 
929
        } else if (r->count != 1) {
 
930
                talloc_free(r);
 
931
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
932
        }
 
933
 
 
934
        s->forest.schema_object_version = ldb_msg_find_attr_as_uint(r->msgs[0], "objectVersion", 0);
 
935
 
 
936
        talloc_free(r);
 
937
        return NT_STATUS_OK;
 
938
}
 
939
 
 
940
static NTSTATUS becomeDC_ldap1_w2k3_update_revision(struct libnet_BecomeDC_state *s)
 
941
{
 
942
        int ret;
 
943
        struct ldb_result *r;
 
944
        struct ldb_dn *basedn;
 
945
        static const char *attrs[] = {
 
946
                "revision",
 
947
                NULL
 
948
        };
 
949
 
 
950
        basedn = ldb_dn_new_fmt(s, s->ldap1.ldb, "CN=Windows2003Update,CN=DomainUpdates,CN=System,%s",
 
951
                                s->domain.dn_str);
 
952
        NT_STATUS_HAVE_NO_MEMORY(basedn);
 
953
 
 
954
        ret = ldb_search(s->ldap1.ldb, s, &r, basedn, LDB_SCOPE_BASE, attrs,
 
955
                         "(objectClass=*)");
 
956
        talloc_free(basedn);
 
957
        if (ret == LDB_ERR_NO_SUCH_OBJECT) {
 
958
                /* w2k doesn't have this object */
 
959
                s->domain.w2k3_update_revision = 0;
 
960
                return NT_STATUS_OK;
 
961
        } else if (ret != LDB_SUCCESS) {
 
962
                return NT_STATUS_LDAP(ret);
 
963
        } else if (r->count != 1) {
 
964
                talloc_free(r);
 
965
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
966
        }
 
967
 
 
968
        s->domain.w2k3_update_revision = ldb_msg_find_attr_as_uint(r->msgs[0], "revision", 0);
 
969
 
 
970
        talloc_free(r);
 
971
        return NT_STATUS_OK;
 
972
}
 
973
 
 
974
static NTSTATUS becomeDC_ldap1_infrastructure_fsmo(struct libnet_BecomeDC_state *s)
 
975
{
 
976
        int ret;
 
977
        struct ldb_result *r;
 
978
        struct ldb_dn *basedn;
 
979
        struct ldb_dn *ntds_dn;
 
980
        struct ldb_dn *server_dn;
 
981
        static const char *_1_1_attrs[] = {
 
982
                "1.1",
 
983
                NULL
 
984
        };
 
985
        static const char *fsmo_attrs[] = {
 
986
                "fSMORoleOwner",
 
987
                NULL
 
988
        };
 
989
        static const char *dns_attrs[] = {
 
990
                "dnsHostName",
 
991
                NULL
 
992
        };
 
993
        static const char *guid_attrs[] = {
 
994
                "objectGUID",
 
995
                NULL
 
996
        };
 
997
 
 
998
        basedn = ldb_dn_new_fmt(s, s->ldap1.ldb, "<WKGUID=2fbac1870ade11d297c400c04fd8d5cd,%s>",
 
999
                                s->domain.dn_str);
 
1000
        NT_STATUS_HAVE_NO_MEMORY(basedn);
 
1001
 
 
1002
        ret = ldb_search(s->ldap1.ldb, s, &r, basedn, LDB_SCOPE_BASE,
 
1003
                         _1_1_attrs, "(objectClass=*)");
 
1004
        talloc_free(basedn);
 
1005
        if (ret != LDB_SUCCESS) {
 
1006
                return NT_STATUS_LDAP(ret);
 
1007
        } else if (r->count != 1) {
 
1008
                talloc_free(r);
 
1009
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
1010
        }
 
1011
 
 
1012
        basedn = talloc_steal(s, r->msgs[0]->dn);
 
1013
        talloc_free(r);
 
1014
 
 
1015
        ret = ldb_search(s->ldap1.ldb, s, &r, basedn, LDB_SCOPE_BASE,
 
1016
                         fsmo_attrs, "(objectClass=*)");
 
1017
        talloc_free(basedn);
 
1018
        if (ret != LDB_SUCCESS) {
 
1019
                return NT_STATUS_LDAP(ret);
 
1020
        } else if (r->count != 1) {
 
1021
                talloc_free(r);
 
1022
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
1023
        }
 
1024
 
 
1025
        s->infrastructure_fsmo.ntds_dn_str      = samdb_result_string(r->msgs[0], "fSMORoleOwner", NULL);
 
1026
        if (!s->infrastructure_fsmo.ntds_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
1027
        talloc_steal(s, s->infrastructure_fsmo.ntds_dn_str);
 
1028
 
 
1029
        talloc_free(r);
 
1030
 
 
1031
        ntds_dn = ldb_dn_new(s, s->ldap1.ldb, s->infrastructure_fsmo.ntds_dn_str);
 
1032
        NT_STATUS_HAVE_NO_MEMORY(ntds_dn);
 
1033
 
 
1034
        server_dn = ldb_dn_get_parent(s, ntds_dn);
 
1035
        NT_STATUS_HAVE_NO_MEMORY(server_dn);
 
1036
 
 
1037
        s->infrastructure_fsmo.server_dn_str = ldb_dn_alloc_linearized(s, server_dn);
 
1038
        NT_STATUS_HAVE_NO_MEMORY(s->infrastructure_fsmo.server_dn_str);
 
1039
 
 
1040
        ret = ldb_search(s->ldap1.ldb, s, &r, server_dn, LDB_SCOPE_BASE,
 
1041
                         dns_attrs, "(objectClass=*)");
 
1042
        if (ret != LDB_SUCCESS) {
 
1043
                return NT_STATUS_LDAP(ret);
 
1044
        } else if (r->count != 1) {
 
1045
                talloc_free(r);
 
1046
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
1047
        }
 
1048
 
 
1049
        s->infrastructure_fsmo.dns_name = samdb_result_string(r->msgs[0], "dnsHostName", NULL);
 
1050
        if (!s->infrastructure_fsmo.dns_name) return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
1051
        talloc_steal(s, s->infrastructure_fsmo.dns_name);
 
1052
 
 
1053
        talloc_free(r);
 
1054
 
 
1055
        ret = ldb_search(s->ldap1.ldb, s, &r, ntds_dn, LDB_SCOPE_BASE,
 
1056
                         guid_attrs, "(objectClass=*)");
 
1057
        if (ret != LDB_SUCCESS) {
 
1058
                return NT_STATUS_LDAP(ret);
 
1059
        } else if (r->count != 1) {
 
1060
                talloc_free(r);
 
1061
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
1062
        }
 
1063
 
 
1064
        s->infrastructure_fsmo.ntds_guid = samdb_result_guid(r->msgs[0], "objectGUID");
 
1065
 
 
1066
        talloc_free(r);
 
1067
 
 
1068
        return NT_STATUS_OK;
 
1069
}
 
1070
 
 
1071
static NTSTATUS becomeDC_ldap1_rid_manager_fsmo(struct libnet_BecomeDC_state *s)
 
1072
{
 
1073
        int ret;
 
1074
        struct ldb_result *r;
 
1075
        struct ldb_dn *basedn;
 
1076
        const char *reference_dn_str;
 
1077
        struct ldb_dn *ntds_dn;
 
1078
        struct ldb_dn *server_dn;
 
1079
        static const char *rid_attrs[] = {
 
1080
                "rIDManagerReference",
 
1081
                NULL
 
1082
        };
 
1083
        static const char *fsmo_attrs[] = {
 
1084
                "fSMORoleOwner",
 
1085
                NULL
 
1086
        };
 
1087
        static const char *dns_attrs[] = {
 
1088
                "dnsHostName",
 
1089
                NULL
 
1090
        };
 
1091
        static const char *guid_attrs[] = {
 
1092
                "objectGUID",
 
1093
                NULL
 
1094
        };
 
1095
 
 
1096
        basedn = ldb_dn_new(s, s->ldap1.ldb, s->domain.dn_str);
 
1097
        NT_STATUS_HAVE_NO_MEMORY(basedn);
 
1098
 
 
1099
        ret = ldb_search(s->ldap1.ldb, s, &r, basedn, LDB_SCOPE_BASE,
 
1100
                         rid_attrs, "(objectClass=*)");
 
1101
        talloc_free(basedn);
 
1102
        if (ret != LDB_SUCCESS) {
 
1103
                return NT_STATUS_LDAP(ret);
 
1104
        } else if (r->count != 1) {
 
1105
                talloc_free(r);
 
1106
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
1107
        }
 
1108
 
 
1109
        reference_dn_str        = samdb_result_string(r->msgs[0], "rIDManagerReference", NULL);
 
1110
        if (!reference_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
1111
 
 
1112
        basedn = ldb_dn_new(s, s->ldap1.ldb, reference_dn_str);
 
1113
        NT_STATUS_HAVE_NO_MEMORY(basedn);
 
1114
 
 
1115
        talloc_free(r);
 
1116
 
 
1117
        ret = ldb_search(s->ldap1.ldb, s, &r, basedn, LDB_SCOPE_BASE,
 
1118
                         fsmo_attrs, "(objectClass=*)");
 
1119
        talloc_free(basedn);
 
1120
        if (ret != LDB_SUCCESS) {
 
1121
                return NT_STATUS_LDAP(ret);
 
1122
        } else if (r->count != 1) {
 
1123
                talloc_free(r);
 
1124
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
1125
        }
 
1126
 
 
1127
        s->rid_manager_fsmo.ntds_dn_str = samdb_result_string(r->msgs[0], "fSMORoleOwner", NULL);
 
1128
        if (!s->rid_manager_fsmo.ntds_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
1129
        talloc_steal(s, s->rid_manager_fsmo.ntds_dn_str);
 
1130
 
 
1131
        talloc_free(r);
 
1132
 
 
1133
        ntds_dn = ldb_dn_new(s, s->ldap1.ldb, s->rid_manager_fsmo.ntds_dn_str);
 
1134
        NT_STATUS_HAVE_NO_MEMORY(ntds_dn);
 
1135
 
 
1136
        server_dn = ldb_dn_get_parent(s, ntds_dn);
 
1137
        NT_STATUS_HAVE_NO_MEMORY(server_dn);
 
1138
 
 
1139
        s->rid_manager_fsmo.server_dn_str = ldb_dn_alloc_linearized(s, server_dn);
 
1140
        NT_STATUS_HAVE_NO_MEMORY(s->rid_manager_fsmo.server_dn_str);
 
1141
 
 
1142
        ret = ldb_search(s->ldap1.ldb, s, &r, server_dn, LDB_SCOPE_BASE,
 
1143
                         dns_attrs, "(objectClass=*)");
 
1144
        if (ret != LDB_SUCCESS) {
 
1145
                return NT_STATUS_LDAP(ret);
 
1146
        } else if (r->count != 1) {
 
1147
                talloc_free(r);
 
1148
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
1149
        }
 
1150
 
 
1151
        s->rid_manager_fsmo.dns_name    = samdb_result_string(r->msgs[0], "dnsHostName", NULL);
 
1152
        if (!s->rid_manager_fsmo.dns_name) return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
1153
        talloc_steal(s, s->rid_manager_fsmo.dns_name);
 
1154
 
 
1155
        talloc_free(r);
 
1156
 
 
1157
        ret = ldb_search(s->ldap1.ldb, s, &r, ntds_dn, LDB_SCOPE_BASE,
 
1158
                         guid_attrs, "(objectClass=*)");
 
1159
        if (ret != LDB_SUCCESS) {
 
1160
                return NT_STATUS_LDAP(ret);
 
1161
        } else if (r->count != 1) {
 
1162
                talloc_free(r);
 
1163
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
1164
        }
 
1165
 
 
1166
        s->rid_manager_fsmo.ntds_guid = samdb_result_guid(r->msgs[0], "objectGUID");
 
1167
 
 
1168
        talloc_free(r);
 
1169
 
 
1170
        return NT_STATUS_OK;
 
1171
}
 
1172
 
 
1173
static NTSTATUS becomeDC_ldap1_site_object(struct libnet_BecomeDC_state *s)
 
1174
{
 
1175
        int ret;
 
1176
        struct ldb_result *r;
 
1177
        struct ldb_dn *basedn;
 
1178
 
 
1179
        basedn = ldb_dn_new_fmt(s, s->ldap1.ldb, "CN=%s,CN=Sites,%s",
 
1180
                                s->dest_dsa.site_name,
 
1181
                                s->forest.config_dn_str);
 
1182
        NT_STATUS_HAVE_NO_MEMORY(basedn);
 
1183
 
 
1184
        ret = ldb_search(s->ldap1.ldb, s, &r, basedn, LDB_SCOPE_BASE,
 
1185
                         NULL, "(objectClass=*)");
 
1186
        talloc_free(basedn);
 
1187
        if (ret != LDB_SUCCESS) {
 
1188
                return NT_STATUS_LDAP(ret);
 
1189
        } else if (r->count != 1) {
 
1190
                talloc_free(r);
 
1191
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
1192
        }
 
1193
 
 
1194
        s->dest_dsa.site_guid = samdb_result_guid(r->msgs[0], "objectGUID");
 
1195
 
 
1196
        talloc_free(r);
 
1197
        return NT_STATUS_OK;
 
1198
}
 
1199
 
 
1200
static NTSTATUS becomeDC_check_options(struct libnet_BecomeDC_state *s)
 
1201
{
 
1202
        if (!s->callbacks.check_options) return NT_STATUS_OK;
 
1203
 
 
1204
        s->_co.domain           = &s->domain;
 
1205
        s->_co.forest           = &s->forest;
 
1206
        s->_co.source_dsa       = &s->source_dsa;
 
1207
 
 
1208
        return s->callbacks.check_options(s->callbacks.private_data, &s->_co);
 
1209
}
 
1210
 
 
1211
static NTSTATUS becomeDC_ldap1_computer_object(struct libnet_BecomeDC_state *s)
 
1212
{
 
1213
        int ret;
 
1214
        struct ldb_result *r;
 
1215
        struct ldb_dn *basedn;
 
1216
        static const char *attrs[] = {
 
1217
                "distinguishedName",
 
1218
                "userAccountControl",
 
1219
                NULL
 
1220
        };
 
1221
 
 
1222
        basedn = ldb_dn_new(s, s->ldap1.ldb, s->domain.dn_str);
 
1223
        NT_STATUS_HAVE_NO_MEMORY(basedn);
 
1224
 
 
1225
        ret = ldb_search(s->ldap1.ldb, s, &r, basedn, LDB_SCOPE_SUBTREE, attrs,
 
1226
                         "(&(|(objectClass=user)(objectClass=computer))(sAMAccountName=%s$))",
 
1227
                         s->dest_dsa.netbios_name);
 
1228
        talloc_free(basedn);
 
1229
        if (ret != LDB_SUCCESS) {
 
1230
                return NT_STATUS_LDAP(ret);
 
1231
        } else if (r->count != 1) {
 
1232
                talloc_free(r);
 
1233
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
1234
        }
 
1235
 
 
1236
        s->dest_dsa.computer_dn_str     = samdb_result_string(r->msgs[0], "distinguishedName", NULL);
 
1237
        if (!s->dest_dsa.computer_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
1238
        talloc_steal(s, s->dest_dsa.computer_dn_str);
 
1239
 
 
1240
        s->dest_dsa.user_account_control = samdb_result_uint(r->msgs[0], "userAccountControl", 0);
 
1241
 
 
1242
        talloc_free(r);
 
1243
        return NT_STATUS_OK;
 
1244
}
 
1245
 
 
1246
static NTSTATUS becomeDC_ldap1_server_object_1(struct libnet_BecomeDC_state *s)
 
1247
{
 
1248
        int ret;
 
1249
        struct ldb_result *r;
 
1250
        struct ldb_dn *basedn;
 
1251
        const char *server_reference_dn_str;
 
1252
        struct ldb_dn *server_reference_dn;
 
1253
        struct ldb_dn *computer_dn;
 
1254
 
 
1255
        basedn = ldb_dn_new_fmt(s, s->ldap1.ldb, "CN=%s,CN=Servers,CN=%s,CN=Sites,%s",
 
1256
                                s->dest_dsa.netbios_name,
 
1257
                                s->dest_dsa.site_name,
 
1258
                                s->forest.config_dn_str);
 
1259
        NT_STATUS_HAVE_NO_MEMORY(basedn);
 
1260
 
 
1261
        ret = ldb_search(s->ldap1.ldb, s, &r, basedn, LDB_SCOPE_BASE,
 
1262
                         NULL, "(objectClass=*)");
 
1263
        talloc_free(basedn);
 
1264
        if (ret == LDB_ERR_NO_SUCH_OBJECT) {
 
1265
                /* if the object doesn't exist, we'll create it later */
 
1266
                return NT_STATUS_OK;
 
1267
        } else if (ret != LDB_SUCCESS) {
 
1268
                return NT_STATUS_LDAP(ret);
 
1269
        } else if (r->count != 1) {
 
1270
                talloc_free(r);
 
1271
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
1272
        }
 
1273
 
 
1274
        server_reference_dn_str = samdb_result_string(r->msgs[0], "serverReference", NULL);
 
1275
        if (server_reference_dn_str) {
 
1276
                server_reference_dn     = ldb_dn_new(r, s->ldap1.ldb, server_reference_dn_str);
 
1277
                NT_STATUS_HAVE_NO_MEMORY(server_reference_dn);
 
1278
 
 
1279
                computer_dn             = ldb_dn_new(r, s->ldap1.ldb, s->dest_dsa.computer_dn_str);
 
1280
                NT_STATUS_HAVE_NO_MEMORY(computer_dn);
 
1281
 
 
1282
                /*
 
1283
                 * if the server object belongs to another DC in another domain in the forest,
 
1284
                 * we should not touch this object!
 
1285
                 */
 
1286
                if (ldb_dn_compare(computer_dn, server_reference_dn) != 0) {
 
1287
                        talloc_free(r);
 
1288
                        return NT_STATUS_OBJECT_NAME_COLLISION;
 
1289
                }
 
1290
        }
 
1291
 
 
1292
        /* if the server object is already for the dest_dsa, then we don't need to create it */
 
1293
        s->dest_dsa.server_dn_str       = samdb_result_string(r->msgs[0], "distinguishedName", NULL);
 
1294
        if (!s->dest_dsa.server_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
1295
        talloc_steal(s, s->dest_dsa.server_dn_str);
 
1296
 
 
1297
        talloc_free(r);
 
1298
        return NT_STATUS_OK;
 
1299
}
 
1300
 
 
1301
static NTSTATUS becomeDC_ldap1_server_object_2(struct libnet_BecomeDC_state *s)
 
1302
{
 
1303
        int ret;
 
1304
        struct ldb_result *r;
 
1305
        struct ldb_dn *basedn;
 
1306
        const char *server_reference_bl_dn_str;
 
1307
        static const char *attrs[] = {
 
1308
                "serverReferenceBL",
 
1309
                NULL
 
1310
        };
 
1311
 
 
1312
        /* if the server_dn_str has a valid value, we skip this lookup */
 
1313
        if (s->dest_dsa.server_dn_str) return NT_STATUS_OK;
 
1314
 
 
1315
        basedn = ldb_dn_new(s, s->ldap1.ldb, s->dest_dsa.computer_dn_str);
 
1316
        NT_STATUS_HAVE_NO_MEMORY(basedn);
 
1317
 
 
1318
        ret = ldb_search(s->ldap1.ldb, s, &r, basedn, LDB_SCOPE_BASE,
 
1319
                         attrs, "(objectClass=*)");
 
1320
        talloc_free(basedn);
 
1321
        if (ret != LDB_SUCCESS) {
 
1322
                return NT_STATUS_LDAP(ret);
 
1323
        } else if (r->count != 1) {
 
1324
                talloc_free(r);
 
1325
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
1326
        }
 
1327
 
 
1328
        server_reference_bl_dn_str = samdb_result_string(r->msgs[0], "serverReferenceBL", NULL);
 
1329
        if (!server_reference_bl_dn_str) {
 
1330
                /* if no back link is present, we're done for this function */
 
1331
                talloc_free(r);
 
1332
                return NT_STATUS_OK;
 
1333
        }
 
1334
 
 
1335
        /* if the server object is already for the dest_dsa, then we don't need to create it */
 
1336
        s->dest_dsa.server_dn_str       = samdb_result_string(r->msgs[0], "serverReferenceBL", NULL);
 
1337
        if (s->dest_dsa.server_dn_str) {
 
1338
                /* if a back link is present, we know that the server object is present */
 
1339
                talloc_steal(s, s->dest_dsa.server_dn_str);
 
1340
        }
 
1341
 
 
1342
        talloc_free(r);
 
1343
        return NT_STATUS_OK;
 
1344
}
 
1345
 
 
1346
static NTSTATUS becomeDC_ldap1_server_object_add(struct libnet_BecomeDC_state *s)
 
1347
{
 
1348
        int ret;
 
1349
        struct ldb_message *msg;
 
1350
        char *server_dn_str;
 
1351
 
 
1352
        /* if the server_dn_str has a valid value, we skip this lookup */
 
1353
        if (s->dest_dsa.server_dn_str) return NT_STATUS_OK;
 
1354
 
 
1355
        msg = ldb_msg_new(s);
 
1356
        NT_STATUS_HAVE_NO_MEMORY(msg);
 
1357
 
 
1358
        msg->dn = ldb_dn_new_fmt(msg, s->ldap1.ldb, "CN=%s,CN=Servers,CN=%s,CN=Sites,%s",
 
1359
                                 s->dest_dsa.netbios_name,
 
1360
                                 s->dest_dsa.site_name,
 
1361
                                 s->forest.config_dn_str);
 
1362
        NT_STATUS_HAVE_NO_MEMORY(msg->dn);
 
1363
 
 
1364
        ret = ldb_msg_add_string(msg, "objectClass", "server");
 
1365
        if (ret != 0) {
 
1366
                talloc_free(msg);
 
1367
                return NT_STATUS_NO_MEMORY;
 
1368
        }
 
1369
        ret = ldb_msg_add_string(msg, "systemFlags", "50000000");
 
1370
        if (ret != 0) {
 
1371
                talloc_free(msg);
 
1372
                return NT_STATUS_NO_MEMORY;
 
1373
        }
 
1374
        ret = ldb_msg_add_string(msg, "serverReference", s->dest_dsa.computer_dn_str);
 
1375
        if (ret != 0) {
 
1376
                talloc_free(msg);
 
1377
                return NT_STATUS_NO_MEMORY;
 
1378
        }
 
1379
 
 
1380
        server_dn_str = ldb_dn_alloc_linearized(s, msg->dn);
 
1381
        NT_STATUS_HAVE_NO_MEMORY(server_dn_str);
 
1382
 
 
1383
        ret = ldb_add(s->ldap1.ldb, msg);
 
1384
        talloc_free(msg);
 
1385
        if (ret != LDB_SUCCESS) {
 
1386
                talloc_free(server_dn_str);
 
1387
                return NT_STATUS_LDAP(ret);
 
1388
        }
 
1389
 
 
1390
        s->dest_dsa.server_dn_str = server_dn_str;
 
1391
 
 
1392
        return NT_STATUS_OK;
 
1393
}
 
1394
 
 
1395
static NTSTATUS becomeDC_ldap1_server_object_modify(struct libnet_BecomeDC_state *s)
 
1396
{
 
1397
        int ret;
 
1398
        struct ldb_message *msg;
 
1399
        uint32_t i;
 
1400
 
 
1401
        /* make a 'modify' msg, and only for serverReference */
 
1402
        msg = ldb_msg_new(s);
 
1403
        NT_STATUS_HAVE_NO_MEMORY(msg);
 
1404
        msg->dn = ldb_dn_new(msg, s->ldap1.ldb, s->dest_dsa.server_dn_str);
 
1405
        NT_STATUS_HAVE_NO_MEMORY(msg->dn);
 
1406
 
 
1407
        ret = ldb_msg_add_string(msg, "serverReference", s->dest_dsa.computer_dn_str);
 
1408
        if (ret != 0) {
 
1409
                talloc_free(msg);
 
1410
                return NT_STATUS_NO_MEMORY;
 
1411
        }
 
1412
 
 
1413
        /* mark all the message elements (should be just one)
 
1414
           as LDB_FLAG_MOD_ADD */
 
1415
        for (i=0;i<msg->num_elements;i++) {
 
1416
                msg->elements[i].flags = LDB_FLAG_MOD_ADD;
 
1417
        }
 
1418
 
 
1419
        ret = ldb_modify(s->ldap1.ldb, msg);
 
1420
        if (ret == LDB_SUCCESS) {
 
1421
                talloc_free(msg);
 
1422
                return NT_STATUS_OK;
 
1423
        } else if (ret == LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) {
 
1424
                /* retry with LDB_FLAG_MOD_REPLACE */
 
1425
        } else {
 
1426
                talloc_free(msg);
 
1427
                return NT_STATUS_LDAP(ret);
 
1428
        }
 
1429
 
 
1430
        /* mark all the message elements (should be just one)
 
1431
           as LDB_FLAG_MOD_REPLACE */
 
1432
        for (i=0;i<msg->num_elements;i++) {
 
1433
                msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
 
1434
        }
 
1435
 
 
1436
        ret = ldb_modify(s->ldap1.ldb, msg);
 
1437
        talloc_free(msg);
 
1438
        if (ret != LDB_SUCCESS) {
 
1439
                return NT_STATUS_LDAP(ret);
 
1440
        }
 
1441
 
 
1442
        return NT_STATUS_OK;
 
1443
}
 
1444
 
 
1445
static void becomeDC_drsuapi_connect_send(struct libnet_BecomeDC_state *s,
 
1446
                                          struct becomeDC_drsuapi *drsuapi,
 
1447
                                          void (*recv_fn)(struct composite_context *req));
 
1448
static void becomeDC_drsuapi1_connect_recv(struct composite_context *req);
 
1449
static void becomeDC_connect_ldap2(struct libnet_BecomeDC_state *s);
 
1450
 
 
1451
static void becomeDC_connect_ldap1(struct libnet_BecomeDC_state *s)
 
1452
{
 
1453
        struct composite_context *c = s->creq;
 
1454
 
 
1455
        c->status = becomeDC_ldap_connect(s, &s->ldap1);
 
1456
        if (!composite_is_ok(c)) return;
 
1457
 
 
1458
        c->status = becomeDC_ldap1_rootdse(s);
 
1459
        if (!composite_is_ok(c)) return;
 
1460
 
 
1461
        c->status = becomeDC_ldap1_crossref_behavior_version(s);
 
1462
        if (!composite_is_ok(c)) return;
 
1463
 
 
1464
        c->status = becomeDC_ldap1_domain_behavior_version(s);
 
1465
        if (!composite_is_ok(c)) return;
 
1466
 
 
1467
        c->status = becomeDC_ldap1_schema_object_version(s);
 
1468
        if (!composite_is_ok(c)) return;
 
1469
 
 
1470
        c->status = becomeDC_ldap1_w2k3_update_revision(s);
 
1471
        if (!composite_is_ok(c)) return;
 
1472
 
 
1473
        c->status = becomeDC_ldap1_infrastructure_fsmo(s);
 
1474
        if (!composite_is_ok(c)) return;
 
1475
 
 
1476
        c->status = becomeDC_ldap1_rid_manager_fsmo(s);
 
1477
        if (!composite_is_ok(c)) return;
 
1478
 
 
1479
        c->status = becomeDC_ldap1_site_object(s);
 
1480
        if (!composite_is_ok(c)) return;
 
1481
 
 
1482
        c->status = becomeDC_check_options(s);
 
1483
        if (!composite_is_ok(c)) return;
 
1484
 
 
1485
        c->status = becomeDC_ldap1_computer_object(s);
 
1486
        if (!composite_is_ok(c)) return;
 
1487
 
 
1488
        c->status = becomeDC_ldap1_server_object_1(s);
 
1489
        if (!composite_is_ok(c)) return;
 
1490
 
 
1491
        c->status = becomeDC_ldap1_server_object_2(s);
 
1492
        if (!composite_is_ok(c)) return;
 
1493
 
 
1494
        c->status = becomeDC_ldap1_server_object_add(s);
 
1495
        if (!composite_is_ok(c)) return;
 
1496
 
 
1497
        c->status = becomeDC_ldap1_server_object_modify(s);
 
1498
        if (!composite_is_ok(c)) return;
 
1499
 
 
1500
        becomeDC_drsuapi_connect_send(s, &s->drsuapi1, becomeDC_drsuapi1_connect_recv);
 
1501
}
 
1502
 
 
1503
static void becomeDC_drsuapi_connect_send(struct libnet_BecomeDC_state *s,
 
1504
                                          struct becomeDC_drsuapi *drsuapi,
 
1505
                                          void (*recv_fn)(struct composite_context *req))
 
1506
{
 
1507
        struct composite_context *c = s->creq;
 
1508
        struct composite_context *creq;
 
1509
        char *binding_str;
 
1510
 
 
1511
        drsuapi->s = s;
 
1512
 
 
1513
        if (!drsuapi->binding) {
 
1514
                const char *krb5_str = "";
 
1515
                const char *print_str = "";
 
1516
                /*
 
1517
                 * Note: Replication only works with Windows 2000 when 'krb5' is
 
1518
                 *       passed as auth_type here. If NTLMSSP is used, Windows
 
1519
                 *       2000 returns garbage in the DsGetNCChanges() response
 
1520
                 *       if encrypted password attributes would be in the response.
 
1521
                 *       That means the replication of the schema and configuration
 
1522
                 *       partition works fine, but it fails for the domain partition.
 
1523
                 */
 
1524
                if (lp_parm_bool(s->libnet->lp_ctx, NULL, "become_dc",
 
1525
                                 "force krb5", true))
 
1526
                {
 
1527
                        krb5_str = "krb5,";
 
1528
                }
 
1529
                if (lp_parm_bool(s->libnet->lp_ctx, NULL, "become_dc",
 
1530
                                 "print", false))
 
1531
                {
 
1532
                        print_str = "print,";
 
1533
                }
 
1534
                binding_str = talloc_asprintf(s, "ncacn_ip_tcp:%s[%s%sseal]",
 
1535
                                              s->source_dsa.dns_name,
 
1536
                                              krb5_str, print_str);
 
1537
                if (composite_nomem(binding_str, c)) return;
 
1538
                c->status = dcerpc_parse_binding(s, binding_str, &drsuapi->binding);
 
1539
                talloc_free(binding_str);
 
1540
                if (!composite_is_ok(c)) return;
 
1541
        }
 
1542
 
 
1543
        creq = dcerpc_pipe_connect_b_send(s, drsuapi->binding, &ndr_table_drsuapi,
 
1544
                                          s->libnet->cred, s->libnet->event_ctx,
 
1545
                                          s->libnet->lp_ctx);
 
1546
        composite_continue(c, creq, recv_fn, s);
 
1547
}
 
1548
 
 
1549
static void becomeDC_drsuapi_bind_send(struct libnet_BecomeDC_state *s,
 
1550
                                       struct becomeDC_drsuapi *drsuapi,
 
1551
                                       void (*recv_fn)(struct rpc_request *req));
 
1552
static void becomeDC_drsuapi1_bind_recv(struct rpc_request *req);
 
1553
 
 
1554
static void becomeDC_drsuapi1_connect_recv(struct composite_context *req)
 
1555
{
 
1556
        struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
 
1557
                                          struct libnet_BecomeDC_state);
 
1558
        struct composite_context *c = s->creq;
 
1559
 
 
1560
        c->status = dcerpc_pipe_connect_b_recv(req, s, &s->drsuapi1.pipe);
 
1561
        if (!composite_is_ok(c)) return;
 
1562
 
 
1563
        c->status = gensec_session_key(s->drsuapi1.pipe->conn->security_state.generic_state,
 
1564
                                       &s->drsuapi1.gensec_skey);
 
1565
        if (!composite_is_ok(c)) return;
 
1566
 
 
1567
        becomeDC_drsuapi_bind_send(s, &s->drsuapi1, becomeDC_drsuapi1_bind_recv);
 
1568
}
 
1569
 
 
1570
static void becomeDC_drsuapi_bind_send(struct libnet_BecomeDC_state *s,
 
1571
                                       struct becomeDC_drsuapi *drsuapi,
 
1572
                                       void (*recv_fn)(struct rpc_request *req))
 
1573
{
 
1574
        struct composite_context *c = s->creq;
 
1575
        struct rpc_request *req;
 
1576
        struct drsuapi_DsBindInfo28 *bind_info28;
 
1577
 
 
1578
        GUID_from_string(DRSUAPI_DS_BIND_GUID_W2K3, &drsuapi->bind_guid);
 
1579
 
 
1580
        bind_info28                             = &drsuapi->local_info28;
 
1581
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_BASE;
 
1582
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION;
 
1583
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI;
 
1584
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2;
 
1585
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS;
 
1586
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1;
 
1587
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION;
 
1588
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE;
 
1589
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2;
 
1590
        if (s->domain.behavior_version == 2) {
 
1591
                /* TODO: find out how this is really triggered! */
 
1592
                bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION;
 
1593
        }
 
1594
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2;
 
1595
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD;
 
1596
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND;
 
1597
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO;
 
1598
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION;
 
1599
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01;
 
1600
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP;
 
1601
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY;
 
1602
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3;
 
1603
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_00100000;
 
1604
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2;
 
1605
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6;
 
1606
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS;
 
1607
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8;
 
1608
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5;
 
1609
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6;
 
1610
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3;
 
1611
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7;
 
1612
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT;
 
1613
#if 0 /* we don't support XPRESS compression yet */
 
1614
        bind_info28->supported_extensions       |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS;
 
1615
#endif
 
1616
        bind_info28->site_guid                  = s->dest_dsa.site_guid;
 
1617
        bind_info28->pid                        = 0;
 
1618
        bind_info28->repl_epoch                 = 0;
 
1619
 
 
1620
        drsuapi->bind_info_ctr.length           = 28;
 
1621
        drsuapi->bind_info_ctr.info.info28      = *bind_info28;
 
1622
 
 
1623
        drsuapi->bind_r.in.bind_guid = &drsuapi->bind_guid;
 
1624
        drsuapi->bind_r.in.bind_info = &drsuapi->bind_info_ctr;
 
1625
        drsuapi->bind_r.out.bind_handle = &drsuapi->bind_handle;
 
1626
 
 
1627
        req = dcerpc_drsuapi_DsBind_send(drsuapi->pipe, s, &drsuapi->bind_r);
 
1628
        composite_continue_rpc(c, req, recv_fn, s);
 
1629
}
 
1630
 
 
1631
static WERROR becomeDC_drsuapi_bind_recv(struct libnet_BecomeDC_state *s,
 
1632
                                         struct becomeDC_drsuapi *drsuapi)
 
1633
{
 
1634
        if (!W_ERROR_IS_OK(drsuapi->bind_r.out.result)) {
 
1635
                return drsuapi->bind_r.out.result;
 
1636
        }
 
1637
 
 
1638
        ZERO_STRUCT(drsuapi->remote_info28);
 
1639
        if (drsuapi->bind_r.out.bind_info) {
 
1640
                switch (drsuapi->bind_r.out.bind_info->length) {
 
1641
                case 24: {
 
1642
                        struct drsuapi_DsBindInfo24 *info24;
 
1643
                        info24 = &drsuapi->bind_r.out.bind_info->info.info24;
 
1644
                        drsuapi->remote_info28.supported_extensions     = info24->supported_extensions;
 
1645
                        drsuapi->remote_info28.site_guid                = info24->site_guid;
 
1646
                        drsuapi->remote_info28.pid                      = info24->pid;
 
1647
                        drsuapi->remote_info28.repl_epoch               = 0;
 
1648
                        break;
 
1649
                }
 
1650
                case 48: {
 
1651
                        struct drsuapi_DsBindInfo48 *info48;
 
1652
                        info48 = &drsuapi->bind_r.out.bind_info->info.info48;
 
1653
                        drsuapi->remote_info28.supported_extensions     = info48->supported_extensions;
 
1654
                        drsuapi->remote_info28.site_guid                = info48->site_guid;
 
1655
                        drsuapi->remote_info28.pid                      = info48->pid;
 
1656
                        drsuapi->remote_info28.repl_epoch               = info48->repl_epoch;
 
1657
                        break;
 
1658
                }
 
1659
                case 28:
 
1660
                        drsuapi->remote_info28 = drsuapi->bind_r.out.bind_info->info.info28;
 
1661
                        break;
 
1662
                }
 
1663
        }
 
1664
 
 
1665
        return WERR_OK;
 
1666
}
 
1667
 
 
1668
static void becomeDC_drsuapi1_add_entry_send(struct libnet_BecomeDC_state *s);
 
1669
 
 
1670
static void becomeDC_drsuapi1_bind_recv(struct rpc_request *req)
 
1671
{
 
1672
        struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
 
1673
                                          struct libnet_BecomeDC_state);
 
1674
        struct composite_context *c = s->creq;
 
1675
        WERROR status;
 
1676
 
 
1677
        bool print = false;
 
1678
 
 
1679
        if (req->p->conn->flags & DCERPC_DEBUG_PRINT_OUT) {
 
1680
                print = true;
 
1681
        }
 
1682
 
 
1683
        c->status = dcerpc_ndr_request_recv(req);
 
1684
        if (!composite_is_ok(c)) return;
 
1685
 
 
1686
        if (print) {
 
1687
                NDR_PRINT_OUT_DEBUG(drsuapi_DsBind, &s->drsuapi1.bind_r);
 
1688
        }
 
1689
 
 
1690
        status = becomeDC_drsuapi_bind_recv(s, &s->drsuapi1);
 
1691
        if (!W_ERROR_IS_OK(status)) {
 
1692
                composite_error(c, werror_to_ntstatus(status));
 
1693
                return;
 
1694
        }
 
1695
 
 
1696
        becomeDC_drsuapi1_add_entry_send(s);
 
1697
}
 
1698
 
 
1699
static void becomeDC_drsuapi1_add_entry_recv(struct rpc_request *req);
 
1700
 
 
1701
static void becomeDC_drsuapi1_add_entry_send(struct libnet_BecomeDC_state *s)
 
1702
{
 
1703
        struct composite_context *c = s->creq;
 
1704
        struct rpc_request *req;
 
1705
        struct drsuapi_DsAddEntry *r;
 
1706
        struct drsuapi_DsReplicaObjectIdentifier *identifier;
 
1707
        uint32_t num_attrs, i = 0;
 
1708
        struct drsuapi_DsReplicaAttribute *attrs;
 
1709
        struct smb_iconv_convenience *iconv_convenience = lp_iconv_convenience(s->libnet->lp_ctx);
 
1710
        enum ndr_err_code ndr_err;
 
1711
        bool w2k3;
 
1712
 
 
1713
        /* choose a random invocationId */
 
1714
        s->dest_dsa.invocation_id = GUID_random();
 
1715
 
 
1716
        /*
 
1717
         * if the schema version indicates w2k3, then
 
1718
         * also send some w2k3 specific attributes
 
1719
         */
 
1720
        if (s->forest.schema_object_version >= 30) {
 
1721
                w2k3 = true;
 
1722
        } else {
 
1723
                w2k3 = false;
 
1724
        }
 
1725
 
 
1726
        r = talloc_zero(s, struct drsuapi_DsAddEntry);
 
1727
        if (composite_nomem(r, c)) return;
 
1728
 
 
1729
        /* setup identifier */
 
1730
        identifier              = talloc(r, struct drsuapi_DsReplicaObjectIdentifier);
 
1731
        if (composite_nomem(identifier, c)) return;
 
1732
        identifier->guid        = GUID_zero();
 
1733
        identifier->sid         = s->zero_sid;
 
1734
        identifier->dn          = talloc_asprintf(identifier, "CN=NTDS Settings,%s",
 
1735
                                                  s->dest_dsa.server_dn_str);
 
1736
        if (composite_nomem(identifier->dn, c)) return;
 
1737
 
 
1738
        /* allocate attribute array */
 
1739
        num_attrs       = 11;
 
1740
        attrs           = talloc_array(r, struct drsuapi_DsReplicaAttribute, num_attrs);
 
1741
        if (composite_nomem(attrs, c)) return;
 
1742
 
 
1743
        /* ntSecurityDescriptor */
 
1744
        {
 
1745
                struct drsuapi_DsAttributeValue *vs;
 
1746
                DATA_BLOB *vd;
 
1747
                struct security_descriptor *v;
 
1748
                struct dom_sid *domain_admins_sid;
 
1749
                const char *domain_admins_sid_str;
 
1750
 
 
1751
                vs = talloc_array(attrs, struct drsuapi_DsAttributeValue, 1);
 
1752
                if (composite_nomem(vs, c)) return;
 
1753
 
 
1754
                vd = talloc_array(vs, DATA_BLOB, 1);
 
1755
                if (composite_nomem(vd, c)) return;
 
1756
 
 
1757
                domain_admins_sid = dom_sid_add_rid(vs, s->domain.sid, DOMAIN_RID_ADMINS);
 
1758
                if (composite_nomem(domain_admins_sid, c)) return;
 
1759
 
 
1760
                domain_admins_sid_str = dom_sid_string(domain_admins_sid, domain_admins_sid);
 
1761
                if (composite_nomem(domain_admins_sid_str, c)) return;
 
1762
 
 
1763
                v = security_descriptor_dacl_create(vd,
 
1764
                                               0,
 
1765
                                               /* owner: domain admins */
 
1766
                                               domain_admins_sid_str,
 
1767
                                               /* owner group: domain admins */
 
1768
                                               domain_admins_sid_str,
 
1769
                                               /* authenticated users */
 
1770
                                               SID_NT_AUTHENTICATED_USERS,
 
1771
                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
 
1772
                                               SEC_STD_READ_CONTROL |
 
1773
                                               SEC_ADS_LIST |
 
1774
                                               SEC_ADS_READ_PROP |
 
1775
                                               SEC_ADS_LIST_OBJECT,
 
1776
                                               0,
 
1777
                                               /* domain admins */
 
1778
                                               domain_admins_sid_str,
 
1779
                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
 
1780
                                               SEC_STD_REQUIRED |
 
1781
                                               SEC_ADS_CREATE_CHILD |
 
1782
                                               SEC_ADS_LIST |
 
1783
                                               SEC_ADS_SELF_WRITE |
 
1784
                                               SEC_ADS_READ_PROP |
 
1785
                                               SEC_ADS_WRITE_PROP |
 
1786
                                               SEC_ADS_DELETE_TREE |
 
1787
                                               SEC_ADS_LIST_OBJECT |
 
1788
                                               SEC_ADS_CONTROL_ACCESS,
 
1789
                                               0,
 
1790
                                               /* system */
 
1791
                                               SID_NT_SYSTEM,
 
1792
                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
 
1793
                                               SEC_STD_REQUIRED |
 
1794
                                               SEC_ADS_CREATE_CHILD |
 
1795
                                               SEC_ADS_DELETE_CHILD |
 
1796
                                               SEC_ADS_LIST |
 
1797
                                               SEC_ADS_SELF_WRITE |
 
1798
                                               SEC_ADS_READ_PROP |
 
1799
                                               SEC_ADS_WRITE_PROP |
 
1800
                                               SEC_ADS_DELETE_TREE |
 
1801
                                               SEC_ADS_LIST_OBJECT |
 
1802
                                               SEC_ADS_CONTROL_ACCESS,
 
1803
                                               0,
 
1804
                                               /* end */
 
1805
                                               NULL);
 
1806
                if (composite_nomem(v, c)) return;
 
1807
 
 
1808
                ndr_err = ndr_push_struct_blob(&vd[0], vd, iconv_convenience, v,(ndr_push_flags_fn_t)ndr_push_security_descriptor);
 
1809
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
1810
                        c->status = ndr_map_error2ntstatus(ndr_err);
 
1811
                        if (!composite_is_ok(c)) return;
 
1812
                }
 
1813
 
 
1814
                vs[0].blob              = &vd[0];
 
1815
 
 
1816
                attrs[i].attid                  = DRSUAPI_ATTRIBUTE_ntSecurityDescriptor;
 
1817
                attrs[i].value_ctr.num_values   = 1;
 
1818
                attrs[i].value_ctr.values       = vs;
 
1819
 
 
1820
                i++;
 
1821
        }
 
1822
 
 
1823
        /* objectClass: nTDSDSA */
 
1824
        {
 
1825
                struct drsuapi_DsAttributeValue *vs;
 
1826
                DATA_BLOB *vd;
 
1827
 
 
1828
                vs = talloc_array(attrs, struct drsuapi_DsAttributeValue, 1);
 
1829
                if (composite_nomem(vs, c)) return;
 
1830
 
 
1831
                vd = talloc_array(vs, DATA_BLOB, 1);
 
1832
                if (composite_nomem(vd, c)) return;
 
1833
 
 
1834
                vd[0] = data_blob_talloc(vd, NULL, 4);
 
1835
                if (composite_nomem(vd[0].data, c)) return;
 
1836
 
 
1837
                /* value for nTDSDSA */
 
1838
                SIVAL(vd[0].data, 0, 0x0017002F);
 
1839
 
 
1840
                vs[0].blob              = &vd[0];
 
1841
 
 
1842
                attrs[i].attid                  = DRSUAPI_ATTRIBUTE_objectClass;
 
1843
                attrs[i].value_ctr.num_values   = 1;
 
1844
                attrs[i].value_ctr.values       = vs;
 
1845
 
 
1846
                i++;
 
1847
        }
 
1848
 
 
1849
        /* objectCategory: CN=NTDS-DSA,CN=Schema,... */
 
1850
        {
 
1851
                struct drsuapi_DsAttributeValue *vs;
 
1852
                DATA_BLOB *vd;
 
1853
                struct drsuapi_DsReplicaObjectIdentifier3 v[1];
 
1854
 
 
1855
                vs = talloc_array(attrs, struct drsuapi_DsAttributeValue, 1);
 
1856
                if (composite_nomem(vs, c)) return;
 
1857
 
 
1858
                vd = talloc_array(vs, DATA_BLOB, 1);
 
1859
                if (composite_nomem(vd, c)) return;
 
1860
 
 
1861
                v[0].guid               = GUID_zero();
 
1862
                v[0].sid                = s->zero_sid;
 
1863
                v[0].dn                 = talloc_asprintf(vd, "CN=NTDS-DSA,%s",
 
1864
                                                          s->forest.schema_dn_str);
 
1865
                if (composite_nomem(v[0].dn, c)) return;
 
1866
 
 
1867
                ndr_err = ndr_push_struct_blob(&vd[0], vd, iconv_convenience, &v[0], 
 
1868
                                               (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
 
1869
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
1870
                        c->status = ndr_map_error2ntstatus(ndr_err);
 
1871
                        if (!composite_is_ok(c)) return;
 
1872
                }
 
1873
 
 
1874
                vs[0].blob              = &vd[0];
 
1875
 
 
1876
                attrs[i].attid                  = DRSUAPI_ATTRIBUTE_objectCategory;
 
1877
                attrs[i].value_ctr.num_values   = 1;
 
1878
                attrs[i].value_ctr.values       = vs;
 
1879
 
 
1880
                i++;
 
1881
        }
 
1882
 
 
1883
        /* invocationId: random guid */
 
1884
        {
 
1885
                struct drsuapi_DsAttributeValue *vs;
 
1886
                DATA_BLOB *vd;
 
1887
                const struct GUID *v;
 
1888
 
 
1889
                vs = talloc_array(attrs, struct drsuapi_DsAttributeValue, 1);
 
1890
                if (composite_nomem(vs, c)) return;
 
1891
 
 
1892
                vd = talloc_array(vs, DATA_BLOB, 1);
 
1893
                if (composite_nomem(vd, c)) return;
 
1894
 
 
1895
                v = &s->dest_dsa.invocation_id;
 
1896
 
 
1897
                ndr_err = ndr_push_struct_blob(&vd[0], vd, iconv_convenience, v, (ndr_push_flags_fn_t)ndr_push_GUID);
 
1898
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
1899
                        c->status = ndr_map_error2ntstatus(ndr_err);
 
1900
                        if (!composite_is_ok(c)) return;
 
1901
                }
 
1902
 
 
1903
                vs[0].blob              = &vd[0];
 
1904
 
 
1905
                attrs[i].attid                  = DRSUAPI_ATTRIBUTE_invocationId;
 
1906
                attrs[i].value_ctr.num_values   = 1;
 
1907
                attrs[i].value_ctr.values       = vs;
 
1908
 
 
1909
                i++;
 
1910
        }
 
1911
 
 
1912
        /* hasMasterNCs: ... */
 
1913
        {
 
1914
                struct drsuapi_DsAttributeValue *vs;
 
1915
                DATA_BLOB *vd;
 
1916
                struct drsuapi_DsReplicaObjectIdentifier3 v[3];
 
1917
 
 
1918
                vs = talloc_array(attrs, struct drsuapi_DsAttributeValue, 3);
 
1919
                if (composite_nomem(vs, c)) return;
 
1920
 
 
1921
                vd = talloc_array(vs, DATA_BLOB, 3);
 
1922
                if (composite_nomem(vd, c)) return;
 
1923
 
 
1924
                v[0].guid               = GUID_zero();
 
1925
                v[0].sid                = s->zero_sid;
 
1926
                v[0].dn                 = s->forest.config_dn_str;
 
1927
 
 
1928
                v[1].guid               = GUID_zero();
 
1929
                v[1].sid                = s->zero_sid;
 
1930
                v[1].dn                 = s->domain.dn_str;
 
1931
 
 
1932
                v[2].guid               = GUID_zero();
 
1933
                v[2].sid                = s->zero_sid;
 
1934
                v[2].dn                 = s->forest.schema_dn_str;
 
1935
 
 
1936
                ndr_err = ndr_push_struct_blob(&vd[0], vd, iconv_convenience, &v[0],
 
1937
                                               (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
 
1938
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
1939
                        c->status = ndr_map_error2ntstatus(ndr_err);
 
1940
                        if (!composite_is_ok(c)) return;
 
1941
                }
 
1942
 
 
1943
                ndr_err = ndr_push_struct_blob(&vd[1], vd, iconv_convenience, &v[1],
 
1944
                                               (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
 
1945
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
1946
                        c->status = ndr_map_error2ntstatus(ndr_err);
 
1947
                        if (!composite_is_ok(c)) return;
 
1948
                }
 
1949
 
 
1950
                ndr_err = ndr_push_struct_blob(&vd[2], vd, iconv_convenience, &v[2],
 
1951
                                               (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
 
1952
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
1953
                        c->status = ndr_map_error2ntstatus(ndr_err);
 
1954
                        if (!composite_is_ok(c)) return;
 
1955
                }
 
1956
 
 
1957
                vs[0].blob              = &vd[0];
 
1958
                vs[1].blob              = &vd[1];
 
1959
                vs[2].blob              = &vd[2];
 
1960
 
 
1961
                attrs[i].attid                  = DRSUAPI_ATTRIBUTE_hasMasterNCs;
 
1962
                attrs[i].value_ctr.num_values   = 3;
 
1963
                attrs[i].value_ctr.values       = vs;
 
1964
 
 
1965
                i++;
 
1966
        }
 
1967
 
 
1968
        /* msDS-hasMasterNCs: ... */
 
1969
        if (w2k3) {
 
1970
                struct drsuapi_DsAttributeValue *vs;
 
1971
                DATA_BLOB *vd;
 
1972
                struct drsuapi_DsReplicaObjectIdentifier3 v[3];
 
1973
 
 
1974
                vs = talloc_array(attrs, struct drsuapi_DsAttributeValue, 3);
 
1975
                if (composite_nomem(vs, c)) return;
 
1976
 
 
1977
                vd = talloc_array(vs, DATA_BLOB, 3);
 
1978
                if (composite_nomem(vd, c)) return;
 
1979
 
 
1980
                v[0].guid               = GUID_zero();
 
1981
                v[0].sid                = s->zero_sid;
 
1982
                v[0].dn                 = s->forest.config_dn_str;
 
1983
 
 
1984
                v[1].guid               = GUID_zero();
 
1985
                v[1].sid                = s->zero_sid;
 
1986
                v[1].dn                 = s->domain.dn_str;
 
1987
 
 
1988
                v[2].guid               = GUID_zero();
 
1989
                v[2].sid                = s->zero_sid;
 
1990
                v[2].dn                 = s->forest.schema_dn_str;
 
1991
 
 
1992
                ndr_err = ndr_push_struct_blob(&vd[0], vd, iconv_convenience, &v[0],
 
1993
                                               (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
 
1994
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
1995
                        c->status = ndr_map_error2ntstatus(ndr_err);
 
1996
                        if (!composite_is_ok(c)) return;
 
1997
                }
 
1998
 
 
1999
                ndr_err = ndr_push_struct_blob(&vd[1], vd, iconv_convenience, &v[1],
 
2000
                                               (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
 
2001
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
2002
                        c->status = ndr_map_error2ntstatus(ndr_err);
 
2003
                        if (!composite_is_ok(c)) return;
 
2004
                }
 
2005
 
 
2006
                ndr_err = ndr_push_struct_blob(&vd[2], vd, iconv_convenience, &v[2],
 
2007
                                               (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
 
2008
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
2009
                        c->status = ndr_map_error2ntstatus(ndr_err);
 
2010
                        if (!composite_is_ok(c)) return;
 
2011
                }
 
2012
 
 
2013
                vs[0].blob              = &vd[0];
 
2014
                vs[1].blob              = &vd[1];
 
2015
                vs[2].blob              = &vd[2];
 
2016
 
 
2017
                attrs[i].attid                  = DRSUAPI_ATTRIBUTE_msDS_hasMasterNCs;
 
2018
                attrs[i].value_ctr.num_values   = 3;
 
2019
                attrs[i].value_ctr.values       = vs;
 
2020
 
 
2021
                i++;
 
2022
        }
 
2023
 
 
2024
        /* dMDLocation: CN=Schema,... */
 
2025
        {
 
2026
                struct drsuapi_DsAttributeValue *vs;
 
2027
                DATA_BLOB *vd;
 
2028
                struct drsuapi_DsReplicaObjectIdentifier3 v[1];
 
2029
 
 
2030
                vs = talloc_array(attrs, struct drsuapi_DsAttributeValue, 1);
 
2031
                if (composite_nomem(vs, c)) return;
 
2032
 
 
2033
                vd = talloc_array(vs, DATA_BLOB, 1);
 
2034
                if (composite_nomem(vd, c)) return;
 
2035
 
 
2036
                v[0].guid               = GUID_zero();
 
2037
                v[0].sid                = s->zero_sid;
 
2038
                v[0].dn                 = s->forest.schema_dn_str;
 
2039
 
 
2040
                ndr_err = ndr_push_struct_blob(&vd[0], vd, iconv_convenience, &v[0],
 
2041
                                               (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
 
2042
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
2043
                        c->status = ndr_map_error2ntstatus(ndr_err);
 
2044
                        if (!composite_is_ok(c)) return;
 
2045
                }
 
2046
 
 
2047
                vs[0].blob              = &vd[0];
 
2048
 
 
2049
                attrs[i].attid                  = DRSUAPI_ATTRIBUTE_dMDLocation;
 
2050
                attrs[i].value_ctr.num_values   = 1;
 
2051
                attrs[i].value_ctr.values       = vs;
 
2052
 
 
2053
                i++;
 
2054
        }
 
2055
 
 
2056
        /* msDS-HasDomainNCs: <domain_partition> */
 
2057
        if (w2k3) {
 
2058
                struct drsuapi_DsAttributeValue *vs;
 
2059
                DATA_BLOB *vd;
 
2060
                struct drsuapi_DsReplicaObjectIdentifier3 v[1];
 
2061
 
 
2062
                vs = talloc_array(attrs, struct drsuapi_DsAttributeValue, 1);
 
2063
                if (composite_nomem(vs, c)) return;
 
2064
 
 
2065
                vd = talloc_array(vs, DATA_BLOB, 1);
 
2066
                if (composite_nomem(vd, c)) return;
 
2067
 
 
2068
                v[0].guid               = GUID_zero();
 
2069
                v[0].sid                = s->zero_sid;
 
2070
                v[0].dn                 = s->domain.dn_str;
 
2071
 
 
2072
                ndr_err = ndr_push_struct_blob(&vd[0], vd, iconv_convenience, &v[0],
 
2073
                                               (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
 
2074
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
2075
                        c->status = ndr_map_error2ntstatus(ndr_err);
 
2076
                        if (!composite_is_ok(c)) return;
 
2077
                }
 
2078
 
 
2079
                vs[0].blob              = &vd[0];
 
2080
 
 
2081
                attrs[i].attid                  = DRSUAPI_ATTRIBUTE_msDS_HasDomainNCs;
 
2082
                attrs[i].value_ctr.num_values   = 1;
 
2083
                attrs[i].value_ctr.values       = vs;
 
2084
 
 
2085
                i++;
 
2086
        }
 
2087
 
 
2088
        /* msDS-Behavior-Version */
 
2089
        if (w2k3) {
 
2090
                struct drsuapi_DsAttributeValue *vs;
 
2091
                DATA_BLOB *vd;
 
2092
 
 
2093
                vs = talloc_array(attrs, struct drsuapi_DsAttributeValue, 1);
 
2094
                if (composite_nomem(vs, c)) return;
 
2095
 
 
2096
                vd = talloc_array(vs, DATA_BLOB, 1);
 
2097
                if (composite_nomem(vd, c)) return;
 
2098
 
 
2099
                vd[0] = data_blob_talloc(vd, NULL, 4);
 
2100
                if (composite_nomem(vd[0].data, c)) return;
 
2101
 
 
2102
                SIVAL(vd[0].data, 0, DS_BEHAVIOR_WIN2008);
 
2103
 
 
2104
                vs[0].blob              = &vd[0];
 
2105
 
 
2106
                attrs[i].attid                  = DRSUAPI_ATTRIBUTE_msDS_Behavior_Version;
 
2107
                attrs[i].value_ctr.num_values   = 1;
 
2108
                attrs[i].value_ctr.values       = vs;
 
2109
 
 
2110
                i++;
 
2111
        }
 
2112
 
 
2113
        /* systemFlags */
 
2114
        {
 
2115
                struct drsuapi_DsAttributeValue *vs;
 
2116
                DATA_BLOB *vd;
 
2117
 
 
2118
                vs = talloc_array(attrs, struct drsuapi_DsAttributeValue, 1);
 
2119
                if (composite_nomem(vs, c)) return;
 
2120
 
 
2121
                vd = talloc_array(vs, DATA_BLOB, 1);
 
2122
                if (composite_nomem(vd, c)) return;
 
2123
 
 
2124
                vd[0] = data_blob_talloc(vd, NULL, 4);
 
2125
                if (composite_nomem(vd[0].data, c)) return;
 
2126
 
 
2127
                SIVAL(vd[0].data, 0, SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
 
2128
 
 
2129
                vs[0].blob              = &vd[0];
 
2130
 
 
2131
                attrs[i].attid                  = DRSUAPI_ATTRIBUTE_systemFlags;
 
2132
                attrs[i].value_ctr.num_values   = 1;
 
2133
                attrs[i].value_ctr.values       = vs;
 
2134
 
 
2135
                i++;
 
2136
        }
 
2137
 
 
2138
        /* serverReference: ... */
 
2139
        {
 
2140
                struct drsuapi_DsAttributeValue *vs;
 
2141
                DATA_BLOB *vd;
 
2142
                struct drsuapi_DsReplicaObjectIdentifier3 v[1];
 
2143
 
 
2144
                vs = talloc_array(attrs, struct drsuapi_DsAttributeValue, 1);
 
2145
                if (composite_nomem(vs, c)) return;
 
2146
 
 
2147
                vd = talloc_array(vs, DATA_BLOB, 1);
 
2148
                if (composite_nomem(vd, c)) return;
 
2149
 
 
2150
                v[0].guid               = GUID_zero();
 
2151
                v[0].sid                = s->zero_sid;
 
2152
                v[0].dn                 = s->dest_dsa.computer_dn_str;
 
2153
 
 
2154
                ndr_err = ndr_push_struct_blob(&vd[0], vd, iconv_convenience, &v[0],
 
2155
                                               (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
 
2156
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
2157
                        c->status = ndr_map_error2ntstatus(ndr_err);
 
2158
                        if (!composite_is_ok(c)) return;
 
2159
                }
 
2160
 
 
2161
                vs[0].blob              = &vd[0];
 
2162
 
 
2163
                attrs[i].attid                  = DRSUAPI_ATTRIBUTE_serverReference;
 
2164
                attrs[i].value_ctr.num_values   = 1;
 
2165
                attrs[i].value_ctr.values       = vs;
 
2166
 
 
2167
                i++;
 
2168
        }
 
2169
 
 
2170
        /* truncate the attribute list to the attribute count we have filled in */
 
2171
        num_attrs = i;
 
2172
 
 
2173
        /* setup request structure */
 
2174
        r->in.bind_handle                                               = &s->drsuapi1.bind_handle;
 
2175
        r->in.level                                                     = 2;
 
2176
        r->in.req                                                       = talloc(s, union drsuapi_DsAddEntryRequest);
 
2177
        r->in.req->req2.first_object.next_object                        = NULL;
 
2178
        r->in.req->req2.first_object.object.identifier                  = identifier;
 
2179
        r->in.req->req2.first_object.object.flags                       = 0x00000000;
 
2180
        r->in.req->req2.first_object.object.attribute_ctr.num_attributes= num_attrs;
 
2181
        r->in.req->req2.first_object.object.attribute_ctr.attributes    = attrs;
 
2182
 
 
2183
        r->out.level_out        = talloc(s, int32_t);
 
2184
        r->out.ctr              = talloc(s, union drsuapi_DsAddEntryCtr);
 
2185
 
 
2186
        req = dcerpc_drsuapi_DsAddEntry_send(s->drsuapi1.pipe, r, r);
 
2187
        composite_continue_rpc(c, req, becomeDC_drsuapi1_add_entry_recv, s);
 
2188
}
 
2189
 
 
2190
static void becomeDC_drsuapi2_connect_recv(struct composite_context *req);
 
2191
static NTSTATUS becomeDC_prepare_db(struct libnet_BecomeDC_state *s);
 
2192
 
 
2193
static void becomeDC_drsuapi1_add_entry_recv(struct rpc_request *req)
 
2194
{
 
2195
        struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
 
2196
                                          struct libnet_BecomeDC_state);
 
2197
        struct composite_context *c = s->creq;
 
2198
        struct drsuapi_DsAddEntry *r = talloc_get_type(req->ndr.struct_ptr,
 
2199
                                       struct drsuapi_DsAddEntry);
 
2200
        char *binding_str;
 
2201
        bool print = false;
 
2202
 
 
2203
        if (req->p->conn->flags & DCERPC_DEBUG_PRINT_OUT) {
 
2204
                print = true;
 
2205
        }
 
2206
 
 
2207
        c->status = dcerpc_ndr_request_recv(req);
 
2208
        if (!composite_is_ok(c)) return;
 
2209
 
 
2210
        if (print) {
 
2211
                NDR_PRINT_OUT_DEBUG(drsuapi_DsAddEntry, r);
 
2212
        }
 
2213
 
 
2214
        if (!W_ERROR_IS_OK(r->out.result)) {
 
2215
                composite_error(c, werror_to_ntstatus(r->out.result));
 
2216
                return;
 
2217
        }
 
2218
 
 
2219
        if (*r->out.level_out == 3) {
 
2220
                if (r->out.ctr->ctr3.count != 1) {
 
2221
                        WERROR status;
 
2222
 
 
2223
                        if (r->out.ctr->ctr3.level != 1) {
 
2224
                                composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
 
2225
                                return;
 
2226
                        }
 
2227
 
 
2228
                        if (!r->out.ctr->ctr3.error) {
 
2229
                                composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
 
2230
                                return;
 
2231
                        }
 
2232
 
 
2233
                        status = r->out.ctr->ctr3.error->info1.status;
 
2234
 
 
2235
                        if (!r->out.ctr->ctr3.error->info1.info) {
 
2236
                                composite_error(c, werror_to_ntstatus(status));
 
2237
                                return;
 
2238
                        }
 
2239
 
 
2240
                        /* see if we can get a more detailed error */
 
2241
                        switch (r->out.ctr->ctr3.error->info1.level) {
 
2242
                        case 1:
 
2243
                                status = r->out.ctr->ctr3.error->info1.info->error1.status;
 
2244
                                break;
 
2245
                        case 4:
 
2246
                        case 5:
 
2247
                        case 6:
 
2248
                        case 7:
 
2249
                                status = r->out.ctr->ctr3.error->info1.info->errorX.status;
 
2250
                                break;
 
2251
                        }
 
2252
 
 
2253
                        composite_error(c, werror_to_ntstatus(status));
 
2254
                        return;
 
2255
                }
 
2256
 
 
2257
                s->dest_dsa.ntds_guid   = r->out.ctr->ctr3.objects[0].guid;
 
2258
        } else if (*r->out.level_out == 2) {
 
2259
                if (r->out.ctr->ctr2.count != 1) {
 
2260
                        composite_error(c, werror_to_ntstatus(r->out.ctr->ctr2.error.status));
 
2261
                        return;
 
2262
                }
 
2263
 
 
2264
                s->dest_dsa.ntds_guid   = r->out.ctr->ctr2.objects[0].guid;
 
2265
        } else {
 
2266
                composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
 
2267
                return;
 
2268
        }
 
2269
 
 
2270
        talloc_free(r);
 
2271
 
 
2272
        s->dest_dsa.ntds_dn_str = talloc_asprintf(s, "CN=NTDS Settings,%s",
 
2273
                                                  s->dest_dsa.server_dn_str);
 
2274
        if (composite_nomem(s->dest_dsa.ntds_dn_str, c)) return;
 
2275
 
 
2276
        c->status = becomeDC_prepare_db(s);
 
2277
        if (!composite_is_ok(c)) return;
 
2278
 
 
2279
        /* this avoids the epmapper lookup on the 2nd connection */
 
2280
        binding_str = dcerpc_binding_string(s, s->drsuapi1.binding);
 
2281
        if (composite_nomem(binding_str, c)) return;
 
2282
 
 
2283
        c->status = dcerpc_parse_binding(s, binding_str, &s->drsuapi2.binding);
 
2284
        talloc_free(binding_str);
 
2285
        if (!composite_is_ok(c)) return;
 
2286
 
 
2287
        /* w2k3 uses the same assoc_group_id as on the first connection, so we do */
 
2288
        s->drsuapi2.binding->assoc_group_id     = s->drsuapi1.pipe->assoc_group_id;
 
2289
 
 
2290
        becomeDC_drsuapi_connect_send(s, &s->drsuapi2, becomeDC_drsuapi2_connect_recv);
 
2291
}
 
2292
 
 
2293
static NTSTATUS becomeDC_prepare_db(struct libnet_BecomeDC_state *s)
 
2294
{
 
2295
        if (!s->callbacks.prepare_db) return NT_STATUS_OK;
 
2296
 
 
2297
        s->_pp.domain           = &s->domain;
 
2298
        s->_pp.forest           = &s->forest;
 
2299
        s->_pp.source_dsa       = &s->source_dsa;
 
2300
        s->_pp.dest_dsa         = &s->dest_dsa;
 
2301
 
 
2302
        return s->callbacks.prepare_db(s->callbacks.private_data, &s->_pp);
 
2303
}
 
2304
 
 
2305
static void becomeDC_drsuapi2_bind_recv(struct rpc_request *req);
 
2306
 
 
2307
static void becomeDC_drsuapi2_connect_recv(struct composite_context *req)
 
2308
{
 
2309
        struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
 
2310
                                          struct libnet_BecomeDC_state);
 
2311
        struct composite_context *c = s->creq;
 
2312
 
 
2313
        c->status = dcerpc_pipe_connect_b_recv(req, s, &s->drsuapi2.pipe);
 
2314
        if (!composite_is_ok(c)) return;
 
2315
 
 
2316
        c->status = gensec_session_key(s->drsuapi2.pipe->conn->security_state.generic_state,
 
2317
                                       &s->drsuapi2.gensec_skey);
 
2318
        if (!composite_is_ok(c)) return;
 
2319
 
 
2320
        becomeDC_drsuapi_bind_send(s, &s->drsuapi2, becomeDC_drsuapi2_bind_recv);
 
2321
}
 
2322
 
 
2323
static void becomeDC_drsuapi3_connect_recv(struct composite_context *req);
 
2324
 
 
2325
static void becomeDC_drsuapi2_bind_recv(struct rpc_request *req)
 
2326
{
 
2327
        struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
 
2328
                                          struct libnet_BecomeDC_state);
 
2329
        struct composite_context *c = s->creq;
 
2330
        char *binding_str;
 
2331
        WERROR status;
 
2332
 
 
2333
        bool print = false;
 
2334
 
 
2335
        if (req->p->conn->flags & DCERPC_DEBUG_PRINT_OUT) {
 
2336
                print = true;
 
2337
        }
 
2338
 
 
2339
        c->status = dcerpc_ndr_request_recv(req);
 
2340
        if (!composite_is_ok(c)) return;
 
2341
 
 
2342
        if (print) {
 
2343
                NDR_PRINT_OUT_DEBUG(drsuapi_DsBind, &s->drsuapi2.bind_r);
 
2344
        }
 
2345
 
 
2346
        status = becomeDC_drsuapi_bind_recv(s, &s->drsuapi2);
 
2347
        if (!W_ERROR_IS_OK(status)) {
 
2348
                composite_error(c, werror_to_ntstatus(status));
 
2349
                return;
 
2350
        }
 
2351
 
 
2352
        /* this avoids the epmapper lookup on the 3rd connection */
 
2353
        binding_str = dcerpc_binding_string(s, s->drsuapi1.binding);
 
2354
        if (composite_nomem(binding_str, c)) return;
 
2355
 
 
2356
        c->status = dcerpc_parse_binding(s, binding_str, &s->drsuapi3.binding);
 
2357
        talloc_free(binding_str);
 
2358
        if (!composite_is_ok(c)) return;
 
2359
 
 
2360
        /* w2k3 uses the same assoc_group_id as on the first connection, so we do */
 
2361
        s->drsuapi3.binding->assoc_group_id     = s->drsuapi1.pipe->assoc_group_id;
 
2362
        /* w2k3 uses the concurrent multiplex feature on the 3rd connection, so we do */
 
2363
        s->drsuapi3.binding->flags              |= DCERPC_CONCURRENT_MULTIPLEX;
 
2364
 
 
2365
        becomeDC_drsuapi_connect_send(s, &s->drsuapi3, becomeDC_drsuapi3_connect_recv);
 
2366
}
 
2367
 
 
2368
static void becomeDC_drsuapi3_pull_schema_send(struct libnet_BecomeDC_state *s);
 
2369
 
 
2370
static void becomeDC_drsuapi3_connect_recv(struct composite_context *req)
 
2371
{
 
2372
        struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
 
2373
                                          struct libnet_BecomeDC_state);
 
2374
        struct composite_context *c = s->creq;
 
2375
 
 
2376
        c->status = dcerpc_pipe_connect_b_recv(req, s, &s->drsuapi3.pipe);
 
2377
        if (!composite_is_ok(c)) return;
 
2378
 
 
2379
        c->status = gensec_session_key(s->drsuapi3.pipe->conn->security_state.generic_state,
 
2380
                                       &s->drsuapi3.gensec_skey);
 
2381
        if (!composite_is_ok(c)) return;
 
2382
 
 
2383
        becomeDC_drsuapi3_pull_schema_send(s);
 
2384
}
 
2385
 
 
2386
static void becomeDC_drsuapi_pull_partition_send(struct libnet_BecomeDC_state *s,
 
2387
                                                 struct becomeDC_drsuapi *drsuapi_h,
 
2388
                                                 struct becomeDC_drsuapi *drsuapi_p,
 
2389
                                                 struct libnet_BecomeDC_Partition *partition,
 
2390
                                                 void (*recv_fn)(struct rpc_request *req))
 
2391
{
 
2392
        struct composite_context *c = s->creq;
 
2393
        struct rpc_request *req;
 
2394
        struct drsuapi_DsGetNCChanges *r;
 
2395
 
 
2396
        r = talloc(s, struct drsuapi_DsGetNCChanges);
 
2397
        if (composite_nomem(r, c)) return;
 
2398
 
 
2399
        r->out.level_out = talloc(r, int32_t);
 
2400
        if (composite_nomem(r->out.level_out, c)) return;
 
2401
        r->in.req = talloc(r, union drsuapi_DsGetNCChangesRequest);
 
2402
        if (composite_nomem(r->in.req, c)) return;
 
2403
        r->out.ctr = talloc(r, union drsuapi_DsGetNCChangesCtr);
 
2404
        if (composite_nomem(r->out.ctr, c)) return;
 
2405
 
 
2406
        r->in.bind_handle       = &drsuapi_h->bind_handle;
 
2407
        if (drsuapi_h->remote_info28.supported_extensions & DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8) {
 
2408
                r->in.level                             = 8;
 
2409
                r->in.req->req8.destination_dsa_guid    = partition->destination_dsa_guid;
 
2410
                r->in.req->req8.source_dsa_invocation_id= partition->source_dsa_invocation_id;
 
2411
                r->in.req->req8.naming_context          = &partition->nc;
 
2412
                r->in.req->req8.highwatermark           = partition->highwatermark;
 
2413
                r->in.req->req8.uptodateness_vector     = NULL;
 
2414
                r->in.req->req8.replica_flags           = partition->replica_flags;
 
2415
                r->in.req->req8.max_object_count        = 133;
 
2416
                r->in.req->req8.max_ndr_size            = 1336811;
 
2417
                r->in.req->req8.extended_op             = DRSUAPI_EXOP_NONE;
 
2418
                r->in.req->req8.fsmo_info               = 0;
 
2419
                r->in.req->req8.partial_attribute_set   = NULL;
 
2420
                r->in.req->req8.partial_attribute_set_ex= NULL;
 
2421
                r->in.req->req8.mapping_ctr.num_mappings= 0;
 
2422
                r->in.req->req8.mapping_ctr.mappings    = NULL;
 
2423
        } else {
 
2424
                r->in.level                             = 5;
 
2425
                r->in.req->req5.destination_dsa_guid    = partition->destination_dsa_guid;
 
2426
                r->in.req->req5.source_dsa_invocation_id= partition->source_dsa_invocation_id;
 
2427
                r->in.req->req5.naming_context          = &partition->nc;
 
2428
                r->in.req->req5.highwatermark           = partition->highwatermark;
 
2429
                r->in.req->req5.uptodateness_vector     = NULL;
 
2430
                r->in.req->req5.replica_flags           = partition->replica_flags;
 
2431
                r->in.req->req5.max_object_count        = 133;
 
2432
                r->in.req->req5.max_ndr_size            = 1336770;
 
2433
                r->in.req->req5.extended_op             = DRSUAPI_EXOP_NONE;
 
2434
                r->in.req->req5.fsmo_info               = 0;
 
2435
        }
 
2436
 
 
2437
        /* 
 
2438
         * we should try to use the drsuapi_p->pipe here, as w2k3 does
 
2439
         * but it seems that some extra flags in the DCERPC Bind call
 
2440
         * are needed for it. Or the same KRB5 TGS is needed on both
 
2441
         * connections.
 
2442
         */
 
2443
        req = dcerpc_drsuapi_DsGetNCChanges_send(drsuapi_p->pipe, r, r);
 
2444
        composite_continue_rpc(c, req, recv_fn, s);
 
2445
}
 
2446
 
 
2447
static WERROR becomeDC_drsuapi_pull_partition_recv(struct libnet_BecomeDC_state *s,
 
2448
                                                   struct becomeDC_drsuapi *drsuapi_h,
 
2449
                                                   struct becomeDC_drsuapi *drsuapi_p,
 
2450
                                                   struct libnet_BecomeDC_Partition *partition,
 
2451
                                                   struct drsuapi_DsGetNCChanges *r)
 
2452
{
 
2453
        uint32_t ctr_level = 0;
 
2454
        struct drsuapi_DsGetNCChangesCtr1 *ctr1 = NULL;
 
2455
        struct drsuapi_DsGetNCChangesCtr6 *ctr6 = NULL;
 
2456
        struct GUID *source_dsa_guid;
 
2457
        struct GUID *source_dsa_invocation_id;
 
2458
        struct drsuapi_DsReplicaHighWaterMark *new_highwatermark;
 
2459
        bool more_data = false;
 
2460
        NTSTATUS nt_status;
 
2461
 
 
2462
        if (!W_ERROR_IS_OK(r->out.result)) {
 
2463
                return r->out.result;
 
2464
        }
 
2465
 
 
2466
        if (*r->out.level_out == 1) {
 
2467
                ctr_level = 1;
 
2468
                ctr1 = &r->out.ctr->ctr1;
 
2469
        } else if (*r->out.level_out == 2 &&
 
2470
                   r->out.ctr->ctr2.mszip1.ts) {
 
2471
                ctr_level = 1;
 
2472
                ctr1 = &r->out.ctr->ctr2.mszip1.ts->ctr1;
 
2473
        } else if (*r->out.level_out == 6) {
 
2474
                ctr_level = 6;
 
2475
                ctr6 = &r->out.ctr->ctr6;
 
2476
        } else if (*r->out.level_out == 7 &&
 
2477
                   r->out.ctr->ctr7.level == 6 &&
 
2478
                   r->out.ctr->ctr7.type == DRSUAPI_COMPRESSION_TYPE_MSZIP &&
 
2479
                   r->out.ctr->ctr7.ctr.mszip6.ts) {
 
2480
                ctr_level = 6;
 
2481
                ctr6 = &r->out.ctr->ctr7.ctr.mszip6.ts->ctr6;
 
2482
        } else if (*r->out.level_out == 7 &&
 
2483
                   r->out.ctr->ctr7.level == 6 &&
 
2484
                   r->out.ctr->ctr7.type == DRSUAPI_COMPRESSION_TYPE_XPRESS &&
 
2485
                   r->out.ctr->ctr7.ctr.xpress6.ts) {
 
2486
                ctr_level = 6;
 
2487
                ctr6 = &r->out.ctr->ctr7.ctr.xpress6.ts->ctr6;
 
2488
        } else {
 
2489
                return WERR_BAD_NET_RESP;
 
2490
        }
 
2491
 
 
2492
        if (!ctr1 && ! ctr6) {
 
2493
                return WERR_BAD_NET_RESP;
 
2494
        }
 
2495
 
 
2496
        if (ctr_level == 6) {
 
2497
                if (!W_ERROR_IS_OK(ctr6->drs_error)) {
 
2498
                        return ctr6->drs_error;
 
2499
                }
 
2500
        }
 
2501
 
 
2502
        switch (ctr_level) {
 
2503
        case 1:
 
2504
                source_dsa_guid                 = &ctr1->source_dsa_guid;
 
2505
                source_dsa_invocation_id        = &ctr1->source_dsa_invocation_id;
 
2506
                new_highwatermark               = &ctr1->new_highwatermark;
 
2507
                more_data                       = ctr1->more_data;
 
2508
                break;
 
2509
        case 6:
 
2510
                source_dsa_guid                 = &ctr6->source_dsa_guid;
 
2511
                source_dsa_invocation_id        = &ctr6->source_dsa_invocation_id;
 
2512
                new_highwatermark               = &ctr6->new_highwatermark;
 
2513
                more_data                       = ctr6->more_data;
 
2514
                break;
 
2515
        }
 
2516
 
 
2517
        partition->highwatermark                = *new_highwatermark;
 
2518
        partition->source_dsa_guid              = *source_dsa_guid;
 
2519
        partition->source_dsa_invocation_id     = *source_dsa_invocation_id;
 
2520
        partition->more_data                    = more_data;
 
2521
 
 
2522
        if (!partition->store_chunk) return WERR_OK;
 
2523
 
 
2524
        s->_sc.domain           = &s->domain;
 
2525
        s->_sc.forest           = &s->forest;
 
2526
        s->_sc.source_dsa       = &s->source_dsa;
 
2527
        s->_sc.dest_dsa         = &s->dest_dsa;
 
2528
        s->_sc.partition        = partition;
 
2529
        s->_sc.ctr_level        = ctr_level;
 
2530
        s->_sc.ctr1             = ctr1;
 
2531
        s->_sc.ctr6             = ctr6;
 
2532
        /* 
 
2533
         * we need to use the drsuapi_p->gensec_skey here,
 
2534
         * when we use drsuapi_p->pipe in the for this request
 
2535
         */
 
2536
        s->_sc.gensec_skey      = &drsuapi_p->gensec_skey;
 
2537
 
 
2538
        nt_status = partition->store_chunk(s->callbacks.private_data, &s->_sc);
 
2539
        if (!NT_STATUS_IS_OK(nt_status)) {
 
2540
                return ntstatus_to_werror(nt_status);
 
2541
        }
 
2542
 
 
2543
        return WERR_OK;
 
2544
}
 
2545
 
 
2546
static void becomeDC_drsuapi3_pull_schema_recv(struct rpc_request *req);
 
2547
 
 
2548
static void becomeDC_drsuapi3_pull_schema_send(struct libnet_BecomeDC_state *s)
 
2549
{
 
2550
        s->schema_part.nc.guid  = GUID_zero();
 
2551
        s->schema_part.nc.sid   = s->zero_sid;
 
2552
        s->schema_part.nc.dn    = s->forest.schema_dn_str;
 
2553
 
 
2554
        s->schema_part.destination_dsa_guid     = s->drsuapi2.bind_guid;
 
2555
 
 
2556
        s->schema_part.replica_flags    = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
 
2557
                                        | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
 
2558
                                        | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS
 
2559
                                        | DRSUAPI_DS_REPLICA_NEIGHBOUR_FULL_IN_PROGRESS
 
2560
                                        | DRSUAPI_DS_REPLICA_NEIGHBOUR_NEVER_SYNCED
 
2561
                                        | DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES;
 
2562
 
 
2563
        s->schema_part.store_chunk      = s->callbacks.schema_chunk;
 
2564
 
 
2565
        becomeDC_drsuapi_pull_partition_send(s, &s->drsuapi2, &s->drsuapi3, &s->schema_part,
 
2566
                                             becomeDC_drsuapi3_pull_schema_recv);
 
2567
}
 
2568
 
 
2569
static void becomeDC_drsuapi3_pull_config_send(struct libnet_BecomeDC_state *s);
 
2570
 
 
2571
static void becomeDC_drsuapi3_pull_schema_recv(struct rpc_request *req)
 
2572
{
 
2573
        struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
 
2574
                                          struct libnet_BecomeDC_state);
 
2575
        struct composite_context *c = s->creq;
 
2576
        struct drsuapi_DsGetNCChanges *r = talloc_get_type(req->ndr.struct_ptr,
 
2577
                                           struct drsuapi_DsGetNCChanges);
 
2578
        WERROR status;
 
2579
 
 
2580
        bool print = false;
 
2581
 
 
2582
        if (req->p->conn->flags & DCERPC_DEBUG_PRINT_OUT) {
 
2583
                print = true;
 
2584
        }
 
2585
 
 
2586
        c->status = dcerpc_ndr_request_recv(req);
 
2587
        if (!composite_is_ok(c)) return;
 
2588
 
 
2589
        if (print) {
 
2590
                NDR_PRINT_OUT_DEBUG(drsuapi_DsGetNCChanges, r);
 
2591
        }
 
2592
 
 
2593
        status = becomeDC_drsuapi_pull_partition_recv(s, &s->drsuapi2, &s->drsuapi3, &s->schema_part, r);
 
2594
        if (!W_ERROR_IS_OK(status)) {
 
2595
                composite_error(c, werror_to_ntstatus(status));
 
2596
                return;
 
2597
        }
 
2598
 
 
2599
        talloc_free(r);
 
2600
 
 
2601
        if (s->schema_part.more_data) {
 
2602
                becomeDC_drsuapi_pull_partition_send(s, &s->drsuapi2, &s->drsuapi3, &s->schema_part,
 
2603
                                                     becomeDC_drsuapi3_pull_schema_recv);
 
2604
                return;
 
2605
        }
 
2606
 
 
2607
        becomeDC_drsuapi3_pull_config_send(s);
 
2608
}
 
2609
 
 
2610
static void becomeDC_drsuapi3_pull_config_recv(struct rpc_request *req);
 
2611
 
 
2612
static void becomeDC_drsuapi3_pull_config_send(struct libnet_BecomeDC_state *s)
 
2613
{
 
2614
        s->config_part.nc.guid  = GUID_zero();
 
2615
        s->config_part.nc.sid   = s->zero_sid;
 
2616
        s->config_part.nc.dn    = s->forest.config_dn_str;
 
2617
 
 
2618
        s->config_part.destination_dsa_guid     = s->drsuapi2.bind_guid;
 
2619
 
 
2620
        s->config_part.replica_flags    = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
 
2621
                                        | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
 
2622
                                        | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS
 
2623
                                        | DRSUAPI_DS_REPLICA_NEIGHBOUR_FULL_IN_PROGRESS
 
2624
                                        | DRSUAPI_DS_REPLICA_NEIGHBOUR_NEVER_SYNCED
 
2625
                                        | DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES;
 
2626
 
 
2627
        s->config_part.store_chunk      = s->callbacks.config_chunk;
 
2628
 
 
2629
        becomeDC_drsuapi_pull_partition_send(s, &s->drsuapi2, &s->drsuapi3, &s->config_part,
 
2630
                                             becomeDC_drsuapi3_pull_config_recv);
 
2631
}
 
2632
 
 
2633
static void becomeDC_drsuapi3_pull_config_recv(struct rpc_request *req)
 
2634
{
 
2635
        struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
 
2636
                                          struct libnet_BecomeDC_state);
 
2637
        struct composite_context *c = s->creq;
 
2638
        struct drsuapi_DsGetNCChanges *r = talloc_get_type(req->ndr.struct_ptr,
 
2639
                                           struct drsuapi_DsGetNCChanges);
 
2640
        WERROR status;
 
2641
 
 
2642
        bool print = false;
 
2643
 
 
2644
        if (req->p->conn->flags & DCERPC_DEBUG_PRINT_OUT) {
 
2645
                print = true;
 
2646
        }
 
2647
 
 
2648
        c->status = dcerpc_ndr_request_recv(req);
 
2649
        if (!composite_is_ok(c)) return;
 
2650
 
 
2651
        if (print) {
 
2652
                NDR_PRINT_OUT_DEBUG(drsuapi_DsGetNCChanges, r);
 
2653
        }
 
2654
 
 
2655
        status = becomeDC_drsuapi_pull_partition_recv(s, &s->drsuapi2, &s->drsuapi3, &s->config_part, r);
 
2656
        if (!W_ERROR_IS_OK(status)) {
 
2657
                composite_error(c, werror_to_ntstatus(status));
 
2658
                return;
 
2659
        }
 
2660
 
 
2661
        talloc_free(r);
 
2662
 
 
2663
        if (s->config_part.more_data) {
 
2664
                becomeDC_drsuapi_pull_partition_send(s, &s->drsuapi2, &s->drsuapi3, &s->config_part,
 
2665
                                                     becomeDC_drsuapi3_pull_config_recv);
 
2666
                return;
 
2667
        }
 
2668
 
 
2669
        becomeDC_connect_ldap2(s);
 
2670
}
 
2671
 
 
2672
static void becomeDC_drsuapi3_pull_domain_recv(struct rpc_request *req);
 
2673
 
 
2674
static void becomeDC_drsuapi3_pull_domain_send(struct libnet_BecomeDC_state *s)
 
2675
{
 
2676
        s->domain_part.nc.guid  = GUID_zero();
 
2677
        s->domain_part.nc.sid   = s->zero_sid;
 
2678
        s->domain_part.nc.dn    = s->domain.dn_str;
 
2679
 
 
2680
        s->domain_part.destination_dsa_guid     = s->drsuapi2.bind_guid;
 
2681
 
 
2682
        s->domain_part.replica_flags    = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
 
2683
                                        | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
 
2684
                                        | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS
 
2685
                                        | DRSUAPI_DS_REPLICA_NEIGHBOUR_FULL_IN_PROGRESS
 
2686
                                        | DRSUAPI_DS_REPLICA_NEIGHBOUR_NEVER_SYNCED
 
2687
                                        | DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES;
 
2688
 
 
2689
        s->domain_part.store_chunk      = s->callbacks.domain_chunk;
 
2690
 
 
2691
        becomeDC_drsuapi_pull_partition_send(s, &s->drsuapi2, &s->drsuapi3, &s->domain_part,
 
2692
                                             becomeDC_drsuapi3_pull_domain_recv);
 
2693
}
 
2694
 
 
2695
static void becomeDC_drsuapi_update_refs_send(struct libnet_BecomeDC_state *s,
 
2696
                                              struct becomeDC_drsuapi *drsuapi,
 
2697
                                              struct libnet_BecomeDC_Partition *partition,
 
2698
                                              void (*recv_fn)(struct rpc_request *req));
 
2699
static void becomeDC_drsuapi2_update_refs_schema_recv(struct rpc_request *req);
 
2700
 
 
2701
static void becomeDC_drsuapi3_pull_domain_recv(struct rpc_request *req)
 
2702
{
 
2703
        struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
 
2704
                                          struct libnet_BecomeDC_state);
 
2705
        struct composite_context *c = s->creq;
 
2706
        struct drsuapi_DsGetNCChanges *r = talloc_get_type(req->ndr.struct_ptr,
 
2707
                                           struct drsuapi_DsGetNCChanges);
 
2708
        WERROR status;
 
2709
        bool print = false;
 
2710
 
 
2711
        if (req->p->conn->flags & DCERPC_DEBUG_PRINT_OUT) {
 
2712
                print = true;
 
2713
        }
 
2714
 
 
2715
        c->status = dcerpc_ndr_request_recv(req);
 
2716
        if (!composite_is_ok(c)) return;
 
2717
 
 
2718
        if (print) {
 
2719
                NDR_PRINT_OUT_DEBUG(drsuapi_DsGetNCChanges, r);
 
2720
        }
 
2721
 
 
2722
        status = becomeDC_drsuapi_pull_partition_recv(s, &s->drsuapi2, &s->drsuapi3, &s->domain_part, r);
 
2723
        if (!W_ERROR_IS_OK(status)) {
 
2724
                composite_error(c, werror_to_ntstatus(status));
 
2725
                return;
 
2726
        }
 
2727
 
 
2728
        talloc_free(r);
 
2729
 
 
2730
        if (s->domain_part.more_data) {
 
2731
                becomeDC_drsuapi_pull_partition_send(s, &s->drsuapi2, &s->drsuapi3, &s->domain_part,
 
2732
                                                     becomeDC_drsuapi3_pull_domain_recv);
 
2733
                return;
 
2734
        }
 
2735
 
 
2736
        becomeDC_drsuapi_update_refs_send(s, &s->drsuapi2, &s->schema_part,
 
2737
                                          becomeDC_drsuapi2_update_refs_schema_recv);
 
2738
}
 
2739
 
 
2740
static void becomeDC_drsuapi_update_refs_send(struct libnet_BecomeDC_state *s,
 
2741
                                              struct becomeDC_drsuapi *drsuapi,
 
2742
                                              struct libnet_BecomeDC_Partition *partition,
 
2743
                                              void (*recv_fn)(struct rpc_request *req))
 
2744
{
 
2745
        struct composite_context *c = s->creq;
 
2746
        struct rpc_request *req;
 
2747
        struct drsuapi_DsReplicaUpdateRefs *r;
 
2748
        const char *ntds_guid_str;
 
2749
        const char *ntds_dns_name;
 
2750
 
 
2751
        r = talloc(s, struct drsuapi_DsReplicaUpdateRefs);
 
2752
        if (composite_nomem(r, c)) return;
 
2753
 
 
2754
        ntds_guid_str = GUID_string(r, &s->dest_dsa.ntds_guid);
 
2755
        if (composite_nomem(ntds_guid_str, c)) return;
 
2756
 
 
2757
        ntds_dns_name = talloc_asprintf(r, "%s._msdcs.%s",
 
2758
                                        ntds_guid_str,
 
2759
                                        s->domain.dns_name);
 
2760
        if (composite_nomem(ntds_dns_name, c)) return;
 
2761
 
 
2762
        r->in.bind_handle               = &drsuapi->bind_handle;
 
2763
        r->in.level                     = 1;
 
2764
        r->in.req.req1.naming_context   = &partition->nc;
 
2765
        r->in.req.req1.dest_dsa_dns_name= ntds_dns_name;
 
2766
        r->in.req.req1.dest_dsa_guid    = s->dest_dsa.ntds_guid;
 
2767
        r->in.req.req1.options          = DRSUAPI_DS_REPLICA_UPDATE_ADD_REFERENCE
 
2768
                                        | DRSUAPI_DS_REPLICA_UPDATE_DELETE_REFERENCE
 
2769
                                        | DRSUAPI_DS_REPLICA_UPDATE_0x00000010;
 
2770
 
 
2771
        req = dcerpc_drsuapi_DsReplicaUpdateRefs_send(drsuapi->pipe, r, r);
 
2772
        composite_continue_rpc(c, req, recv_fn, s);
 
2773
}
 
2774
 
 
2775
static void becomeDC_drsuapi2_update_refs_config_recv(struct rpc_request *req);
 
2776
 
 
2777
static void becomeDC_drsuapi2_update_refs_schema_recv(struct rpc_request *req)
 
2778
{
 
2779
        struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
 
2780
                                          struct libnet_BecomeDC_state);
 
2781
        struct composite_context *c = s->creq;
 
2782
        struct drsuapi_DsReplicaUpdateRefs *r = talloc_get_type(req->ndr.struct_ptr,
 
2783
                                           struct drsuapi_DsReplicaUpdateRefs);
 
2784
        bool print = false;
 
2785
 
 
2786
        if (req->p->conn->flags & DCERPC_DEBUG_PRINT_OUT) {
 
2787
                print = true;
 
2788
        }
 
2789
 
 
2790
        c->status = dcerpc_ndr_request_recv(req);
 
2791
        if (!composite_is_ok(c)) return;
 
2792
 
 
2793
        if (print) {
 
2794
                NDR_PRINT_OUT_DEBUG(drsuapi_DsReplicaUpdateRefs, r);
 
2795
        }
 
2796
 
 
2797
        if (!W_ERROR_IS_OK(r->out.result)) {
 
2798
                composite_error(c, werror_to_ntstatus(r->out.result));
 
2799
                return;
 
2800
        }
 
2801
 
 
2802
        talloc_free(r);
 
2803
 
 
2804
        becomeDC_drsuapi_update_refs_send(s, &s->drsuapi2, &s->config_part,
 
2805
                                          becomeDC_drsuapi2_update_refs_config_recv);
 
2806
}
 
2807
 
 
2808
static void becomeDC_drsuapi2_update_refs_domain_recv(struct rpc_request *req);
 
2809
 
 
2810
static void becomeDC_drsuapi2_update_refs_config_recv(struct rpc_request *req)
 
2811
{
 
2812
        struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
 
2813
                                          struct libnet_BecomeDC_state);
 
2814
        struct composite_context *c = s->creq;
 
2815
        struct drsuapi_DsReplicaUpdateRefs *r = talloc_get_type(req->ndr.struct_ptr,
 
2816
                                           struct drsuapi_DsReplicaUpdateRefs);
 
2817
 
 
2818
        c->status = dcerpc_ndr_request_recv(req);
 
2819
        if (!composite_is_ok(c)) return;
 
2820
 
 
2821
        if (!W_ERROR_IS_OK(r->out.result)) {
 
2822
                composite_error(c, werror_to_ntstatus(r->out.result));
 
2823
                return;
 
2824
        }
 
2825
 
 
2826
        talloc_free(r);
 
2827
 
 
2828
        becomeDC_drsuapi_update_refs_send(s, &s->drsuapi2, &s->domain_part,
 
2829
                                          becomeDC_drsuapi2_update_refs_domain_recv);
 
2830
}
 
2831
 
 
2832
static void becomeDC_drsuapi2_update_refs_domain_recv(struct rpc_request *req)
 
2833
{
 
2834
        struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
 
2835
                                          struct libnet_BecomeDC_state);
 
2836
        struct composite_context *c = s->creq;
 
2837
        struct drsuapi_DsReplicaUpdateRefs *r = talloc_get_type(req->ndr.struct_ptr,
 
2838
                                           struct drsuapi_DsReplicaUpdateRefs);
 
2839
 
 
2840
        c->status = dcerpc_ndr_request_recv(req);
 
2841
        if (!composite_is_ok(c)) return;
 
2842
 
 
2843
        if (!W_ERROR_IS_OK(r->out.result)) {
 
2844
                composite_error(c, werror_to_ntstatus(r->out.result));
 
2845
                return;
 
2846
        }
 
2847
 
 
2848
        talloc_free(r);
 
2849
 
 
2850
        /* TODO: use DDNS updates and register dns names */
 
2851
        composite_done(c);
 
2852
}
 
2853
 
 
2854
static NTSTATUS becomeDC_ldap2_modify_computer(struct libnet_BecomeDC_state *s)
 
2855
{
 
2856
        int ret;
 
2857
        struct ldb_message *msg;
 
2858
        uint32_t i;
 
2859
        uint32_t user_account_control = UF_SERVER_TRUST_ACCOUNT |
 
2860
                                        UF_TRUSTED_FOR_DELEGATION;
 
2861
 
 
2862
        /* as the value is already as we want it to be, we're done */
 
2863
        if (s->dest_dsa.user_account_control == user_account_control) {
 
2864
                return NT_STATUS_OK;
 
2865
        }
 
2866
 
 
2867
        /* make a 'modify' msg, and only for serverReference */
 
2868
        msg = ldb_msg_new(s);
 
2869
        NT_STATUS_HAVE_NO_MEMORY(msg);
 
2870
        msg->dn = ldb_dn_new(msg, s->ldap2.ldb, s->dest_dsa.computer_dn_str);
 
2871
        NT_STATUS_HAVE_NO_MEMORY(msg->dn);
 
2872
 
 
2873
        ret = ldb_msg_add_fmt(msg, "userAccountControl", "%u", user_account_control);
 
2874
        if (ret != 0) {
 
2875
                talloc_free(msg);
 
2876
                return NT_STATUS_NO_MEMORY;
 
2877
        }
 
2878
 
 
2879
        /* mark all the message elements (should be just one)
 
2880
           as LDB_FLAG_MOD_REPLACE */
 
2881
        for (i=0;i<msg->num_elements;i++) {
 
2882
                msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
 
2883
        }
 
2884
 
 
2885
        ret = ldb_modify(s->ldap2.ldb, msg);
 
2886
        talloc_free(msg);
 
2887
        if (ret != LDB_SUCCESS) {
 
2888
                return NT_STATUS_LDAP(ret);
 
2889
        }
 
2890
 
 
2891
        s->dest_dsa.user_account_control = user_account_control;
 
2892
 
 
2893
        return NT_STATUS_OK;
 
2894
}
 
2895
 
 
2896
static NTSTATUS becomeDC_ldap2_move_computer(struct libnet_BecomeDC_state *s)
 
2897
{
 
2898
        int ret;
 
2899
        struct ldb_result *r;
 
2900
        struct ldb_dn *basedn;
 
2901
        struct ldb_dn *old_dn;
 
2902
        struct ldb_dn *new_dn;
 
2903
        static const char *_1_1_attrs[] = {
 
2904
                "1.1",
 
2905
                NULL
 
2906
        };
 
2907
 
 
2908
        basedn = ldb_dn_new_fmt(s, s->ldap2.ldb, "<WKGUID=a361b2ffffd211d1aa4b00c04fd7d83a,%s>",
 
2909
                                s->domain.dn_str);
 
2910
        NT_STATUS_HAVE_NO_MEMORY(basedn);
 
2911
 
 
2912
        ret = ldb_search(s->ldap2.ldb, s, &r, basedn, LDB_SCOPE_BASE,
 
2913
                         _1_1_attrs, "(objectClass=*)");
 
2914
        talloc_free(basedn);
 
2915
        if (ret != LDB_SUCCESS) {
 
2916
                return NT_STATUS_LDAP(ret);
 
2917
        } else if (r->count != 1) {
 
2918
                talloc_free(r);
 
2919
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
 
2920
        }
 
2921
 
 
2922
        old_dn = ldb_dn_new(r, s->ldap2.ldb, s->dest_dsa.computer_dn_str);
 
2923
        NT_STATUS_HAVE_NO_MEMORY(old_dn);
 
2924
 
 
2925
        new_dn = r->msgs[0]->dn;
 
2926
 
 
2927
        if (!ldb_dn_add_child_fmt(new_dn, "CN=%s", s->dest_dsa.netbios_name)) {
 
2928
                talloc_free(r);
 
2929
                return NT_STATUS_NO_MEMORY;
 
2930
        }
 
2931
 
 
2932
        if (ldb_dn_compare(old_dn, new_dn) == 0) {
 
2933
                /* we don't need to rename if the old and new dn match */
 
2934
                talloc_free(r);
 
2935
                return NT_STATUS_OK;
 
2936
        }
 
2937
 
 
2938
        ret = ldb_rename(s->ldap2.ldb, old_dn, new_dn);
 
2939
        if (ret != LDB_SUCCESS) {
 
2940
                talloc_free(r);
 
2941
                return NT_STATUS_LDAP(ret);
 
2942
        }
 
2943
 
 
2944
        s->dest_dsa.computer_dn_str = ldb_dn_alloc_linearized(s, new_dn);
 
2945
        NT_STATUS_HAVE_NO_MEMORY(s->dest_dsa.computer_dn_str);
 
2946
 
 
2947
        talloc_free(r);
 
2948
 
 
2949
        return NT_STATUS_OK;
 
2950
}
 
2951
 
 
2952
static void becomeDC_connect_ldap2(struct libnet_BecomeDC_state *s)
 
2953
{
 
2954
        struct composite_context *c = s->creq;
 
2955
 
 
2956
        c->status = becomeDC_ldap_connect(s, &s->ldap2);
 
2957
        if (!composite_is_ok(c)) return;
 
2958
 
 
2959
        c->status = becomeDC_ldap2_modify_computer(s);
 
2960
        if (!composite_is_ok(c)) return;
 
2961
 
 
2962
        c->status = becomeDC_ldap2_move_computer(s);
 
2963
        if (!composite_is_ok(c)) return;
 
2964
 
 
2965
        becomeDC_drsuapi3_pull_domain_send(s);
 
2966
}
 
2967
 
 
2968
struct composite_context *libnet_BecomeDC_send(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_BecomeDC *r)
 
2969
{
 
2970
        struct composite_context *c;
 
2971
        struct libnet_BecomeDC_state *s;
 
2972
        char *tmp_name;
 
2973
 
 
2974
        c = composite_create(mem_ctx, ctx->event_ctx);
 
2975
        if (c == NULL) return NULL;
 
2976
 
 
2977
        s = talloc_zero(c, struct libnet_BecomeDC_state);
 
2978
        if (composite_nomem(s, c)) return c;
 
2979
        c->private_data = s;
 
2980
        s->creq         = c;
 
2981
        s->libnet       = ctx;
 
2982
 
 
2983
        /* Domain input */
 
2984
        s->domain.dns_name      = talloc_strdup(s, r->in.domain_dns_name);
 
2985
        if (composite_nomem(s->domain.dns_name, c)) return c;
 
2986
        s->domain.netbios_name  = talloc_strdup(s, r->in.domain_netbios_name);
 
2987
        if (composite_nomem(s->domain.netbios_name, c)) return c;
 
2988
        s->domain.sid           = dom_sid_dup(s, r->in.domain_sid);
 
2989
        if (composite_nomem(s->domain.sid, c)) return c;
 
2990
 
 
2991
        /* Source DSA input */
 
2992
        s->source_dsa.address   = talloc_strdup(s, r->in.source_dsa_address);
 
2993
        if (composite_nomem(s->source_dsa.address, c)) return c;
 
2994
 
 
2995
        /* Destination DSA input */
 
2996
        s->dest_dsa.netbios_name= talloc_strdup(s, r->in.dest_dsa_netbios_name);
 
2997
        if (composite_nomem(s->dest_dsa.netbios_name, c)) return c;
 
2998
 
 
2999
        /* Destination DSA dns_name construction */
 
3000
        tmp_name        = strlower_talloc(s, s->dest_dsa.netbios_name);
 
3001
        if (composite_nomem(tmp_name, c)) return c;
 
3002
        tmp_name        = talloc_asprintf_append_buffer(tmp_name, ".%s",s->domain.dns_name);
 
3003
        if (composite_nomem(tmp_name, c)) return c;
 
3004
        s->dest_dsa.dns_name    = tmp_name;
 
3005
 
 
3006
        /* Callback function pointers */
 
3007
        s->callbacks = r->in.callbacks;
 
3008
 
 
3009
        becomeDC_send_cldap(s);
 
3010
        return c;
 
3011
}
 
3012
 
 
3013
NTSTATUS libnet_BecomeDC_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, struct libnet_BecomeDC *r)
 
3014
{
 
3015
        NTSTATUS status;
 
3016
 
 
3017
        status = composite_wait(c);
 
3018
 
 
3019
        ZERO_STRUCT(r->out);
 
3020
 
 
3021
        talloc_free(c);
 
3022
        return status;
 
3023
}
 
3024
 
 
3025
NTSTATUS libnet_BecomeDC(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_BecomeDC *r)
 
3026
{
 
3027
        NTSTATUS status;
 
3028
        struct composite_context *c;
 
3029
        c = libnet_BecomeDC_send(ctx, mem_ctx, r);
 
3030
        status = libnet_BecomeDC_recv(c, mem_ctx, r);
 
3031
        return status;
 
3032
}