LCOV - code coverage report
Current view: top level - source4/libnet - libnet_become_dc.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 1104 1444 76.5 %
Date: 2024-04-21 15:09:00 Functions: 48 48 100.0 %

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

Generated by: LCOV version 1.14