r25446: Merge some changes I made on the way home from SFO:
[tprouty/samba.git] / source4 / libnet / libnet_become_dc.c
index a302ded4f5b082850603c1d5ba320afc0ce8170a..cd782066dbe3e420893acfaf3f867b2dce80b2da 100644 (file)
@@ -1,11 +1,11 @@
 /*
    Unix SMB/CIFS implementation.
 
-   Copyright (C) Stefan Metzmacher     2006
+   Copyright (C) Stefan Metzmacher <metze@samba.org> 2006
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -14,8 +14,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 #include "librpc/gen_ndr/ndr_security.h"
 #include "librpc/gen_ndr/ndr_drsuapi.h"
 #include "auth/gensec/gensec.h"
+#include "param/param.h"
+
+/*****************************************************************************
+ * Windows 2003 (w2k3) does the following steps when changing the server role
+ * from domain member to domain controller
+ *
+ * We mostly do the same.
+ *****************************************************************************/
+
+/*
+ * lookup DC:
+ * - using nbt name<1C> request and a samlogon mailslot request
+ * or
+ * - using a DNS SRV _ldap._tcp.dc._msdcs. request and a CLDAP netlogon request
+ *
+ * see: becomeDC_recv_cldap() and becomeDC_send_cldap()
+ */
+
+/*
+ * Open 1st LDAP connection to the DC using admin credentials
+ *
+ * see: becomeDC_connect_ldap1() and becomeDC_ldap_connect()
+ */
+
+/*
+ * LDAP search 1st LDAP connection:
+ *
+ * see: becomeDC_ldap1_rootdse()
+ *
+ * Request:
+ *     basedn: ""
+ *     scope:  base
+ *     filter: (objectClass=*)
+ *     attrs:  *
+ * Result:
+ *      ""
+ *             currentTime:            20061202155100.0Z
+ *             subschemaSubentry:      CN=Aggregate,CN=Schema,CN=Configuration,<domain_partition>
+ *             dsServiceName:          CN=<netbios_name>,CN=Servers,CN=<site_name>,CN=Sites,CN=Configuration,<domain_partition>
+ *             namingContexts:         <domain_partition>
+ *                                     CN=Configuration,<domain_partition>
+ *                                     CN=Schema,CN=Configuration,<domain_partition>
+ *             defaultNamingContext:   <domain_partition>
+ *             schemaNamingContext:    CN=Schema,CN=Configuration,<domain_partition>
+ *             configurationNamingContext:CN=Configuration,<domain_partition>
+ *             rootDomainNamingContext:<domain_partition>
+ *             supportedControl:       ...
+ *             supportedLDAPVersion:   3
+ *                                     2
+ *             supportedLDAPPolicies:  ...
+ *             highestCommitedUSN:     ...
+ *             supportedSASLMechanisms:GSSAPI
+ *                                     GSS-SPNEGO
+ *                                     EXTERNAL
+ *                                     DIGEST-MD5
+ *             dnsHostName:            <dns_host_name>
+ *             ldapServiceName:        <domain_dns_name>:<netbios_name>$@<REALM>
+ *             serverName:             CN=Servers,CN=<site_name>,CN=Sites,CN=Configuration,<domain_partition>
+ *             supportedCapabilities:  ...
+ *             isSyncronized:          TRUE
+ *             isGlobalCatalogReady:   TRUE
+ *             domainFunctionality:    0
+ *             forestFunctionality:    0
+ *             domainControllerFunctionality: 2
+ */
+
+/*
+ * LDAP search 1st LDAP connection:
+ *
+ * see: becomeDC_ldap1_crossref_behavior_version()
+ *
+ * Request:
+ *     basedn: CN=Configuration,<domain_partition>
+ *     scope:  one
+ *     filter: (cn=Partitions)
+ *     attrs:  msDS-Behavior-Version
+ * Result:
+ *      CN=Partitions,CN=Configuration,<domain_partition>
+ *             msDS-Behavior-Version:  0
+ */
+
+/*
+ * LDAP search 1st LDAP connection:
+ *
+ * NOTE: this seems to be a bug! as the messageID of the LDAP message is corrupted!
+ *
+ * not implemented here
+ * 
+ * Request:
+ *     basedn: CN=Schema,CN=Configuration,<domain_partition>
+ *     scope:  one
+ *     filter: (cn=Partitions)
+ *     attrs:  msDS-Behavior-Version
+ * Result:
+ *     <none>
+ *
+ */
+
+/*
+ * LDAP search 1st LDAP connection:
+ *
+ * see: becomeDC_ldap1_domain_behavior_version()
+ * 
+ * Request:
+ *     basedn: <domain_partition>
+ *     scope:  base
+ *     filter: (objectClass=*)
+ *     attrs:  msDS-Behavior-Version
+ * Result:
+ *     <domain_partition>
+ *             msDS-Behavior-Version:  0
+ */
+
+/*
+ * LDAP search 1st LDAP connection:
+ * 
+ * see: becomeDC_ldap1_schema_object_version()
+ *
+ * Request:
+ *     basedn: CN=Schema,CN=Configuration,<domain_partition>
+ *     scope:  base
+ *     filter: (objectClass=*)
+ *     attrs:  objectVersion
+ * Result:
+ *     CN=Schema,CN=Configuration,<domain_partition>
+ *             objectVersion:  30
+ */
+
+/*
+ * LDAP search 1st LDAP connection:
+ * 
+ * not implemented, because the information is already there
+ *
+ * Request:
+ *     basedn: ""
+ *     scope:  base
+ *     filter: (objectClass=*)
+ *     attrs:  defaultNamingContext
+ *             dnsHostName
+ * Result:
+ *     ""
+ *             defaultNamingContext:   <domain_partition>
+ *             dnsHostName:            <dns_host_name>
+ */
+
+/*
+ * LDAP search 1st LDAP connection:
+ *
+ * see: becomeDC_ldap1_infrastructure_fsmo()
+ * 
+ * Request:
+ *     basedn: <WKGUID=2fbac1870ade11d297c400c04fd8d5cd,domain_partition>
+ *     scope:  base
+ *     filter: (objectClass=*)
+ *     attrs:  1.1
+ * Result:
+ *     CN=Infrastructure,<domain_partition>
+ */
+
+/*
+ * LDAP search 1st LDAP connection:
+ *
+ * see: becomeDC_ldap1_w2k3_update_revision()
+ *
+ * Request:
+ *     basedn: CN=Windows2003Update,CN=DomainUpdates,CN=System,<domain_partition>
+ *     scope:  base
+ *     filter: (objectClass=*)
+ *     attrs:  revision
+ * Result:
+ *      CN=Windows2003Update,CN=DomainUpdates,CN=System,<domain_partition>
+ *             revision:       8
+ */
+
+/*
+ * LDAP search 1st LDAP connection:
+ *
+ * see: becomeDC_ldap1_infrastructure_fsmo()
+ *
+ * Request:
+ *     basedn: CN=Infrastructure,<domain_partition>
+ *     scope:  base
+ *     filter: (objectClass=*)
+ *     attrs:  fSMORoleOwner
+ * Result:
+ *      CN=Infrastructure,<domain_partition>
+ *             fSMORoleOwner:  CN=NTDS Settings,<infrastructure_fsmo_server_object>
+ */
+
+/*
+ * LDAP search 1st LDAP connection:
+ *
+ * see: becomeDC_ldap1_infrastructure_fsmo()
+ *
+ * Request:
+ *     basedn: <infrastructure_fsmo_server_object>
+ *     scope:  base
+ *     filter: (objectClass=*)
+ *     attrs:  dnsHostName
+ * Result:
+ *      <infrastructure_fsmo_server_object>
+ *             dnsHostName:    <dns_host_name>
+ */
+
+/*
+ * LDAP search 1st LDAP connection:
+ *
+ * see: becomeDC_ldap1_infrastructure_fsmo()
+ *
+ * Request:
+ *     basedn: CN=NTDS Settings,<infrastructure_fsmo_server_object>
+ *     scope:  base
+ *     filter: (objectClass=*)
+ *     attrs:  objectGUID
+ * Result:
+ *      CN=NTDS Settings,<infrastructure_fsmo_server_object>
+ *             objectGUID:     <object_guid>
+ */
+
+/*
+ * LDAP search 1st LDAP connection:
+ * 
+ * see: becomeDC_ldap1_rid_manager_fsmo()
+ *
+ * Request:
+ *     basedn: <domain_partition>
+ *     scope:  base
+ *     filter: (objectClass=*)
+ *     attrs:  rIDManagerReference
+ * Result:
+ *     <domain_partition>
+ *             rIDManagerReference:    CN=RID Manager$,CN=System,<domain_partition>
+ */
+
+/*
+ * LDAP search 1st LDAP connection:
+ * 
+ * see: becomeDC_ldap1_rid_manager_fsmo()
+ *
+ * Request:
+ *     basedn: CN=RID Manager$,CN=System,<domain_partition>
+ *     scope:  base
+ *     filter: (objectClass=*)
+ *     attrs:  fSMORoleOwner
+ * Result:
+ *      CN=Infrastructure,<domain_partition>
+ *             fSMORoleOwner:  CN=NTDS Settings,<rid_manager_fsmo_server_object>
+ */
+
+/*
+ * LDAP search 1st LDAP connection:
+ *
+ * see: becomeDC_ldap1_rid_manager_fsmo()
+ *
+ * Request:
+ *     basedn: <rid_manager_fsmo_server_object>
+ *     scope:  base
+ *     filter: (objectClass=*)
+ *     attrs:  dnsHostName
+ * Result:
+ *      <rid_manager_fsmo_server_object>
+ *             dnsHostName:    <dns_host_name>
+ */
+
+/*
+ * LDAP search 1st LDAP connection:
+ *
+ * see: becomeDC_ldap1_rid_manager_fsmo()
+ *
+ * Request:
+ *     basedn: CN=NTDS Settings,<rid_manager_fsmo_server_object>
+ *     scope:  base
+ *     filter: (objectClass=*)
+ *     attrs:  msDs-ReplicationEpoch
+ * Result:
+ *      CN=NTDS Settings,<rid_manager_fsmo_server_object>
+ */
+
+/*
+ * LDAP search 1st LDAP connection:
+ *
+ * see: becomeDC_ldap1_site_object()
+ *
+ * Request:
+ *     basedn: CN=<new_dc_site_name>,CN=Sites,CN=Configuration,<domain_partition>
+ *     scope:  base
+ *     filter: (objectClass=*)
+ *     attrs:
+ * Result:
+ *      CN=<new_dc_site_name>,CN=Sites,CN=Configuration,<domain_partition>
+ *             objectClass:    top
+ *                             site
+ *             cn:             <new_dc_site_name>
+ *             distinguishedName:CN=<new_dc_site_name>,CN=Sites,CN=Configuration,<domain_partition>
+ *             instanceType:   4
+ *             whenCreated:    ...
+ *             whenChanged:    ...
+ *             uSNCreated:     ...
+ *             uSNChanged:     ...
+ *             showInAdvancedViewOnly: TRUE
+ *             name:           <new_dc_site_name>
+ *             objectGUID:     <object_guid>
+ *             systemFlags:    1107296256 <0x42000000>
+ *             objectCategory: CN=Site,C=Schema,CN=Configuration,<domain_partition>
+ */
+
+/***************************************************************
+ * Add this stage we call the check_options() callback function
+ * of the caller, to see if he wants us to continue
+ *
+ * see: becomeDC_check_options()
+ ***************************************************************/
+
+/*
+ * LDAP search 1st LDAP connection:
+ *
+ * see: becomeDC_ldap1_computer_object()
+ *
+ * Request:
+ *     basedn: <domain_partition>
+ *     scope:  sub
+ *     filter: (&(|(objectClass=user)(objectClass=computer))(sAMAccountName=<new_dc_account_name>))
+ *     attrs:  distinguishedName
+ *             userAccountControl
+ * Result:
+ *      CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
+ *             distinguishedName:      CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
+ *             userAccoountControl:    4096 <0x1000>
+ */
+
+/*
+ * LDAP search 1st LDAP connection:
+ *
+ * see: becomeDC_ldap1_server_object_1()
+ *
+ * Request:
+ *     basedn: CN=<new_dc_netbios_name>,CN=Servers,CN=<new_dc_site_name>,CN=Sites,CN=Configuration,<domain_partition>
+ *     scope:  base
+ *     filter: (objectClass=*)
+ *     attrs:
+ * Result:
+ *      <noSuchObject>
+ *     <matchedDN:CN=Servers,CN=<new_dc_site_name>,CN=Sites,CN=Configuration,<domain_partition>>
+ */
+
+/*
+ * LDAP search 1st LDAP connection:
+ *
+ * see: becomeDC_ldap1_server_object_2()
+ * 
+ * Request:
+ *     basedn: CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
+ *     scope:  base
+ *     filter: (objectClass=*)
+ *     attrs:  serverReferenceBL
+ *     typesOnly: TRUE!!!
+ * Result:
+ *      CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
+ */
+
+/*
+ * LDAP add 1st LDAP connection:
+ * 
+ * see: becomeDC_ldap1_server_object_add()
+ *
+ * Request:
+ *     CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
+ *     objectClass:    server
+ *     systemFlags:    50000000 <0x2FAF080>
+ *     serverReference:CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
+ * Result:
+ *      <success>
+ */
+
+/*
+ * LDAP search 1st LDAP connection:
+ *
+ * not implemented, maybe we can add that later
+ *
+ * Request:
+ *     basedn: CN=NTDS Settings,CN=<new_dc_netbios_name>,CN=Servers,CN=<new_dc_site_name>,CN=Sites,CN=Configuration,<domain_partition>
+ *     scope:  base
+ *     filter: (objectClass=*)
+ *     attrs:
+ * Result:
+ *      <noSuchObject>
+ *     <matchedDN:CN=<new_dc_netbios_name>,CN=Servers,CN=<new_dc_site_name>,CN=Sites,CN=Configuration,<domain_partition>>
+ */
+
+/*
+ * LDAP search 1st LDAP connection:
+ *
+ * not implemented because it gives no new information
+ * 
+ * Request:
+ *     basedn: CN=Partitions,CN=Configuration,<domain_partition>
+ *     scope:  sub
+ *     filter: (nCName=<domain_partition>)
+ *     attrs:  nCName
+ *             dnsRoot
+ *     controls: LDAP_SERVER_EXTENDED_DN_OID:critical=false
+ * Result:
+ *      <GUID=<hex_guid>>;CN=<domain_netbios_name>,CN=Partitions,<domain_partition>>
+ *             nCName:         <GUID=<hex_guid>>;<SID=<hex_sid>>;<domain_partition>>
+ *             dnsRoot:        <domain_dns_name>
+ */
+
+/*
+ * LDAP modify 1st LDAP connection:
+ *
+ * see: becomeDC_ldap1_server_object_modify()
+ * 
+ * Request (add):
+ *     CN=<new_dc_netbios_name>,CN=Servers,CN=<new_dc_site_name>,CN=Sites,CN=Configuration,<domain_partition>>
+ *     serverReference:CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
+ * Result:
+ *     <attributeOrValueExist>
+ */
+
+/*
+ * LDAP modify 1st LDAP connection:
+ *
+ * see: becomeDC_ldap1_server_object_modify()
+ *
+ * Request (replace):
+ *     CN=<new_dc_netbios_name>,CN=Servers,CN=<new_dc_site_name>,CN=Sites,CN=Configuration,<domain_partition>>
+ *     serverReference:CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
+ * Result:
+ *     <success>
+ */
+
+/*
+ * Open 1st DRSUAPI connection to the DC using admin credentials
+ * DsBind with DRSUAPI_DS_BIND_GUID_W2K3 ("6afab99c-6e26-464a-975f-f58f105218bc")
+ * (w2k3 does 2 DsBind() calls here..., where is first is unused and contains garbage at the end)
+ *
+ * see: becomeDC_drsuapi_connect_send(), becomeDC_drsuapi1_connect_recv(),
+ *      becomeDC_drsuapi_bind_send(), becomeDC_drsuapi_bind_recv() and becomeDC_drsuapi1_bind_recv()
+ */
+
+/*
+ * DsAddEntry to create the CN=NTDS Settings,CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name, ...
+ * on the 1st DRSUAPI connection
+ *
+ * see: becomeDC_drsuapi1_add_entry_send() and becomeDC_drsuapi1_add_entry_recv()
+ */
+
+/***************************************************************
+ * Add this stage we call the prepare_db() callback function
+ * of the caller, to see if he wants us to continue
+ *
+ * see: becomeDC_prepare_db()
+ ***************************************************************/
+
+/*
+ * Open 2nd and 3rd DRSUAPI connection to the DC using admin credentials
+ * - a DsBind with DRSUAPI_DS_BIND_GUID_W2K3 ("6afab99c-6e26-464a-975f-f58f105218bc")
+ *   on the 2nd connection
+ *
+ * see: becomeDC_drsuapi_connect_send(), becomeDC_drsuapi2_connect_recv(),
+ *      becomeDC_drsuapi_bind_send(), becomeDC_drsuapi_bind_recv(), becomeDC_drsuapi2_bind_recv()
+ *     and becomeDC_drsuapi3_connect_recv()
+ */
+
+/*
+ * replicate CN=Schema,CN=Configuration,...
+ * on the 3rd DRSUAPI connection and the bind_handle from the 2nd connection
+ *
+ * see: becomeDC_drsuapi_pull_partition_send(), becomeDC_drsuapi_pull_partition_recv(),
+ *     becomeDC_drsuapi3_pull_schema_send() and becomeDC_drsuapi3_pull_schema_recv()
+ *
+ ***************************************************************
+ * Add this stage we call the schema_chunk() callback function
+ * for each replication message
+ ***************************************************************/
+
+/*
+ * replicate CN=Configuration,...
+ * on the 3rd DRSUAPI connection and the bind_handle from the 2nd connection
+ *
+ * see: becomeDC_drsuapi_pull_partition_send(), becomeDC_drsuapi_pull_partition_recv(),
+ *     becomeDC_drsuapi3_pull_config_send() and becomeDC_drsuapi3_pull_config_recv()
+ *
+ ***************************************************************
+ * Add this stage we call the config_chunk() callback function
+ * for each replication message
+ ***************************************************************/
+
+/*
+ * LDAP unbind on the 1st LDAP connection
+ *
+ * not implemented, because it's not needed...
+ */
+
+/*
+ * Open 2nd LDAP connection to the DC using admin credentials
+ *
+ * see: becomeDC_connect_ldap2() and becomeDC_ldap_connect()
+ */
+
+/*
+ * LDAP search 2nd LDAP connection:
+ * 
+ * not implemented because it gives no new information
+ * same as becomeDC_ldap1_computer_object()
+ *
+ * Request:
+ *     basedn: <domain_partition>
+ *     scope:  sub
+ *     filter: (&(|(objectClass=user)(objectClass=computer))(sAMAccountName=<new_dc_account_name>))
+ *     attrs:  distinguishedName
+ *             userAccountControl
+ * Result:
+ *      CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
+ *             distinguishedName:      CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
+ *             userAccoountControl:    4096 <0x00001000>
+ */
+
+/*
+ * LDAP search 2nd LDAP connection:
+ * 
+ * not implemented because it gives no new information
+ * same as becomeDC_ldap1_computer_object()
+ *
+ * Request:
+ *     basedn: CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
+ *     scope:  base
+ *     filter: (objectClass=*)
+ *     attrs:  userAccountControl
+ * Result:
+ *      CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
+ *             userAccoountControl:    4096 <0x00001000>
+ */
+
+/*
+ * LDAP modify 2nd LDAP connection:
+ *
+ * see: becomeDC_ldap2_modify_computer()
+ *
+ * Request (replace):
+ *     CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
+ *     userAccoountControl:    532480 <0x82000>
+ * Result:
+ *     <success>
+ */
+
+/*
+ * LDAP search 2nd LDAP connection:
+ *
+ * see: becomeDC_ldap2_move_computer()
+ * 
+ * Request:
+ *     basedn: <WKGUID=2fbac1870ade11d297c400c04fd8d5cd,<domain_partition>>
+ *     scope:  base
+ *     filter: (objectClass=*)
+ *     attrs:  1.1
+ * Result:
+ *     CN=Domain Controllers,<domain_partition>
+ */
+
+/*
+ * LDAP search 2nd LDAP connection:
+ *
+ * not implemented because it gives no new information
+ * 
+ * Request:
+ *     basedn: CN=Domain Controllers,<domain_partition>
+ *     scope:  base
+ *     filter: (objectClass=*)
+ *     attrs:  distinguishedName
+ * Result:
+ *     CN=Domain Controller,<domain_partition>
+ *             distinguishedName:      CN=Domain Controllers,<domain_partition>
+ */
+
+/*
+ * LDAP modifyRDN 2nd LDAP connection:
+ *
+ * see: becomeDC_ldap2_move_computer()
+ * 
+ * Request:
+ *      entry:         CN=<new_dc_netbios_name>,CN=Computers,<domain_partition>
+ *     newrdn:         CN=<new_dc_netbios_name>
+ *     deleteoldrdn:   TRUE
+ *     newparent:      CN=Domain Controllers,<domain_partition>
+ * Result:
+ *     <success>
+ */
+
+/*
+ * LDAP unbind on the 2nd LDAP connection
+ *
+ * not implemented, because it's not needed...
+ */
+
+/*
+ * replicate Domain Partition
+ * on the 3rd DRSUAPI connection and the bind_handle from the 2nd connection
+ *
+ * see: becomeDC_drsuapi_pull_partition_send(), becomeDC_drsuapi_pull_partition_recv(),
+ *     becomeDC_drsuapi3_pull_domain_send() and becomeDC_drsuapi3_pull_domain_recv()
+ *
+ ***************************************************************
+ * Add this stage we call the domain_chunk() callback function
+ * for each replication message
+ ***************************************************************/
+
+/* call DsReplicaUpdateRefs() for all partitions like this:
+ *     req1: struct drsuapi_DsReplicaUpdateRefsRequest1
+ *
+ *                 naming_context: struct drsuapi_DsReplicaObjectIdentifier
+ *                     __ndr_size               : 0x000000ae (174)
+ *                     __ndr_size_sid           : 0x00000000 (0)
+ *                     guid                     : 00000000-0000-0000-0000-000000000000
+ *                     sid                      : S-0-0
+ *                     dn                       : 'CN=Schema,CN=Configuration,DC=w2k3,DC=vmnet1,DC=vm,DC=base'
+ *
+ *                 dest_dsa_dns_name        : '4a0df188-a0b8-47ea-bbe5-e614723f16dd._msdcs.w2k3.vmnet1.vm.base'
+ *           dest_dsa_guid            : 4a0df188-a0b8-47ea-bbe5-e614723f16dd
+ *           options                  : 0x0000001c (28)
+ *                 0: DRSUAPI_DS_REPLICA_UPDATE_ASYNCHRONOUS_OPERATION
+ *                 0: DRSUAPI_DS_REPLICA_UPDATE_WRITEABLE
+ *                 1: DRSUAPI_DS_REPLICA_UPDATE_ADD_REFERENCE
+ *                 1: DRSUAPI_DS_REPLICA_UPDATE_DELETE_REFERENCE
+ *                 1: DRSUAPI_DS_REPLICA_UPDATE_0x00000010
+ *
+ * 4a0df188-a0b8-47ea-bbe5-e614723f16dd is the objectGUID the DsAddEntry() returned for the
+ * CN=NTDS Settings,CN=<machine_name>,CN=Servers,CN=Default-First-Site-Name, ...
+ * on the 2nd!!! DRSUAPI connection
+ *
+ * see:        becomeDC_drsuapi_update_refs_send(), becomeDC_drsuapi2_update_refs_schema_recv(),
+ *     becomeDC_drsuapi2_update_refs_config_recv() and becomeDC_drsuapi2_update_refs_domain_recv()
+ */
+
+/*
+ * Windows does opens the 4th and 5th DRSUAPI connection...
+ * and does a DsBind() with the objectGUID from DsAddEntry() as bind_guid
+ * on the 4th connection
+ *
+ * and then 2 full replications of the domain partition on the 5th connection
+ * with the bind_handle from the 4th connection
+ *
+ * not implemented because it gives no new information
+ */
 
 struct libnet_BecomeDC_state {
        struct composite_context *creq;
@@ -87,6 +730,31 @@ struct libnet_BecomeDC_state {
        struct libnet_BecomeDC_Callbacks callbacks;
 };
 
+static void becomeDC_recv_cldap(struct cldap_request *req);
+
+static void becomeDC_send_cldap(struct libnet_BecomeDC_state *s)
+{
+       struct composite_context *c = s->creq;
+       struct cldap_request *req;
+
+       s->cldap.io.in.dest_address     = s->source_dsa.address;
+       s->cldap.io.in.realm            = s->domain.dns_name;
+       s->cldap.io.in.host             = s->dest_dsa.netbios_name;
+       s->cldap.io.in.user             = NULL;
+       s->cldap.io.in.domain_guid      = NULL;
+       s->cldap.io.in.domain_sid       = NULL;
+       s->cldap.io.in.acct_control     = -1;
+       s->cldap.io.in.version          = 6;
+
+       s->cldap.sock = cldap_socket_init(s, s->libnet->event_ctx);
+       if (composite_nomem(s->cldap.sock, c)) return;
+
+       req = cldap_netlogon_send(s->cldap.sock, &s->cldap.io);
+       if (composite_nomem(req, c)) return;
+       req->async.fn           = becomeDC_recv_cldap;
+       req->async.private      = s;
+}
+
 static void becomeDC_connect_ldap1(struct libnet_BecomeDC_state *s);
 
 static void becomeDC_recv_cldap(struct cldap_request *req)
@@ -115,29 +783,6 @@ static void becomeDC_recv_cldap(struct cldap_request *req)
        becomeDC_connect_ldap1(s);
 }
 
-static void becomeDC_send_cldap(struct libnet_BecomeDC_state *s)
-{
-       struct composite_context *c = s->creq;
-       struct cldap_request *req;
-
-       s->cldap.io.in.dest_address     = s->source_dsa.address;
-       s->cldap.io.in.realm            = s->domain.dns_name;
-       s->cldap.io.in.host             = s->dest_dsa.netbios_name;
-       s->cldap.io.in.user             = NULL;
-       s->cldap.io.in.domain_guid      = NULL;
-       s->cldap.io.in.domain_sid       = NULL;
-       s->cldap.io.in.acct_control     = -1;
-       s->cldap.io.in.version          = 6;
-
-       s->cldap.sock = cldap_socket_init(s, s->libnet->event_ctx);
-       if (composite_nomem(s->cldap.sock, c)) return;
-
-       req = cldap_netlogon_send(s->cldap.sock, &s->cldap.io);
-       if (composite_nomem(req, c)) return;
-       req->async.fn           = becomeDC_recv_cldap;
-       req->async.private      = s;
-}
-
 static NTSTATUS becomeDC_ldap_connect(struct libnet_BecomeDC_state *s, struct becomeDC_ldap *ldap)
 {
        char *url;
@@ -145,7 +790,7 @@ static NTSTATUS becomeDC_ldap_connect(struct libnet_BecomeDC_state *s, struct be
        url = talloc_asprintf(s, "ldap://%s/", s->source_dsa.dns_name);
        NT_STATUS_HAVE_NO_MEMORY(url);
 
-       ldap->ldb = ldb_wrap_connect(s, url,
+       ldap->ldb = ldb_wrap_connect(s, global_loadparm, url,
                                     NULL,
                                     s->libnet->cred,
                                     0, NULL);
@@ -866,7 +1511,7 @@ static void becomeDC_drsuapi_connect_send(struct libnet_BecomeDC_state *s,
        drsuapi->s = s;
 
        if (!drsuapi->binding) {
-               if (lp_parm_bool(-1, "become_dc", "print", False)) {
+               if (lp_parm_bool(global_loadparm, NULL, "become_dc", "print", false)) {
                        binding_str = talloc_asprintf(s, "ncacn_ip_tcp:%s[krb5,print,seal]", s->source_dsa.dns_name);
                        if (composite_nomem(binding_str, c)) return;
                } else {
@@ -878,7 +1523,7 @@ static void becomeDC_drsuapi_connect_send(struct libnet_BecomeDC_state *s,
                if (!composite_is_ok(c)) return;
        }
 
-       creq = dcerpc_pipe_connect_b_send(s, drsuapi->binding, &dcerpc_table_drsuapi,
+       creq = dcerpc_pipe_connect_b_send(s, drsuapi->binding, &ndr_table_drsuapi,
                                          s->libnet->cred, s->libnet->event_ctx);
        composite_continue(c, creq, recv_fn, s);
 }
@@ -1002,7 +1647,7 @@ static void becomeDC_drsuapi1_add_entry_send(struct libnet_BecomeDC_state *s);
 
 static void becomeDC_drsuapi1_bind_recv(struct rpc_request *req)
 {
-       struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
+       struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
                                          struct libnet_BecomeDC_state);
        struct composite_context *c = s->creq;
        WERROR status;
@@ -1189,7 +1834,7 @@ static void becomeDC_drsuapi1_add_entry_send(struct libnet_BecomeDC_state *s)
                v[0].sid                = s->zero_sid;
                v[0].dn                 = talloc_asprintf(vd, "CN=NTDS-DSA,%s",
                                                          s->forest.schema_dn_str);
-               if (composite_nomem(v->dn, c)) return;
+               if (composite_nomem(v[0].dn, c)) return;
 
                c->status = ndr_push_struct_blob(&vd[0], vd, &v[0],
                                                 (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
@@ -1482,11 +2127,12 @@ static NTSTATUS becomeDC_prepare_db(struct libnet_BecomeDC_state *s);
 
 static void becomeDC_drsuapi1_add_entry_recv(struct rpc_request *req)
 {
-       struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
+       struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
                                          struct libnet_BecomeDC_state);
        struct composite_context *c = s->creq;
        struct drsuapi_DsAddEntry *r = talloc_get_type(req->ndr.struct_ptr,
                                       struct drsuapi_DsAddEntry);
+       char *binding_str;
        bool print = false;
 
        if (req->p->conn->flags & DCERPC_DEBUG_PRINT_OUT) {
@@ -1565,6 +2211,17 @@ static void becomeDC_drsuapi1_add_entry_recv(struct rpc_request *req)
        c->status = becomeDC_prepare_db(s);
        if (!composite_is_ok(c)) return;
 
+       /* this avoids the epmapper lookup on the 2nd connection */
+       binding_str = dcerpc_binding_string(s, s->drsuapi1.binding);
+       if (composite_nomem(binding_str, c)) return;
+
+       c->status = dcerpc_parse_binding(s, binding_str, &s->drsuapi2.binding);
+       talloc_free(binding_str);
+       if (!composite_is_ok(c)) return;
+
+       /* w2k3 uses the same assoc_group_id as on the first connection, so we do */
+       s->drsuapi2.binding->assoc_group_id     = s->drsuapi1.pipe->assoc_group_id;
+
        becomeDC_drsuapi_connect_send(s, &s->drsuapi2, becomeDC_drsuapi2_connect_recv);
 }
 
@@ -1602,7 +2259,7 @@ static void becomeDC_drsuapi3_connect_recv(struct composite_context *req);
 
 static void becomeDC_drsuapi2_bind_recv(struct rpc_request *req)
 {
-       struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
+       struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
                                          struct libnet_BecomeDC_state);
        struct composite_context *c = s->creq;
        char *binding_str;
@@ -1627,14 +2284,19 @@ static void becomeDC_drsuapi2_bind_recv(struct rpc_request *req)
                return;
        }
 
-       /* this avoids the epmapper lookup on the 2nd connection */
-       binding_str = dcerpc_binding_string(s, s->drsuapi2.binding);
+       /* this avoids the epmapper lookup on the 3rd connection */
+       binding_str = dcerpc_binding_string(s, s->drsuapi1.binding);
        if (composite_nomem(binding_str, c)) return;
 
        c->status = dcerpc_parse_binding(s, binding_str, &s->drsuapi3.binding);
        talloc_free(binding_str);
        if (!composite_is_ok(c)) return;
 
+       /* w2k3 uses the same assoc_group_id as on the first connection, so we do */
+       s->drsuapi3.binding->assoc_group_id     = s->drsuapi1.pipe->assoc_group_id;
+       /* w2k3 uses the concurrent multiplex feature on the 3rd connection, so we do */
+       s->drsuapi3.binding->flags              |= DCERPC_CONCURRENT_MULTIPLEX;
+
        becomeDC_drsuapi_connect_send(s, &s->drsuapi3, becomeDC_drsuapi3_connect_recv);
 }
 
@@ -1711,11 +2373,13 @@ static void becomeDC_drsuapi_pull_partition_send(struct libnet_BecomeDC_state *s
         * are needed for it. Or the same KRB5 TGS is needed on both
         * connections.
         */
-       req = dcerpc_drsuapi_DsGetNCChanges_send(drsuapi_h->pipe, r, r);
+       req = dcerpc_drsuapi_DsGetNCChanges_send(drsuapi_p->pipe, r, r);
        composite_continue_rpc(c, req, recv_fn, s);
 }
 
 static WERROR becomeDC_drsuapi_pull_partition_recv(struct libnet_BecomeDC_state *s,
+                                                  struct becomeDC_drsuapi *drsuapi_h,
+                                                  struct becomeDC_drsuapi *drsuapi_p,
                                                   struct libnet_BecomeDC_Partition *partition,
                                                   struct drsuapi_DsGetNCChanges *r)
 {
@@ -1776,6 +2440,11 @@ static WERROR becomeDC_drsuapi_pull_partition_recv(struct libnet_BecomeDC_state
        s->_sc.ctr_level        = ctr_level;
        s->_sc.ctr1             = ctr1;
        s->_sc.ctr6             = ctr6;
+       /* 
+        * we need to use the drsuapi_p->gensec_skey here,
+        * when we use drsuapi_p->pipe in the for this request
+        */
+       s->_sc.gensec_skey      = &drsuapi_p->gensec_skey;
 
        nt_status = partition->store_chunk(s->callbacks.private_data, &s->_sc);
        if (!NT_STATUS_IS_OK(nt_status)) {
@@ -1812,7 +2481,7 @@ static void becomeDC_drsuapi3_pull_config_send(struct libnet_BecomeDC_state *s);
 
 static void becomeDC_drsuapi3_pull_schema_recv(struct rpc_request *req)
 {
-       struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
+       struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
                                          struct libnet_BecomeDC_state);
        struct composite_context *c = s->creq;
        struct drsuapi_DsGetNCChanges *r = talloc_get_type(req->ndr.struct_ptr,
@@ -1832,7 +2501,7 @@ static void becomeDC_drsuapi3_pull_schema_recv(struct rpc_request *req)
                NDR_PRINT_OUT_DEBUG(drsuapi_DsGetNCChanges, r);
        }
 
-       status = becomeDC_drsuapi_pull_partition_recv(s, &s->schema_part, r);
+       status = becomeDC_drsuapi_pull_partition_recv(s, &s->drsuapi2, &s->drsuapi3, &s->schema_part, r);
        if (!W_ERROR_IS_OK(status)) {
                composite_error(c, werror_to_ntstatus(status));
                return;
@@ -1874,7 +2543,7 @@ static void becomeDC_drsuapi3_pull_config_send(struct libnet_BecomeDC_state *s)
 
 static void becomeDC_drsuapi3_pull_config_recv(struct rpc_request *req)
 {
-       struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
+       struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
                                          struct libnet_BecomeDC_state);
        struct composite_context *c = s->creq;
        struct drsuapi_DsGetNCChanges *r = talloc_get_type(req->ndr.struct_ptr,
@@ -1894,7 +2563,7 @@ static void becomeDC_drsuapi3_pull_config_recv(struct rpc_request *req)
                NDR_PRINT_OUT_DEBUG(drsuapi_DsGetNCChanges, r);
        }
 
-       status = becomeDC_drsuapi_pull_partition_recv(s, &s->config_part, r);
+       status = becomeDC_drsuapi_pull_partition_recv(s, &s->drsuapi2, &s->drsuapi3, &s->config_part, r);
        if (!W_ERROR_IS_OK(status)) {
                composite_error(c, werror_to_ntstatus(status));
                return;
@@ -1942,7 +2611,7 @@ static void becomeDC_drsuapi2_update_refs_schema_recv(struct rpc_request *req);
 
 static void becomeDC_drsuapi3_pull_domain_recv(struct rpc_request *req)
 {
-       struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
+       struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
                                          struct libnet_BecomeDC_state);
        struct composite_context *c = s->creq;
        struct drsuapi_DsGetNCChanges *r = talloc_get_type(req->ndr.struct_ptr,
@@ -1961,7 +2630,7 @@ static void becomeDC_drsuapi3_pull_domain_recv(struct rpc_request *req)
                NDR_PRINT_OUT_DEBUG(drsuapi_DsGetNCChanges, r);
        }
 
-       status = becomeDC_drsuapi_pull_partition_recv(s, &s->domain_part, r);
+       status = becomeDC_drsuapi_pull_partition_recv(s, &s->drsuapi2, &s->drsuapi3, &s->domain_part, r);
        if (!W_ERROR_IS_OK(status)) {
                composite_error(c, werror_to_ntstatus(status));
                return;
@@ -2018,7 +2687,7 @@ static void becomeDC_drsuapi2_update_refs_config_recv(struct rpc_request *req);
 
 static void becomeDC_drsuapi2_update_refs_schema_recv(struct rpc_request *req)
 {
-       struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
+       struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
                                          struct libnet_BecomeDC_state);
        struct composite_context *c = s->creq;
        struct drsuapi_DsReplicaUpdateRefs *r = talloc_get_type(req->ndr.struct_ptr,
@@ -2051,7 +2720,7 @@ static void becomeDC_drsuapi2_update_refs_domain_recv(struct rpc_request *req);
 
 static void becomeDC_drsuapi2_update_refs_config_recv(struct rpc_request *req)
 {
-       struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
+       struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
                                          struct libnet_BecomeDC_state);
        struct composite_context *c = s->creq;
        struct drsuapi_DsReplicaUpdateRefs *r = talloc_get_type(req->ndr.struct_ptr,
@@ -2073,7 +2742,7 @@ static void becomeDC_drsuapi2_update_refs_config_recv(struct rpc_request *req)
 
 static void becomeDC_drsuapi2_update_refs_domain_recv(struct rpc_request *req)
 {
-       struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private,
+       struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
                                          struct libnet_BecomeDC_state);
        struct composite_context *c = s->creq;
        struct drsuapi_DsReplicaUpdateRefs *r = talloc_get_type(req->ndr.struct_ptr,
@@ -2241,7 +2910,7 @@ struct composite_context *libnet_BecomeDC_send(struct libnet_context *ctx, TALLO
        /* Destination DSA dns_name construction */
        tmp_name        = strlower_talloc(s, s->dest_dsa.netbios_name);
        if (composite_nomem(tmp_name, c)) return c;
-       tmp_name        = talloc_asprintf_append(tmp_name, ".%s",s->domain.dns_name);
+       tmp_name        = talloc_asprintf_append_buffer(tmp_name, ".%s",s->domain.dns_name);
        if (composite_nomem(tmp_name, c)) return c;
        s->dest_dsa.dns_name    = tmp_name;