2006-12-02 15:46:13 +03:00
/*
Unix SMB / CIFS implementation .
2007-03-14 22:10:21 +03:00
Copyright ( C ) Stefan Metzmacher < metze @ samba . org > 2006
2006-12-02 15:46:13 +03:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2006-12-02 15:46:13 +03:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2006-12-02 15:46:13 +03:00
*/
# include "includes.h"
# include "libnet/libnet.h"
2006-12-02 16:00:20 +03:00
# include "libcli/composite/composite.h"
2006-12-03 22:22:51 +03:00
# include "libcli/cldap/cldap.h"
2011-02-10 06:12:51 +03:00
# include <ldb.h>
# include <ldb_errors.h>
2010-06-16 15:43:38 +04:00
# include "ldb_wrap.h"
2006-12-04 12:40:16 +03:00
# include "dsdb/samdb/samdb.h"
2009-06-12 16:27:19 +04:00
# include "../libds/common/flags.h"
2006-12-06 15:15:07 +03:00
# include "librpc/gen_ndr/ndr_drsuapi_c.h"
2006-12-07 13:04:35 +03:00
# include "libcli/security/security.h"
2007-01-02 16:54:37 +03:00
# include "librpc/gen_ndr/ndr_misc.h"
2006-12-30 13:51:04 +03:00
# include "librpc/gen_ndr/ndr_security.h"
2008-05-16 07:03:01 +04:00
# include "librpc/gen_ndr/ndr_nbt.h"
2007-01-02 22:29:32 +03:00
# include "librpc/gen_ndr/ndr_drsuapi.h"
2007-02-12 13:58:06 +03:00
# include "auth/gensec/gensec.h"
2007-09-08 16:42:09 +04:00
# include "param/param.h"
2010-02-25 14:47:38 +03:00
# include "lib/tsocket/tsocket.h"
2006-12-02 15:46:13 +03:00
2007-03-13 18:41:25 +03:00
/*****************************************************************************
* Windows 2003 ( w2k3 ) does the following steps when changing the server role
* from domain member to domain controller
*
* We mostly do the same .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* lookup DC :
* - using nbt name < 1 C > request and a samlogon mailslot request
* or
* - using a DNS SRV _ldap . _tcp . dc . _msdcs . request and a CLDAP netlogon request
*
* see : becomeDC_recv_cldap ( ) and becomeDC_send_cldap ( )
*/
/*
* Open 1 st LDAP connection to the DC using admin credentials
*
* see : becomeDC_connect_ldap1 ( ) and becomeDC_ldap_connect ( )
*/
/*
* LDAP search 1 st LDAP connection :
*
* see : becomeDC_ldap1_rootdse ( )
*
* Request :
* basedn : " "
* scope : base
* filter : ( objectClass = * )
* attrs : *
* Result :
* " "
* currentTime : 20061202155100.0 Z
* subschemaSubentry : CN = Aggregate , CN = Schema , CN = Configuration , < domain_partition >
* dsServiceName : CN = < netbios_name > , CN = Servers , CN = < site_name > , CN = Sites , CN = Configuration , < domain_partition >
* namingContexts : < domain_partition >
* CN = Configuration , < domain_partition >
* CN = Schema , CN = Configuration , < domain_partition >
* defaultNamingContext : < domain_partition >
* schemaNamingContext : CN = Schema , CN = Configuration , < domain_partition >
* configurationNamingContext : CN = Configuration , < domain_partition >
* rootDomainNamingContext : < domain_partition >
* supportedControl : . . .
* supportedLDAPVersion : 3
* 2
* supportedLDAPPolicies : . . .
2016-12-01 13:49:25 +03:00
* highestCommittedUSN : . . .
2007-03-13 18:41:25 +03:00
* supportedSASLMechanisms : GSSAPI
* GSS - SPNEGO
* EXTERNAL
* DIGEST - MD5
* dnsHostName : < dns_host_name >
* ldapServiceName : < domain_dns_name > : < netbios_name > $ @ < REALM >
* serverName : CN = Servers , CN = < site_name > , CN = Sites , CN = Configuration , < domain_partition >
* supportedCapabilities : . . .
2024-03-05 02:37:11 +03:00
* isSynchronized : TRUE
2007-03-13 18:41:25 +03:00
* isGlobalCatalogReady : TRUE
* domainFunctionality : 0
* forestFunctionality : 0
* domainControllerFunctionality : 2
*/
/*
* LDAP search 1 st LDAP connection :
*
* see : becomeDC_ldap1_crossref_behavior_version ( )
*
* Request :
* basedn : CN = Configuration , < domain_partition >
* scope : one
* filter : ( cn = Partitions )
* attrs : msDS - Behavior - Version
* Result :
* CN = Partitions , CN = Configuration , < domain_partition >
* msDS - Behavior - Version : 0
*/
/*
* LDAP search 1 st LDAP connection :
*
* NOTE : this seems to be a bug ! as the messageID of the LDAP message is corrupted !
*
* not implemented here
*
* Request :
* basedn : CN = Schema , CN = Configuration , < domain_partition >
* scope : one
* filter : ( cn = Partitions )
* attrs : msDS - Behavior - Version
* Result :
* < none >
*
*/
/*
* LDAP search 1 st LDAP connection :
*
* see : becomeDC_ldap1_domain_behavior_version ( )
*
* Request :
* basedn : < domain_partition >
* scope : base
* filter : ( objectClass = * )
* attrs : msDS - Behavior - Version
* Result :
* < domain_partition >
* msDS - Behavior - Version : 0
*/
/*
* LDAP search 1 st LDAP connection :
*
* see : becomeDC_ldap1_schema_object_version ( )
*
* Request :
* basedn : CN = Schema , CN = Configuration , < domain_partition >
* scope : base
* filter : ( objectClass = * )
* attrs : objectVersion
* Result :
* CN = Schema , CN = Configuration , < domain_partition >
* objectVersion : 30
*/
/*
* LDAP search 1 st LDAP connection :
*
* not implemented , because the information is already there
*
* Request :
* basedn : " "
* scope : base
* filter : ( objectClass = * )
* attrs : defaultNamingContext
* dnsHostName
* Result :
* " "
* defaultNamingContext : < domain_partition >
* dnsHostName : < dns_host_name >
*/
/*
* LDAP search 1 st LDAP connection :
*
* see : becomeDC_ldap1_infrastructure_fsmo ( )
*
* Request :
* basedn : < WKGUID = 2f bac1870ade11d297c400c04fd8d5cd , domain_partition >
* scope : base
* filter : ( objectClass = * )
* attrs : 1.1
* Result :
* CN = Infrastructure , < domain_partition >
*/
/*
* LDAP search 1 st LDAP connection :
*
* see : becomeDC_ldap1_w2k3_update_revision ( )
*
* Request :
* basedn : CN = Windows2003Update , CN = DomainUpdates , CN = System , < domain_partition >
* scope : base
* filter : ( objectClass = * )
* attrs : revision
* Result :
* CN = Windows2003Update , CN = DomainUpdates , CN = System , < domain_partition >
* revision : 8
*/
/*
* LDAP search 1 st LDAP connection :
*
* see : becomeDC_ldap1_infrastructure_fsmo ( )
*
* Request :
* basedn : CN = Infrastructure , < domain_partition >
* scope : base
* filter : ( objectClass = * )
* attrs : fSMORoleOwner
* Result :
* CN = Infrastructure , < domain_partition >
* fSMORoleOwner : CN = NTDS Settings , < infrastructure_fsmo_server_object >
*/
/*
* LDAP search 1 st LDAP connection :
*
* see : becomeDC_ldap1_infrastructure_fsmo ( )
*
* Request :
* basedn : < infrastructure_fsmo_server_object >
* scope : base
* filter : ( objectClass = * )
* attrs : dnsHostName
* Result :
* < infrastructure_fsmo_server_object >
* dnsHostName : < dns_host_name >
*/
/*
* LDAP search 1 st LDAP connection :
*
* see : becomeDC_ldap1_infrastructure_fsmo ( )
*
* Request :
* basedn : CN = NTDS Settings , < infrastructure_fsmo_server_object >
* scope : base
* filter : ( objectClass = * )
* attrs : objectGUID
* Result :
* CN = NTDS Settings , < infrastructure_fsmo_server_object >
* objectGUID : < object_guid >
*/
/*
* LDAP search 1 st LDAP connection :
*
* see : becomeDC_ldap1_rid_manager_fsmo ( )
*
* Request :
* basedn : < domain_partition >
* scope : base
* filter : ( objectClass = * )
* attrs : rIDManagerReference
* Result :
* < domain_partition >
* rIDManagerReference : CN = RID Manager $ , CN = System , < domain_partition >
*/
/*
* LDAP search 1 st LDAP connection :
*
* see : becomeDC_ldap1_rid_manager_fsmo ( )
*
* Request :
* basedn : CN = RID Manager $ , CN = System , < domain_partition >
* scope : base
* filter : ( objectClass = * )
* attrs : fSMORoleOwner
* Result :
* CN = Infrastructure , < domain_partition >
* fSMORoleOwner : CN = NTDS Settings , < rid_manager_fsmo_server_object >
*/
/*
* LDAP search 1 st LDAP connection :
*
* see : becomeDC_ldap1_rid_manager_fsmo ( )
*
* Request :
* basedn : < rid_manager_fsmo_server_object >
* scope : base
* filter : ( objectClass = * )
* attrs : dnsHostName
* Result :
* < rid_manager_fsmo_server_object >
* dnsHostName : < dns_host_name >
*/
/*
* LDAP search 1 st LDAP connection :
*
* see : becomeDC_ldap1_rid_manager_fsmo ( )
*
* Request :
* basedn : CN = NTDS Settings , < rid_manager_fsmo_server_object >
* scope : base
* filter : ( objectClass = * )
* attrs : msDs - ReplicationEpoch
* Result :
* CN = NTDS Settings , < rid_manager_fsmo_server_object >
*/
/*
* LDAP search 1 st LDAP connection :
*
* see : becomeDC_ldap1_site_object ( )
*
* Request :
* basedn : CN = < new_dc_site_name > , CN = Sites , CN = Configuration , < domain_partition >
* scope : base
* filter : ( objectClass = * )
* attrs :
* Result :
* CN = < new_dc_site_name > , CN = Sites , CN = Configuration , < domain_partition >
* objectClass : top
* site
* cn : < new_dc_site_name >
* distinguishedName : CN = < new_dc_site_name > , CN = Sites , CN = Configuration , < domain_partition >
* instanceType : 4
* whenCreated : . . .
* whenChanged : . . .
* uSNCreated : . . .
* uSNChanged : . . .
* showInAdvancedViewOnly : TRUE
* name : < new_dc_site_name >
* objectGUID : < object_guid >
* systemFlags : 1107296256 < 0x42000000 >
2009-11-24 21:17:08 +03:00
* objectCategory : CN = Site , CN = Schema , CN = Configuration , < domain_partition >
2007-03-13 18:41:25 +03:00
*/
/***************************************************************
* Add this stage we call the check_options ( ) callback function
* of the caller , to see if he wants us to continue
*
* see : becomeDC_check_options ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* LDAP search 1 st LDAP connection :
*
* see : becomeDC_ldap1_computer_object ( )
*
* Request :
* basedn : < domain_partition >
* scope : sub
* filter : ( & ( | ( objectClass = user ) ( objectClass = computer ) ) ( sAMAccountName = < new_dc_account_name > ) )
* attrs : distinguishedName
* userAccountControl
* Result :
* CN = < new_dc_netbios_name > , CN = Computers , < domain_partition >
* distinguishedName : CN = < new_dc_netbios_name > , CN = Computers , < domain_partition >
2024-03-05 02:37:11 +03:00
* userAccountControl : 4096 < 0x1000 >
2007-03-13 18:41:25 +03:00
*/
/*
* LDAP search 1 st LDAP connection :
*
* see : becomeDC_ldap1_server_object_1 ( )
*
* Request :
* basedn : CN = < new_dc_netbios_name > , CN = Servers , CN = < new_dc_site_name > , CN = Sites , CN = Configuration , < domain_partition >
* scope : base
* filter : ( objectClass = * )
* attrs :
* Result :
* < noSuchObject >
* < matchedDN : CN = Servers , CN = < new_dc_site_name > , CN = Sites , CN = Configuration , < domain_partition > >
*/
/*
* LDAP search 1 st LDAP connection :
*
* see : becomeDC_ldap1_server_object_2 ( )
*
* Request :
* basedn : CN = < new_dc_netbios_name > , CN = Computers , < domain_partition >
* scope : base
* filter : ( objectClass = * )
* attrs : serverReferenceBL
* typesOnly : TRUE ! ! !
* Result :
* CN = < new_dc_netbios_name > , CN = Computers , < domain_partition >
*/
/*
* LDAP add 1 st LDAP connection :
*
* see : becomeDC_ldap1_server_object_add ( )
*
* Request :
* CN = < new_dc_netbios_name > , CN = Computers , < domain_partition >
* objectClass : server
* systemFlags : 50000000 < 0x2FAF080 >
* serverReference : CN = < new_dc_netbios_name > , CN = Computers , < domain_partition >
* Result :
* < success >
*/
/*
* LDAP search 1 st LDAP connection :
*
* not implemented , maybe we can add that later
*
* Request :
* basedn : CN = NTDS Settings , CN = < new_dc_netbios_name > , CN = Servers , CN = < new_dc_site_name > , CN = Sites , CN = Configuration , < domain_partition >
* scope : base
* filter : ( objectClass = * )
* attrs :
* Result :
* < noSuchObject >
* < matchedDN : CN = < new_dc_netbios_name > , CN = Servers , CN = < new_dc_site_name > , CN = Sites , CN = Configuration , < domain_partition > >
*/
/*
* LDAP search 1 st LDAP connection :
*
* not implemented because it gives no new information
*
* Request :
* basedn : CN = Partitions , CN = Configuration , < domain_partition >
* scope : sub
* filter : ( nCName = < domain_partition > )
* attrs : nCName
* dnsRoot
* controls : LDAP_SERVER_EXTENDED_DN_OID : critical = false
* Result :
* < GUID = < hex_guid > > ; CN = < domain_netbios_name > , CN = Partitions , < domain_partition > >
* nCName : < GUID = < hex_guid > > ; < SID = < hex_sid > > ; < domain_partition > >
* dnsRoot : < domain_dns_name >
*/
/*
* LDAP modify 1 st LDAP connection :
*
* see : becomeDC_ldap1_server_object_modify ( )
*
* Request ( add ) :
* CN = < new_dc_netbios_name > , CN = Servers , CN = < new_dc_site_name > , CN = Sites , CN = Configuration , < domain_partition > >
* serverReference : CN = < new_dc_netbios_name > , CN = Computers , < domain_partition >
* Result :
* < attributeOrValueExist >
*/
/*
* LDAP modify 1 st LDAP connection :
*
* see : becomeDC_ldap1_server_object_modify ( )
*
* Request ( replace ) :
* CN = < new_dc_netbios_name > , CN = Servers , CN = < new_dc_site_name > , CN = Sites , CN = Configuration , < domain_partition > >
* serverReference : CN = < new_dc_netbios_name > , CN = Computers , < domain_partition >
* Result :
* < success >
*/
/*
* Open 1 st DRSUAPI connection to the DC using admin credentials
* DsBind with DRSUAPI_DS_BIND_GUID_W2K3 ( " 6afab99c-6e26-464a-975f-f58f105218bc " )
* ( w2k3 does 2 DsBind ( ) calls here . . . , where is first is unused and contains garbage at the end )
*
* see : becomeDC_drsuapi_connect_send ( ) , becomeDC_drsuapi1_connect_recv ( ) ,
* becomeDC_drsuapi_bind_send ( ) , becomeDC_drsuapi_bind_recv ( ) and becomeDC_drsuapi1_bind_recv ( )
*/
/*
* DsAddEntry to create the CN = NTDS Settings , CN = < machine_name > , CN = Servers , CN = Default - First - Site - Name , . . .
* on the 1 st DRSUAPI connection
*
* see : becomeDC_drsuapi1_add_entry_send ( ) and becomeDC_drsuapi1_add_entry_recv ( )
*/
/***************************************************************
* Add this stage we call the prepare_db ( ) callback function
* of the caller , to see if he wants us to continue
*
* see : becomeDC_prepare_db ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* Open 2 nd and 3 rd DRSUAPI connection to the DC using admin credentials
* - a DsBind with DRSUAPI_DS_BIND_GUID_W2K3 ( " 6afab99c-6e26-464a-975f-f58f105218bc " )
* on the 2 nd connection
*
* see : becomeDC_drsuapi_connect_send ( ) , becomeDC_drsuapi2_connect_recv ( ) ,
* becomeDC_drsuapi_bind_send ( ) , becomeDC_drsuapi_bind_recv ( ) , becomeDC_drsuapi2_bind_recv ( )
* and becomeDC_drsuapi3_connect_recv ( )
*/
/*
* replicate CN = Schema , CN = Configuration , . . .
* on the 3 rd DRSUAPI connection and the bind_handle from the 2 nd connection
*
* see : becomeDC_drsuapi_pull_partition_send ( ) , becomeDC_drsuapi_pull_partition_recv ( ) ,
* becomeDC_drsuapi3_pull_schema_send ( ) and becomeDC_drsuapi3_pull_schema_recv ( )
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Add this stage we call the schema_chunk ( ) callback function
* for each replication message
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* replicate CN = Configuration , . . .
* on the 3 rd DRSUAPI connection and the bind_handle from the 2 nd connection
*
* see : becomeDC_drsuapi_pull_partition_send ( ) , becomeDC_drsuapi_pull_partition_recv ( ) ,
* becomeDC_drsuapi3_pull_config_send ( ) and becomeDC_drsuapi3_pull_config_recv ( )
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Add this stage we call the config_chunk ( ) callback function
* for each replication message
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* LDAP unbind on the 1 st LDAP connection
*
* not implemented , because it ' s not needed . . .
*/
/*
* Open 2 nd LDAP connection to the DC using admin credentials
*
* see : becomeDC_connect_ldap2 ( ) and becomeDC_ldap_connect ( )
*/
/*
* LDAP search 2 nd LDAP connection :
*
* not implemented because it gives no new information
* same as becomeDC_ldap1_computer_object ( )
*
* Request :
* basedn : < domain_partition >
* scope : sub
* filter : ( & ( | ( objectClass = user ) ( objectClass = computer ) ) ( sAMAccountName = < new_dc_account_name > ) )
* attrs : distinguishedName
* userAccountControl
* Result :
* CN = < new_dc_netbios_name > , CN = Computers , < domain_partition >
* distinguishedName : CN = < new_dc_netbios_name > , CN = Computers , < domain_partition >
2024-03-05 02:37:11 +03:00
* userAccountControl : 4096 < 0x00001000 >
2007-03-13 18:41:25 +03:00
*/
/*
* LDAP search 2 nd LDAP connection :
*
* not implemented because it gives no new information
* same as becomeDC_ldap1_computer_object ( )
*
* Request :
* basedn : CN = < new_dc_netbios_name > , CN = Computers , < domain_partition >
* scope : base
* filter : ( objectClass = * )
* attrs : userAccountControl
* Result :
* CN = < new_dc_netbios_name > , CN = Computers , < domain_partition >
2024-03-05 02:37:11 +03:00
* userAccountControl : 4096 < 0x00001000 >
2007-03-13 18:41:25 +03:00
*/
/*
* LDAP modify 2 nd LDAP connection :
*
* see : becomeDC_ldap2_modify_computer ( )
*
* Request ( replace ) :
* CN = < new_dc_netbios_name > , CN = Computers , < domain_partition >
2024-03-05 02:37:11 +03:00
* userAccountControl : 532480 < 0x82000 >
2007-03-13 18:41:25 +03:00
* Result :
* < success >
*/
/*
* LDAP search 2 nd LDAP connection :
*
* see : becomeDC_ldap2_move_computer ( )
*
* Request :
* basedn : < WKGUID = 2f bac1870ade11d297c400c04fd8d5cd , < domain_partition > >
* scope : base
* filter : ( objectClass = * )
* attrs : 1.1
* Result :
* CN = Domain Controllers , < domain_partition >
*/
/*
* LDAP search 2 nd LDAP connection :
*
* not implemented because it gives no new information
*
* Request :
* basedn : CN = Domain Controllers , < domain_partition >
* scope : base
* filter : ( objectClass = * )
* attrs : distinguishedName
* Result :
* CN = Domain Controller , < domain_partition >
* distinguishedName : CN = Domain Controllers , < domain_partition >
*/
/*
* LDAP modifyRDN 2 nd LDAP connection :
*
* see : becomeDC_ldap2_move_computer ( )
*
* Request :
* entry : CN = < new_dc_netbios_name > , CN = Computers , < domain_partition >
* newrdn : CN = < new_dc_netbios_name >
* deleteoldrdn : TRUE
* newparent : CN = Domain Controllers , < domain_partition >
* Result :
* < success >
*/
/*
* LDAP unbind on the 2 nd LDAP connection
*
* not implemented , because it ' s not needed . . .
*/
/*
* replicate Domain Partition
* on the 3 rd DRSUAPI connection and the bind_handle from the 2 nd connection
*
* see : becomeDC_drsuapi_pull_partition_send ( ) , becomeDC_drsuapi_pull_partition_recv ( ) ,
* becomeDC_drsuapi3_pull_domain_send ( ) and becomeDC_drsuapi3_pull_domain_recv ( )
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Add this stage we call the domain_chunk ( ) callback function
* for each replication message
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* call DsReplicaUpdateRefs() for all partitions like this:
* req1 : struct drsuapi_DsReplicaUpdateRefsRequest1
*
* naming_context : struct drsuapi_DsReplicaObjectIdentifier
* __ndr_size : 0x000000ae ( 174 )
* __ndr_size_sid : 0x00000000 ( 0 )
* guid : 00000000 - 0000 - 0000 - 0000 - 000000000000
* sid : S - 0 - 0
* dn : ' CN = Schema , CN = Configuration , DC = w2k3 , DC = vmnet1 , DC = vm , DC = base '
*
* dest_dsa_dns_name : ' 4 a0df188 - a0b8 - 47 ea - bbe5 - e614723f16dd . _msdcs . w2k3 . vmnet1 . vm . base '
* dest_dsa_guid : 4 a0df188 - a0b8 - 47 ea - bbe5 - e614723f16dd
* options : 0x0000001c ( 28 )
* 0 : DRSUAPI_DS_REPLICA_UPDATE_ASYNCHRONOUS_OPERATION
* 0 : DRSUAPI_DS_REPLICA_UPDATE_WRITEABLE
* 1 : DRSUAPI_DS_REPLICA_UPDATE_ADD_REFERENCE
* 1 : DRSUAPI_DS_REPLICA_UPDATE_DELETE_REFERENCE
* 1 : DRSUAPI_DS_REPLICA_UPDATE_0x00000010
*
* 4 a0df188 - a0b8 - 47 ea - bbe5 - e614723f16dd is the objectGUID the DsAddEntry ( ) returned for the
* CN = NTDS Settings , CN = < machine_name > , CN = Servers , CN = Default - First - Site - Name , . . .
* on the 2 nd ! ! ! DRSUAPI connection
*
* see : becomeDC_drsuapi_update_refs_send ( ) , becomeDC_drsuapi2_update_refs_schema_recv ( ) ,
* becomeDC_drsuapi2_update_refs_config_recv ( ) and becomeDC_drsuapi2_update_refs_domain_recv ( )
*/
/*
* Windows does opens the 4 th and 5 th DRSUAPI connection . . .
* and does a DsBind ( ) with the objectGUID from DsAddEntry ( ) as bind_guid
* on the 4 th connection
*
* and then 2 full replications of the domain partition on the 5 th connection
* with the bind_handle from the 4 th connection
*
* not implemented because it gives no new information
*/
2006-12-02 18:35:27 +03:00
struct libnet_BecomeDC_state {
2006-12-03 22:22:51 +03:00
struct composite_context * creq ;
2006-12-02 18:35:27 +03:00
struct libnet_context * libnet ;
2006-12-07 18:33:24 +03:00
struct dom_sid zero_sid ;
2006-12-03 22:22:51 +03:00
struct {
struct cldap_socket * sock ;
struct cldap_netlogon io ;
2008-05-16 07:03:01 +04:00
struct NETLOGON_SAM_LOGON_RESPONSE_EX netlogon ;
2006-12-03 22:22:51 +03:00
} cldap ;
2006-12-02 18:35:27 +03:00
struct becomeDC_ldap {
struct ldb_context * ldb ;
2006-12-03 23:37:44 +03:00
const struct ldb_message * rootdse ;
2006-12-05 16:46:27 +03:00
} ldap1 , ldap2 ;
2006-12-02 18:35:27 +03:00
2006-12-06 15:15:07 +03:00
struct becomeDC_drsuapi {
struct libnet_BecomeDC_state * s ;
struct dcerpc_binding * binding ;
struct dcerpc_pipe * pipe ;
2010-03-08 18:41:43 +03:00
struct dcerpc_binding_handle * drsuapi_handle ;
2007-02-12 13:58:06 +03:00
DATA_BLOB gensec_skey ;
2006-12-06 15:15:07 +03:00
struct drsuapi_DsBind bind_r ;
struct GUID bind_guid ;
2006-12-06 19:04:43 +03:00
struct drsuapi_DsBindInfoCtr bind_info_ctr ;
struct drsuapi_DsBindInfo28 local_info28 ;
struct drsuapi_DsBindInfo28 remote_info28 ;
2006-12-06 15:15:07 +03:00
struct policy_handle bind_handle ;
2006-12-07 22:50:46 +03:00
} drsuapi1 , drsuapi2 , drsuapi3 ;
2006-12-06 15:15:07 +03:00
2010-02-27 12:00:42 +03:00
void * ndr_struct_ptr ;
2006-12-20 19:34:35 +03:00
struct libnet_BecomeDC_Domain domain ;
struct libnet_BecomeDC_Forest forest ;
struct libnet_BecomeDC_SourceDSA source_dsa ;
struct libnet_BecomeDC_DestDSA dest_dsa ;
2006-12-04 12:40:16 +03:00
2006-12-21 00:54:06 +03:00
struct libnet_BecomeDC_Partition schema_part , config_part , domain_part ;
2006-12-08 03:16:36 +03:00
2006-12-04 12:40:16 +03:00
struct becomeDC_fsmo {
const char * dns_name ;
const char * server_dn_str ;
const char * ntds_dn_str ;
struct GUID ntds_guid ;
} infrastructure_fsmo ;
2006-12-04 13:02:08 +03:00
struct becomeDC_fsmo rid_manager_fsmo ;
2006-12-20 17:49:40 +03:00
2006-12-20 19:34:35 +03:00
struct libnet_BecomeDC_CheckOptions _co ;
2006-12-21 00:14:44 +03:00
struct libnet_BecomeDC_PrepareDB _pp ;
2006-12-21 00:54:06 +03:00
struct libnet_BecomeDC_StoreChunk _sc ;
2006-12-20 18:34:32 +03:00
struct libnet_BecomeDC_Callbacks callbacks ;
2010-02-17 19:01:31 +03:00
bool rodc_join ;
2011-11-05 03:22:47 +04:00
bool critical_only ;
2006-12-02 18:35:27 +03:00
} ;
2009-09-25 12:44:19 +04:00
static int32_t get_dc_function_level ( struct loadparm_context * lp_ctx )
{
2010-06-21 15:40:15 +04:00
/* per default we are (Windows) 2008 R2 compatible */
2010-07-16 08:32:42 +04:00
return lpcfg_parm_int ( lp_ctx , NULL , " ads " , " dc function level " ,
2010-06-21 15:40:15 +04:00
DS_DOMAIN_FUNCTION_2008_R2 ) ;
2009-09-25 12:44:19 +04:00
}
2009-02-13 15:13:54 +03:00
static void becomeDC_recv_cldap ( struct tevent_req * req ) ;
2007-03-13 17:32:20 +03:00
static void becomeDC_send_cldap ( struct libnet_BecomeDC_state * s )
{
struct composite_context * c = s - > creq ;
2009-02-13 15:13:54 +03:00
struct tevent_req * req ;
2010-02-25 14:47:38 +03:00
struct tsocket_address * dest_address ;
int ret ;
2007-03-13 17:32:20 +03:00
2010-02-25 14:47:38 +03:00
s - > cldap . io . in . dest_address = NULL ;
s - > cldap . io . in . dest_port = 0 ;
2007-03-13 17:32:20 +03:00
s - > cldap . io . in . realm = s - > domain . dns_name ;
s - > cldap . io . in . host = s - > dest_dsa . netbios_name ;
s - > cldap . io . in . user = NULL ;
s - > cldap . io . in . domain_guid = NULL ;
s - > cldap . io . in . domain_sid = NULL ;
s - > cldap . io . in . acct_control = - 1 ;
2008-05-16 07:03:01 +04:00
s - > cldap . io . in . version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX ;
s - > cldap . io . in . map_response = true ;
2007-03-13 17:32:20 +03:00
2010-02-25 14:47:38 +03:00
ret = tsocket_address_inet_from_strings ( s , " ip " ,
s - > source_dsa . address ,
2010-07-16 08:32:42 +04:00
lpcfg_cldap_port ( s - > libnet - > lp_ctx ) ,
2010-02-25 14:47:38 +03:00
& dest_address ) ;
if ( ret ! = 0 ) {
2011-06-20 08:55:32 +04:00
c - > status = map_nt_error_from_unix_common ( errno ) ;
2010-02-25 14:47:38 +03:00
if ( ! composite_is_ok ( c ) ) return ;
}
2011-10-10 17:58:24 +04:00
c - > status = cldap_socket_init ( s , NULL , dest_address , & s - > cldap . sock ) ;
2009-02-13 15:13:54 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2007-03-13 17:32:20 +03:00
2011-10-10 17:42:57 +04:00
req = cldap_netlogon_send ( s , s - > libnet - > event_ctx ,
s - > cldap . sock , & s - > cldap . io ) ;
2007-03-13 17:32:20 +03:00
if ( composite_nomem ( req , c ) ) return ;
2009-02-13 15:13:54 +03:00
tevent_req_set_callback ( req , becomeDC_recv_cldap , s ) ;
2007-03-13 17:32:20 +03:00
}
2006-12-03 23:37:44 +03:00
static void becomeDC_connect_ldap1 ( struct libnet_BecomeDC_state * s ) ;
2009-02-13 15:13:54 +03:00
static void becomeDC_recv_cldap ( struct tevent_req * req )
2006-12-03 22:22:51 +03:00
{
2009-02-13 15:13:54 +03:00
struct libnet_BecomeDC_state * s = tevent_req_callback_data ( req ,
2006-12-03 22:22:51 +03:00
struct libnet_BecomeDC_state ) ;
struct composite_context * c = s - > creq ;
2010-05-09 19:20:01 +04:00
c - > status = cldap_netlogon_recv ( req , s , & s - > cldap . io ) ;
2009-02-13 15:13:54 +03:00
talloc_free ( req ) ;
2009-11-09 12:31:42 +03:00
if ( ! composite_is_ok ( c ) ) {
DEBUG ( 0 , ( " Failed to send, receive or parse CLDAP reply from server %s for our host %s: %s \n " ,
s - > cldap . io . in . dest_address ,
s - > cldap . io . in . host ,
nt_errstr ( c - > status ) ) ) ;
return ;
}
2008-10-02 10:09:25 +04:00
s - > cldap . netlogon = s - > cldap . io . out . netlogon . data . nt5_ex ;
2006-12-03 22:22:51 +03:00
2008-05-16 07:03:01 +04:00
s - > domain . dns_name = s - > cldap . netlogon . dns_domain ;
2010-04-27 18:56:36 +04:00
s - > domain . netbios_name = s - > cldap . netlogon . domain_name ;
2008-05-16 07:03:01 +04:00
s - > domain . guid = s - > cldap . netlogon . domain_uuid ;
2006-12-03 22:22:51 +03:00
2008-05-16 07:03:01 +04:00
s - > forest . dns_name = s - > cldap . netlogon . forest ;
2006-12-03 22:22:51 +03:00
2008-05-16 07:03:01 +04:00
s - > source_dsa . dns_name = s - > cldap . netlogon . pdc_dns_name ;
s - > source_dsa . netbios_name = s - > cldap . netlogon . pdc_name ;
s - > source_dsa . site_name = s - > cldap . netlogon . server_site ;
2006-12-03 22:22:51 +03:00
2008-05-16 07:03:01 +04:00
s - > dest_dsa . site_name = s - > cldap . netlogon . client_site ;
2006-12-03 22:22:51 +03:00
2010-04-27 06:17:36 +04:00
DEBUG ( 0 , ( " CLDAP response: forest=%s dns=%s netbios=%s server_site=%s client_site=%s \n " ,
s - > forest . dns_name , s - > domain . dns_name , s - > domain . netbios_name ,
s - > source_dsa . site_name , s - > dest_dsa . site_name ) ) ;
2010-04-27 09:02:29 +04:00
if ( ! s - > dest_dsa . site_name | | strcmp ( s - > dest_dsa . site_name , " " ) = = 0 ) {
DEBUG ( 0 , ( " Got empty client site - using server site name %s \n " ,
s - > source_dsa . site_name ) ) ;
s - > dest_dsa . site_name = s - > source_dsa . site_name ;
}
2010-04-27 06:17:36 +04:00
2006-12-03 23:37:44 +03:00
becomeDC_connect_ldap1 ( s ) ;
2006-12-03 22:22:51 +03:00
}
2007-12-04 03:51:36 +03:00
static NTSTATUS becomeDC_ldap_connect ( struct libnet_BecomeDC_state * s ,
struct becomeDC_ldap * ldap )
2006-12-02 18:35:27 +03:00
{
2006-12-03 23:37:44 +03:00
char * url ;
url = talloc_asprintf ( s , " ldap://%s/ " , s - > source_dsa . dns_name ) ;
NT_STATUS_HAVE_NO_MEMORY ( url ) ;
2008-04-17 14:23:44 +04:00
ldap - > ldb = ldb_wrap_connect ( s , s - > libnet - > event_ctx , s - > libnet - > lp_ctx , url ,
2006-12-03 23:37:44 +03:00
NULL ,
s - > libnet - > cred ,
2009-10-23 07:27:00 +04:00
0 ) ;
2006-12-03 23:37:44 +03:00
talloc_free ( url ) ;
if ( ldap - > ldb = = NULL ) {
return NT_STATUS_UNEXPECTED_NETWORK_ERROR ;
}
return NT_STATUS_OK ;
}
static NTSTATUS becomeDC_ldap1_rootdse ( struct libnet_BecomeDC_state * s )
{
int ret ;
struct ldb_result * r ;
struct ldb_dn * basedn ;
2007-12-20 02:02:15 +03:00
static const char * attrs [ ] = {
2006-12-03 23:37:44 +03:00
" * " ,
NULL
} ;
basedn = ldb_dn_new ( s , s - > ldap1 . ldb , NULL ) ;
2006-12-04 00:05:18 +03:00
NT_STATUS_HAVE_NO_MEMORY ( basedn ) ;
2006-12-03 23:37:44 +03:00
2008-09-23 22:30:06 +04:00
ret = ldb_search ( s - > ldap1 . ldb , s , & r , basedn , LDB_SCOPE_BASE , attrs ,
" (objectClass=*) " ) ;
2006-12-03 23:37:44 +03:00
talloc_free ( basedn ) ;
if ( ret ! = LDB_SUCCESS ) {
return NT_STATUS_LDAP ( ret ) ;
} else if ( r - > count ! = 1 ) {
talloc_free ( r ) ;
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
s - > ldap1 . rootdse = r - > msgs [ 0 ] ;
s - > domain . dn_str = ldb_msg_find_attr_as_string ( s - > ldap1 . rootdse , " defaultNamingContext " , NULL ) ;
if ( ! s - > domain . dn_str ) return NT_STATUS_INVALID_NETWORK_RESPONSE ;
s - > forest . root_dn_str = ldb_msg_find_attr_as_string ( s - > ldap1 . rootdse , " rootDomainNamingContext " , NULL ) ;
if ( ! s - > forest . root_dn_str ) return NT_STATUS_INVALID_NETWORK_RESPONSE ;
s - > forest . config_dn_str = ldb_msg_find_attr_as_string ( s - > ldap1 . rootdse , " configurationNamingContext " , NULL ) ;
if ( ! s - > forest . config_dn_str ) return NT_STATUS_INVALID_NETWORK_RESPONSE ;
s - > forest . schema_dn_str = ldb_msg_find_attr_as_string ( s - > ldap1 . rootdse , " schemaNamingContext " , NULL ) ;
if ( ! s - > forest . schema_dn_str ) return NT_STATUS_INVALID_NETWORK_RESPONSE ;
s - > source_dsa . server_dn_str = ldb_msg_find_attr_as_string ( s - > ldap1 . rootdse , " serverName " , NULL ) ;
if ( ! s - > source_dsa . server_dn_str ) return NT_STATUS_INVALID_NETWORK_RESPONSE ;
s - > source_dsa . ntds_dn_str = ldb_msg_find_attr_as_string ( s - > ldap1 . rootdse , " dsServiceName " , NULL ) ;
if ( ! s - > source_dsa . ntds_dn_str ) return NT_STATUS_INVALID_NETWORK_RESPONSE ;
return NT_STATUS_OK ;
2006-12-02 18:35:27 +03:00
}
2006-12-20 19:34:35 +03:00
static NTSTATUS becomeDC_ldap1_crossref_behavior_version ( struct libnet_BecomeDC_state * s )
2006-12-02 18:35:27 +03:00
{
2006-12-03 23:37:44 +03:00
int ret ;
struct ldb_result * r ;
struct ldb_dn * basedn ;
2007-12-20 02:02:15 +03:00
static const char * attrs [ ] = {
2006-12-03 23:37:44 +03:00
" msDs-Behavior-Version " ,
NULL
} ;
basedn = ldb_dn_new ( s , s - > ldap1 . ldb , s - > forest . config_dn_str ) ;
2006-12-04 00:05:18 +03:00
NT_STATUS_HAVE_NO_MEMORY ( basedn ) ;
2006-12-03 23:37:44 +03:00
2008-09-23 22:30:06 +04:00
ret = ldb_search ( s - > ldap1 . ldb , s , & r , basedn , LDB_SCOPE_ONELEVEL , attrs ,
" (cn=Partitions) " ) ;
2006-12-03 23:37:44 +03:00
talloc_free ( basedn ) ;
if ( ret ! = LDB_SUCCESS ) {
return NT_STATUS_LDAP ( ret ) ;
} else if ( r - > count ! = 1 ) {
talloc_free ( r ) ;
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
2006-12-20 19:34:35 +03:00
s - > forest . crossref_behavior_version = ldb_msg_find_attr_as_uint ( r - > msgs [ 0 ] , " msDs-Behavior-Version " , 0 ) ;
2009-09-25 12:44:19 +04:00
if ( s - > forest . crossref_behavior_version >
get_dc_function_level ( s - > libnet - > lp_ctx ) ) {
talloc_free ( r ) ;
2009-10-02 09:09:59 +04:00
DEBUG ( 0 , ( " The servers function level %u is above 'ads:dc function level' of %u \n " ,
s - > forest . crossref_behavior_version ,
get_dc_function_level ( s - > libnet - > lp_ctx ) ) ) ;
2009-09-25 12:44:19 +04:00
return NT_STATUS_NOT_SUPPORTED ;
}
2006-12-03 23:37:44 +03:00
talloc_free ( r ) ;
return NT_STATUS_OK ;
}
static NTSTATUS becomeDC_ldap1_domain_behavior_version ( struct libnet_BecomeDC_state * s )
{
int ret ;
struct ldb_result * r ;
struct ldb_dn * basedn ;
2007-12-20 02:02:15 +03:00
static const char * attrs [ ] = {
2006-12-03 23:37:44 +03:00
" msDs-Behavior-Version " ,
NULL
} ;
basedn = ldb_dn_new ( s , s - > ldap1 . ldb , s - > domain . dn_str ) ;
2006-12-04 00:05:18 +03:00
NT_STATUS_HAVE_NO_MEMORY ( basedn ) ;
2006-12-03 23:37:44 +03:00
2008-09-23 22:30:06 +04:00
ret = ldb_search ( s - > ldap1 . ldb , s , & r , basedn , LDB_SCOPE_BASE , attrs ,
" (objectClass=*) " ) ;
2006-12-03 23:37:44 +03:00
talloc_free ( basedn ) ;
if ( ret ! = LDB_SUCCESS ) {
return NT_STATUS_LDAP ( ret ) ;
} else if ( r - > count ! = 1 ) {
talloc_free ( r ) ;
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
2006-12-20 19:34:35 +03:00
s - > domain . behavior_version = ldb_msg_find_attr_as_uint ( r - > msgs [ 0 ] , " msDs-Behavior-Version " , 0 ) ;
2009-09-25 12:44:19 +04:00
if ( s - > domain . behavior_version >
get_dc_function_level ( s - > libnet - > lp_ctx ) ) {
talloc_free ( r ) ;
2009-10-02 09:09:59 +04:00
DEBUG ( 0 , ( " The servers function level %u is above 'ads:dc function level' of %u \n " ,
s - > forest . crossref_behavior_version ,
get_dc_function_level ( s - > libnet - > lp_ctx ) ) ) ;
2009-09-25 12:44:19 +04:00
return NT_STATUS_NOT_SUPPORTED ;
}
2006-12-03 23:37:44 +03:00
talloc_free ( r ) ;
return NT_STATUS_OK ;
}
static NTSTATUS becomeDC_ldap1_schema_object_version ( struct libnet_BecomeDC_state * s )
{
int ret ;
struct ldb_result * r ;
struct ldb_dn * basedn ;
2007-12-20 02:02:15 +03:00
static const char * attrs [ ] = {
2006-12-03 23:37:44 +03:00
" objectVersion " ,
NULL
} ;
basedn = ldb_dn_new ( s , s - > ldap1 . ldb , s - > forest . schema_dn_str ) ;
2006-12-04 00:05:18 +03:00
NT_STATUS_HAVE_NO_MEMORY ( basedn ) ;
2006-12-03 23:37:44 +03:00
2008-09-23 22:30:06 +04:00
ret = ldb_search ( s - > ldap1 . ldb , s , & r , basedn , LDB_SCOPE_BASE , attrs ,
" (objectClass=*) " ) ;
2006-12-03 23:37:44 +03:00
talloc_free ( basedn ) ;
if ( ret ! = LDB_SUCCESS ) {
return NT_STATUS_LDAP ( ret ) ;
} else if ( r - > count ! = 1 ) {
talloc_free ( r ) ;
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
2006-12-20 19:34:35 +03:00
s - > forest . schema_object_version = ldb_msg_find_attr_as_uint ( r - > msgs [ 0 ] , " objectVersion " , 0 ) ;
2006-12-03 23:37:44 +03:00
talloc_free ( r ) ;
return NT_STATUS_OK ;
}
2006-12-04 12:40:16 +03:00
static NTSTATUS becomeDC_ldap1_w2k3_update_revision ( struct libnet_BecomeDC_state * s )
{
int ret ;
struct ldb_result * r ;
struct ldb_dn * basedn ;
2007-12-20 02:02:15 +03:00
static const char * attrs [ ] = {
2006-12-04 12:40:16 +03:00
" revision " ,
NULL
} ;
basedn = ldb_dn_new_fmt ( s , s - > ldap1 . ldb , " CN=Windows2003Update,CN=DomainUpdates,CN=System,%s " ,
s - > domain . dn_str ) ;
NT_STATUS_HAVE_NO_MEMORY ( basedn ) ;
2008-09-23 22:30:06 +04:00
ret = ldb_search ( s - > ldap1 . ldb , s , & r , basedn , LDB_SCOPE_BASE , attrs ,
" (objectClass=*) " ) ;
2006-12-04 12:40:16 +03:00
talloc_free ( basedn ) ;
2006-12-11 20:04:43 +03:00
if ( ret = = LDB_ERR_NO_SUCH_OBJECT ) {
/* w2k doesn't have this object */
2006-12-20 19:34:35 +03:00
s - > domain . w2k3_update_revision = 0 ;
2006-12-11 20:04:43 +03:00
return NT_STATUS_OK ;
} else if ( ret ! = LDB_SUCCESS ) {
2006-12-04 12:40:16 +03:00
return NT_STATUS_LDAP ( ret ) ;
} else if ( r - > count ! = 1 ) {
talloc_free ( r ) ;
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
2006-12-20 19:34:35 +03:00
s - > domain . w2k3_update_revision = ldb_msg_find_attr_as_uint ( r - > msgs [ 0 ] , " revision " , 0 ) ;
2006-12-04 12:40:16 +03:00
talloc_free ( r ) ;
return NT_STATUS_OK ;
}
2006-12-04 00:05:18 +03:00
static NTSTATUS becomeDC_ldap1_infrastructure_fsmo ( struct libnet_BecomeDC_state * s )
{
int ret ;
struct ldb_result * r ;
struct ldb_dn * basedn ;
2006-12-04 12:40:16 +03:00
struct ldb_dn * ntds_dn ;
struct ldb_dn * server_dn ;
2007-12-20 02:02:15 +03:00
static const char * dns_attrs [ ] = {
2006-12-04 12:40:16 +03:00
" dnsHostName " ,
NULL
} ;
2007-12-20 02:02:15 +03:00
static const char * guid_attrs [ ] = {
2006-12-04 12:40:16 +03:00
" objectGUID " ,
NULL
} ;
2006-12-04 00:05:18 +03:00
2010-04-13 10:41:10 +04:00
ret = dsdb_wellknown_dn ( s - > ldap1 . ldb , s ,
ldb_get_default_basedn ( s - > ldap1 . ldb ) ,
2010-01-09 07:57:52 +03:00
DS_GUID_INFRASTRUCTURE_CONTAINER ,
& basedn ) ;
2006-12-04 00:05:18 +03:00
if ( ret ! = LDB_SUCCESS ) {
2012-08-14 16:53:35 +04:00
DEBUG ( 0 , ( " Failed to get well known DN for DS_GUID_INFRASTRUCTURE_CONTAINER on %s: %s \n " ,
ldb_dn_get_linearized ( ldb_get_default_basedn ( s - > ldap1 . ldb ) ) ,
ldb_errstring ( s - > ldap1 . ldb ) ) ) ;
2006-12-04 00:05:18 +03:00
return NT_STATUS_LDAP ( ret ) ;
}
2010-01-09 07:57:52 +03:00
ret = samdb_reference_dn ( s - > ldap1 . ldb , s , basedn , " fSMORoleOwner " , & ntds_dn ) ;
2006-12-04 00:05:18 +03:00
if ( ret ! = LDB_SUCCESS ) {
2012-08-14 16:53:35 +04:00
DEBUG ( 0 , ( " Failed to get reference DN from fsmoRoleOwner on %s: %s \n " ,
ldb_dn_get_linearized ( basedn ) ,
ldb_errstring ( s - > ldap1 . ldb ) ) ) ;
2010-01-09 07:57:52 +03:00
talloc_free ( basedn ) ;
2006-12-04 00:05:18 +03:00
return NT_STATUS_LDAP ( ret ) ;
}
2010-01-09 07:57:52 +03:00
s - > infrastructure_fsmo . ntds_dn_str = ldb_dn_get_linearized ( ntds_dn ) ;
NT_STATUS_HAVE_NO_MEMORY ( s - > infrastructure_fsmo . ntds_dn_str ) ;
2006-12-04 12:40:16 +03:00
server_dn = ldb_dn_get_parent ( s , ntds_dn ) ;
NT_STATUS_HAVE_NO_MEMORY ( server_dn ) ;
2006-12-04 13:02:08 +03:00
s - > infrastructure_fsmo . server_dn_str = ldb_dn_alloc_linearized ( s , server_dn ) ;
NT_STATUS_HAVE_NO_MEMORY ( s - > infrastructure_fsmo . server_dn_str ) ;
2008-09-23 22:30:06 +04:00
ret = ldb_search ( s - > ldap1 . ldb , s , & r , server_dn , LDB_SCOPE_BASE ,
dns_attrs , " (objectClass=*) " ) ;
2006-12-04 12:40:16 +03:00
if ( ret ! = LDB_SUCCESS ) {
2012-08-14 16:53:35 +04:00
DEBUG ( 0 , ( " Failed to get server DN %s: %s \n " ,
ldb_dn_get_linearized ( server_dn ) ,
ldb_errstring ( s - > ldap1 . ldb ) ) ) ;
2006-12-04 12:40:16 +03:00
return NT_STATUS_LDAP ( ret ) ;
} else if ( r - > count ! = 1 ) {
talloc_free ( r ) ;
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
2010-10-14 11:41:42 +04:00
s - > infrastructure_fsmo . dns_name = ldb_msg_find_attr_as_string ( r - > msgs [ 0 ] , " dnsHostName " , NULL ) ;
2006-12-04 12:40:16 +03:00
if ( ! s - > infrastructure_fsmo . dns_name ) return NT_STATUS_INVALID_NETWORK_RESPONSE ;
talloc_steal ( s , s - > infrastructure_fsmo . dns_name ) ;
2006-12-04 00:05:18 +03:00
talloc_free ( r ) ;
2006-12-04 12:40:16 +03:00
2012-08-14 16:54:26 +04:00
ldb_dn_remove_extended_components ( ntds_dn ) ;
2008-09-23 22:30:06 +04:00
ret = ldb_search ( s - > ldap1 . ldb , s , & r , ntds_dn , LDB_SCOPE_BASE ,
guid_attrs , " (objectClass=*) " ) ;
2006-12-04 12:40:16 +03:00
if ( ret ! = LDB_SUCCESS ) {
2012-08-14 16:53:35 +04:00
DEBUG ( 0 , ( " Failed to get NTDS Settings DN %s: %s \n " ,
ldb_dn_get_linearized ( ntds_dn ) ,
ldb_errstring ( s - > ldap1 . ldb ) ) ) ;
2006-12-04 12:40:16 +03:00
return NT_STATUS_LDAP ( ret ) ;
} else if ( r - > count ! = 1 ) {
talloc_free ( r ) ;
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
s - > infrastructure_fsmo . ntds_guid = samdb_result_guid ( r - > msgs [ 0 ] , " objectGUID " ) ;
talloc_free ( r ) ;
2006-12-04 13:02:08 +03:00
return NT_STATUS_OK ;
}
static NTSTATUS becomeDC_ldap1_rid_manager_fsmo ( struct libnet_BecomeDC_state * s )
{
int ret ;
struct ldb_result * r ;
struct ldb_dn * basedn ;
const char * reference_dn_str ;
struct ldb_dn * ntds_dn ;
struct ldb_dn * server_dn ;
2007-12-20 02:02:15 +03:00
static const char * rid_attrs [ ] = {
2006-12-04 13:02:08 +03:00
" rIDManagerReference " ,
NULL
} ;
2007-12-20 02:02:15 +03:00
static const char * fsmo_attrs [ ] = {
2006-12-04 13:02:08 +03:00
" fSMORoleOwner " ,
NULL
} ;
2007-12-20 02:02:15 +03:00
static const char * dns_attrs [ ] = {
2006-12-04 13:02:08 +03:00
" dnsHostName " ,
NULL
} ;
2007-12-20 02:02:15 +03:00
static const char * guid_attrs [ ] = {
2006-12-04 13:02:08 +03:00
" objectGUID " ,
NULL
} ;
basedn = ldb_dn_new ( s , s - > ldap1 . ldb , s - > domain . dn_str ) ;
NT_STATUS_HAVE_NO_MEMORY ( basedn ) ;
2008-09-23 22:30:06 +04:00
ret = ldb_search ( s - > ldap1 . ldb , s , & r , basedn , LDB_SCOPE_BASE ,
rid_attrs , " (objectClass=*) " ) ;
2006-12-04 13:02:08 +03:00
talloc_free ( basedn ) ;
if ( ret ! = LDB_SUCCESS ) {
return NT_STATUS_LDAP ( ret ) ;
} else if ( r - > count ! = 1 ) {
talloc_free ( r ) ;
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
2010-10-14 11:41:42 +04:00
reference_dn_str = ldb_msg_find_attr_as_string ( r - > msgs [ 0 ] , " rIDManagerReference " , NULL ) ;
2006-12-04 13:02:08 +03:00
if ( ! reference_dn_str ) return NT_STATUS_INVALID_NETWORK_RESPONSE ;
basedn = ldb_dn_new ( s , s - > ldap1 . ldb , reference_dn_str ) ;
NT_STATUS_HAVE_NO_MEMORY ( basedn ) ;
talloc_free ( r ) ;
2008-09-23 22:30:06 +04:00
ret = ldb_search ( s - > ldap1 . ldb , s , & r , basedn , LDB_SCOPE_BASE ,
fsmo_attrs , " (objectClass=*) " ) ;
2006-12-04 13:02:08 +03:00
talloc_free ( basedn ) ;
if ( ret ! = LDB_SUCCESS ) {
return NT_STATUS_LDAP ( ret ) ;
} else if ( r - > count ! = 1 ) {
talloc_free ( r ) ;
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
2010-10-14 11:41:42 +04:00
s - > rid_manager_fsmo . ntds_dn_str = ldb_msg_find_attr_as_string ( r - > msgs [ 0 ] , " fSMORoleOwner " , NULL ) ;
2006-12-04 13:02:08 +03:00
if ( ! s - > rid_manager_fsmo . ntds_dn_str ) return NT_STATUS_INVALID_NETWORK_RESPONSE ;
talloc_steal ( s , s - > rid_manager_fsmo . ntds_dn_str ) ;
talloc_free ( r ) ;
ntds_dn = ldb_dn_new ( s , s - > ldap1 . ldb , s - > rid_manager_fsmo . ntds_dn_str ) ;
NT_STATUS_HAVE_NO_MEMORY ( ntds_dn ) ;
server_dn = ldb_dn_get_parent ( s , ntds_dn ) ;
NT_STATUS_HAVE_NO_MEMORY ( server_dn ) ;
s - > rid_manager_fsmo . server_dn_str = ldb_dn_alloc_linearized ( s , server_dn ) ;
NT_STATUS_HAVE_NO_MEMORY ( s - > rid_manager_fsmo . server_dn_str ) ;
2008-09-23 22:30:06 +04:00
ret = ldb_search ( s - > ldap1 . ldb , s , & r , server_dn , LDB_SCOPE_BASE ,
dns_attrs , " (objectClass=*) " ) ;
2006-12-04 13:02:08 +03:00
if ( ret ! = LDB_SUCCESS ) {
return NT_STATUS_LDAP ( ret ) ;
} else if ( r - > count ! = 1 ) {
talloc_free ( r ) ;
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
2010-10-14 11:41:42 +04:00
s - > rid_manager_fsmo . dns_name = ldb_msg_find_attr_as_string ( r - > msgs [ 0 ] , " dnsHostName " , NULL ) ;
2006-12-04 13:02:08 +03:00
if ( ! s - > rid_manager_fsmo . dns_name ) return NT_STATUS_INVALID_NETWORK_RESPONSE ;
talloc_steal ( s , s - > rid_manager_fsmo . dns_name ) ;
talloc_free ( r ) ;
2008-09-23 22:30:06 +04:00
ret = ldb_search ( s - > ldap1 . ldb , s , & r , ntds_dn , LDB_SCOPE_BASE ,
guid_attrs , " (objectClass=*) " ) ;
2006-12-04 13:02:08 +03:00
if ( ret ! = LDB_SUCCESS ) {
return NT_STATUS_LDAP ( ret ) ;
} else if ( r - > count ! = 1 ) {
talloc_free ( r ) ;
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
s - > rid_manager_fsmo . ntds_guid = samdb_result_guid ( r - > msgs [ 0 ] , " objectGUID " ) ;
talloc_free ( r ) ;
return NT_STATUS_OK ;
2006-12-04 00:05:18 +03:00
}
2006-12-04 19:30:27 +03:00
static NTSTATUS becomeDC_ldap1_site_object ( struct libnet_BecomeDC_state * s )
{
int ret ;
struct ldb_result * r ;
struct ldb_dn * basedn ;
basedn = ldb_dn_new_fmt ( s , s - > ldap1 . ldb , " CN=%s,CN=Sites,%s " ,
s - > dest_dsa . site_name ,
s - > forest . config_dn_str ) ;
NT_STATUS_HAVE_NO_MEMORY ( basedn ) ;
2008-09-23 22:30:06 +04:00
ret = ldb_search ( s - > ldap1 . ldb , s , & r , basedn , LDB_SCOPE_BASE ,
NULL , " (objectClass=*) " ) ;
2006-12-04 19:30:27 +03:00
talloc_free ( basedn ) ;
if ( ret ! = LDB_SUCCESS ) {
return NT_STATUS_LDAP ( ret ) ;
} else if ( r - > count ! = 1 ) {
talloc_free ( r ) ;
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
2006-12-04 20:27:46 +03:00
s - > dest_dsa . site_guid = samdb_result_guid ( r - > msgs [ 0 ] , " objectGUID " ) ;
2006-12-04 19:30:27 +03:00
talloc_free ( r ) ;
return NT_STATUS_OK ;
}
2006-12-20 17:49:40 +03:00
static NTSTATUS becomeDC_check_options ( struct libnet_BecomeDC_state * s )
{
if ( ! s - > callbacks . check_options ) return NT_STATUS_OK ;
2006-12-20 19:34:35 +03:00
s - > _co . domain = & s - > domain ;
s - > _co . forest = & s - > forest ;
s - > _co . source_dsa = & s - > source_dsa ;
return s - > callbacks . check_options ( s - > callbacks . private_data , & s - > _co ) ;
2006-12-20 17:49:40 +03:00
}
2006-12-04 20:27:46 +03:00
static NTSTATUS becomeDC_ldap1_computer_object ( struct libnet_BecomeDC_state * s )
{
int ret ;
struct ldb_result * r ;
struct ldb_dn * basedn ;
2007-12-20 02:02:15 +03:00
static const char * attrs [ ] = {
2006-12-04 20:27:46 +03:00
" distinguishedName " ,
" userAccountControl " ,
NULL
} ;
basedn = ldb_dn_new ( s , s - > ldap1 . ldb , s - > domain . dn_str ) ;
NT_STATUS_HAVE_NO_MEMORY ( basedn ) ;
2008-09-23 22:30:06 +04:00
ret = ldb_search ( s - > ldap1 . ldb , s , & r , basedn , LDB_SCOPE_SUBTREE , attrs ,
" (&(|(objectClass=user)(objectClass=computer))(sAMAccountName=%s$)) " ,
s - > dest_dsa . netbios_name ) ;
2006-12-04 20:27:46 +03:00
talloc_free ( basedn ) ;
if ( ret ! = LDB_SUCCESS ) {
return NT_STATUS_LDAP ( ret ) ;
} else if ( r - > count ! = 1 ) {
talloc_free ( r ) ;
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
2010-10-14 11:41:42 +04:00
s - > dest_dsa . computer_dn_str = ldb_msg_find_attr_as_string ( r - > msgs [ 0 ] , " distinguishedName " , NULL ) ;
2006-12-04 20:27:46 +03:00
if ( ! s - > dest_dsa . computer_dn_str ) return NT_STATUS_INVALID_NETWORK_RESPONSE ;
talloc_steal ( s , s - > dest_dsa . computer_dn_str ) ;
2010-10-14 11:41:42 +04:00
s - > dest_dsa . user_account_control = ldb_msg_find_attr_as_uint ( r - > msgs [ 0 ] , " userAccountControl " , 0 ) ;
2006-12-04 20:27:46 +03:00
talloc_free ( r ) ;
return NT_STATUS_OK ;
}
2006-12-03 23:37:44 +03:00
2006-12-04 21:20:03 +03:00
static NTSTATUS becomeDC_ldap1_server_object_1 ( struct libnet_BecomeDC_state * s )
{
int ret ;
struct ldb_result * r ;
struct ldb_dn * basedn ;
const char * server_reference_dn_str ;
struct ldb_dn * server_reference_dn ;
struct ldb_dn * computer_dn ;
basedn = ldb_dn_new_fmt ( s , s - > ldap1 . ldb , " CN=%s,CN=Servers,CN=%s,CN=Sites,%s " ,
s - > dest_dsa . netbios_name ,
s - > dest_dsa . site_name ,
s - > forest . config_dn_str ) ;
NT_STATUS_HAVE_NO_MEMORY ( basedn ) ;
2008-09-23 22:30:06 +04:00
ret = ldb_search ( s - > ldap1 . ldb , s , & r , basedn , LDB_SCOPE_BASE ,
NULL , " (objectClass=*) " ) ;
2006-12-04 21:20:03 +03:00
talloc_free ( basedn ) ;
if ( ret = = LDB_ERR_NO_SUCH_OBJECT ) {
/* if the object doesn't exist, we'll create it later */
return NT_STATUS_OK ;
} else if ( ret ! = LDB_SUCCESS ) {
return NT_STATUS_LDAP ( ret ) ;
} else if ( r - > count ! = 1 ) {
talloc_free ( r ) ;
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
2010-10-14 11:41:42 +04:00
server_reference_dn_str = ldb_msg_find_attr_as_string ( r - > msgs [ 0 ] , " serverReference " , NULL ) ;
2006-12-06 15:08:32 +03:00
if ( server_reference_dn_str ) {
server_reference_dn = ldb_dn_new ( r , s - > ldap1 . ldb , server_reference_dn_str ) ;
NT_STATUS_HAVE_NO_MEMORY ( server_reference_dn ) ;
computer_dn = ldb_dn_new ( r , s - > ldap1 . ldb , s - > dest_dsa . computer_dn_str ) ;
NT_STATUS_HAVE_NO_MEMORY ( computer_dn ) ;
/*
2009-09-25 12:44:19 +04:00
* if the server object belongs to another DC in another domain
* in the forest , we should not touch this object !
2006-12-06 15:08:32 +03:00
*/
if ( ldb_dn_compare ( computer_dn , server_reference_dn ) ! = 0 ) {
talloc_free ( r ) ;
return NT_STATUS_OBJECT_NAME_COLLISION ;
}
2006-12-04 21:20:03 +03:00
}
/* if the server object is already for the dest_dsa, then we don't need to create it */
2010-10-14 11:41:42 +04:00
s - > dest_dsa . server_dn_str = ldb_msg_find_attr_as_string ( r - > msgs [ 0 ] , " distinguishedName " , NULL ) ;
2006-12-04 21:20:03 +03:00
if ( ! s - > dest_dsa . server_dn_str ) return NT_STATUS_INVALID_NETWORK_RESPONSE ;
talloc_steal ( s , s - > dest_dsa . server_dn_str ) ;
talloc_free ( r ) ;
return NT_STATUS_OK ;
}
static NTSTATUS becomeDC_ldap1_server_object_2 ( struct libnet_BecomeDC_state * s )
{
int ret ;
struct ldb_result * r ;
struct ldb_dn * basedn ;
const char * server_reference_bl_dn_str ;
2007-12-20 02:02:15 +03:00
static const char * attrs [ ] = {
2006-12-04 21:20:03 +03:00
" serverReferenceBL " ,
NULL
} ;
/* if the server_dn_str has a valid value, we skip this lookup */
if ( s - > dest_dsa . server_dn_str ) return NT_STATUS_OK ;
basedn = ldb_dn_new ( s , s - > ldap1 . ldb , s - > dest_dsa . computer_dn_str ) ;
NT_STATUS_HAVE_NO_MEMORY ( basedn ) ;
2008-09-23 22:30:06 +04:00
ret = ldb_search ( s - > ldap1 . ldb , s , & r , basedn , LDB_SCOPE_BASE ,
attrs , " (objectClass=*) " ) ;
2006-12-04 21:20:03 +03:00
talloc_free ( basedn ) ;
if ( ret ! = LDB_SUCCESS ) {
return NT_STATUS_LDAP ( ret ) ;
} else if ( r - > count ! = 1 ) {
talloc_free ( r ) ;
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
2010-10-14 11:41:42 +04:00
server_reference_bl_dn_str = ldb_msg_find_attr_as_string ( r - > msgs [ 0 ] , " serverReferenceBL " , NULL ) ;
2006-12-04 21:20:03 +03:00
if ( ! server_reference_bl_dn_str ) {
/* if no back link is present, we're done for this function */
talloc_free ( r ) ;
return NT_STATUS_OK ;
}
/* if the server object is already for the dest_dsa, then we don't need to create it */
2010-10-14 11:41:42 +04:00
s - > dest_dsa . server_dn_str = ldb_msg_find_attr_as_string ( r - > msgs [ 0 ] , " serverReferenceBL " , NULL ) ;
2006-12-04 21:20:03 +03:00
if ( s - > dest_dsa . server_dn_str ) {
/* if a back link is present, we know that the server object is present */
talloc_steal ( s , s - > dest_dsa . server_dn_str ) ;
}
talloc_free ( r ) ;
return NT_STATUS_OK ;
}
static NTSTATUS becomeDC_ldap1_server_object_add ( struct libnet_BecomeDC_state * s )
{
int ret ;
struct ldb_message * msg ;
char * server_dn_str ;
/* if the server_dn_str has a valid value, we skip this lookup */
if ( s - > dest_dsa . server_dn_str ) return NT_STATUS_OK ;
msg = ldb_msg_new ( s ) ;
NT_STATUS_HAVE_NO_MEMORY ( msg ) ;
2006-12-05 18:41:41 +03:00
msg - > dn = ldb_dn_new_fmt ( msg , s - > ldap1 . ldb , " CN=%s,CN=Servers,CN=%s,CN=Sites,%s " ,
2006-12-04 21:20:03 +03:00
s - > dest_dsa . netbios_name ,
s - > dest_dsa . site_name ,
s - > forest . config_dn_str ) ;
NT_STATUS_HAVE_NO_MEMORY ( msg - > dn ) ;
ret = ldb_msg_add_string ( msg , " objectClass " , " server " ) ;
if ( ret ! = 0 ) {
talloc_free ( msg ) ;
return NT_STATUS_NO_MEMORY ;
}
ret = ldb_msg_add_string ( msg , " systemFlags " , " 50000000 " ) ;
if ( ret ! = 0 ) {
talloc_free ( msg ) ;
return NT_STATUS_NO_MEMORY ;
}
ret = ldb_msg_add_string ( msg , " serverReference " , s - > dest_dsa . computer_dn_str ) ;
if ( ret ! = 0 ) {
talloc_free ( msg ) ;
return NT_STATUS_NO_MEMORY ;
}
server_dn_str = ldb_dn_alloc_linearized ( s , msg - > dn ) ;
NT_STATUS_HAVE_NO_MEMORY ( server_dn_str ) ;
ret = ldb_add ( s - > ldap1 . ldb , msg ) ;
talloc_free ( msg ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( server_dn_str ) ;
return NT_STATUS_LDAP ( ret ) ;
}
s - > dest_dsa . server_dn_str = server_dn_str ;
return NT_STATUS_OK ;
}
2006-12-06 15:08:32 +03:00
static NTSTATUS becomeDC_ldap1_server_object_modify ( struct libnet_BecomeDC_state * s )
{
int ret ;
struct ldb_message * msg ;
2010-03-10 22:22:06 +03:00
unsigned int i ;
2006-12-06 15:08:32 +03:00
/* make a 'modify' msg, and only for serverReference */
msg = ldb_msg_new ( s ) ;
NT_STATUS_HAVE_NO_MEMORY ( msg ) ;
msg - > dn = ldb_dn_new ( msg , s - > ldap1 . ldb , s - > dest_dsa . server_dn_str ) ;
NT_STATUS_HAVE_NO_MEMORY ( msg - > dn ) ;
ret = ldb_msg_add_string ( msg , " serverReference " , s - > dest_dsa . computer_dn_str ) ;
if ( ret ! = 0 ) {
talloc_free ( msg ) ;
return NT_STATUS_NO_MEMORY ;
}
/* mark all the message elements (should be just one)
as LDB_FLAG_MOD_ADD */
for ( i = 0 ; i < msg - > num_elements ; i + + ) {
msg - > elements [ i ] . flags = LDB_FLAG_MOD_ADD ;
}
ret = ldb_modify ( s - > ldap1 . ldb , msg ) ;
if ( ret = = LDB_SUCCESS ) {
talloc_free ( msg ) ;
return NT_STATUS_OK ;
} else if ( ret = = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS ) {
/* retry with LDB_FLAG_MOD_REPLACE */
} else {
talloc_free ( msg ) ;
return NT_STATUS_LDAP ( ret ) ;
}
/* mark all the message elements (should be just one)
as LDB_FLAG_MOD_REPLACE */
for ( i = 0 ; i < msg - > num_elements ; i + + ) {
msg - > elements [ i ] . flags = LDB_FLAG_MOD_REPLACE ;
}
ret = ldb_modify ( s - > ldap1 . ldb , msg ) ;
talloc_free ( msg ) ;
if ( ret ! = LDB_SUCCESS ) {
return NT_STATUS_LDAP ( ret ) ;
}
return NT_STATUS_OK ;
}
2006-12-06 15:15:07 +03:00
static void becomeDC_drsuapi_connect_send ( struct libnet_BecomeDC_state * s ,
struct becomeDC_drsuapi * drsuapi ,
void ( * recv_fn ) ( struct composite_context * req ) ) ;
static void becomeDC_drsuapi1_connect_recv ( struct composite_context * req ) ;
2006-12-05 16:46:27 +03:00
static void becomeDC_connect_ldap2 ( struct libnet_BecomeDC_state * s ) ;
2006-12-03 23:37:44 +03:00
static void becomeDC_connect_ldap1 ( struct libnet_BecomeDC_state * s )
{
struct composite_context * c = s - > creq ;
c - > status = becomeDC_ldap_connect ( s , & s - > ldap1 ) ;
if ( ! composite_is_ok ( c ) ) return ;
c - > status = becomeDC_ldap1_rootdse ( s ) ;
if ( ! composite_is_ok ( c ) ) return ;
2006-12-20 19:34:35 +03:00
c - > status = becomeDC_ldap1_crossref_behavior_version ( s ) ;
2006-12-03 23:37:44 +03:00
if ( ! composite_is_ok ( c ) ) return ;
c - > status = becomeDC_ldap1_domain_behavior_version ( s ) ;
if ( ! composite_is_ok ( c ) ) return ;
c - > status = becomeDC_ldap1_schema_object_version ( s ) ;
if ( ! composite_is_ok ( c ) ) return ;
2006-12-04 12:40:16 +03:00
c - > status = becomeDC_ldap1_w2k3_update_revision ( s ) ;
if ( ! composite_is_ok ( c ) ) return ;
2006-12-04 00:05:18 +03:00
c - > status = becomeDC_ldap1_infrastructure_fsmo ( s ) ;
if ( ! composite_is_ok ( c ) ) return ;
2006-12-04 13:02:08 +03:00
c - > status = becomeDC_ldap1_rid_manager_fsmo ( s ) ;
if ( ! composite_is_ok ( c ) ) return ;
2006-12-04 19:30:27 +03:00
c - > status = becomeDC_ldap1_site_object ( s ) ;
if ( ! composite_is_ok ( c ) ) return ;
2006-12-20 17:49:40 +03:00
c - > status = becomeDC_check_options ( s ) ;
if ( ! composite_is_ok ( c ) ) return ;
2006-12-04 20:27:46 +03:00
c - > status = becomeDC_ldap1_computer_object ( s ) ;
if ( ! composite_is_ok ( c ) ) return ;
2006-12-04 21:20:03 +03:00
c - > status = becomeDC_ldap1_server_object_1 ( s ) ;
if ( ! composite_is_ok ( c ) ) return ;
c - > status = becomeDC_ldap1_server_object_2 ( s ) ;
if ( ! composite_is_ok ( c ) ) return ;
c - > status = becomeDC_ldap1_server_object_add ( s ) ;
2006-12-05 18:41:41 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2006-12-05 16:46:27 +03:00
2006-12-06 15:08:32 +03:00
c - > status = becomeDC_ldap1_server_object_modify ( s ) ;
if ( ! composite_is_ok ( c ) ) return ;
2006-12-06 15:15:07 +03:00
becomeDC_drsuapi_connect_send ( s , & s - > drsuapi1 , becomeDC_drsuapi1_connect_recv ) ;
}
static void becomeDC_drsuapi_connect_send ( struct libnet_BecomeDC_state * s ,
struct becomeDC_drsuapi * drsuapi ,
void ( * recv_fn ) ( struct composite_context * req ) )
{
struct composite_context * c = s - > creq ;
struct composite_context * creq ;
char * binding_str ;
drsuapi - > s = s ;
2006-12-07 22:50:46 +03:00
if ( ! drsuapi - > binding ) {
2008-12-24 00:11:21 +03:00
const char * krb5_str = " " ;
const char * print_str = " " ;
2008-07-17 15:36:59 +04:00
/*
2008-07-23 19:54:25 +04:00
* Note : Replication only works with Windows 2000 when ' krb5 ' is
* passed as auth_type here . If NTLMSSP is used , Windows
* 2000 returns garbage in the DsGetNCChanges ( ) response
2009-09-25 12:44:19 +04:00
* if encrypted password attributes would be in the
* response . That means the replication of the schema and
* configuration partition works fine , but it fails for
* the domain partition .
2008-07-17 15:36:59 +04:00
*/
2010-07-16 08:32:42 +04:00
if ( lpcfg_parm_bool ( s - > libnet - > lp_ctx , NULL , " become_dc " ,
2008-07-23 19:54:25 +04:00
" force krb5 " , true ) )
{
krb5_str = " krb5, " ;
2007-02-12 12:53:52 +03:00
}
2010-07-16 08:32:42 +04:00
if ( lpcfg_parm_bool ( s - > libnet - > lp_ctx , NULL , " become_dc " ,
2008-07-23 19:54:25 +04:00
" print " , false ) )
{
print_str = " print, " ;
}
2014-02-04 12:59:54 +04:00
binding_str = talloc_asprintf ( s , " ncacn_ip_tcp:%s[%s%sseal,target_hostname=%s] " ,
s - > source_dsa . address ,
krb5_str , print_str ,
s - > source_dsa . dns_name ) ;
2008-07-23 19:54:25 +04:00
if ( composite_nomem ( binding_str , c ) ) return ;
2006-12-07 22:50:46 +03:00
c - > status = dcerpc_parse_binding ( s , binding_str , & drsuapi - > binding ) ;
talloc_free ( binding_str ) ;
if ( ! composite_is_ok ( c ) ) return ;
}
2006-12-06 15:15:07 +03:00
2011-04-01 08:56:58 +04:00
if ( DEBUGLEVEL > = 10 ) {
2014-02-04 12:57:07 +04:00
c - > status = dcerpc_binding_set_flags ( drsuapi - > binding ,
DCERPC_DEBUG_PRINT_BOTH ,
0 ) ;
if ( ! composite_is_ok ( c ) ) return ;
2011-04-01 08:56:58 +04:00
}
2007-08-20 01:23:03 +04:00
creq = dcerpc_pipe_connect_b_send ( s , drsuapi - > binding , & ndr_table_drsuapi ,
2007-12-07 04:37:04 +03:00
s - > libnet - > cred , s - > libnet - > event_ctx ,
s - > libnet - > lp_ctx ) ;
2006-12-06 15:15:07 +03:00
composite_continue ( c , creq , recv_fn , s ) ;
}
2006-12-06 15:25:41 +03:00
static void becomeDC_drsuapi_bind_send ( struct libnet_BecomeDC_state * s ,
struct becomeDC_drsuapi * drsuapi ,
2010-03-08 18:41:43 +03:00
void ( * recv_fn ) ( struct tevent_req * subreq ) ) ;
static void becomeDC_drsuapi1_bind_recv ( struct tevent_req * subreq ) ;
2006-12-06 15:25:41 +03:00
2006-12-06 15:15:07 +03:00
static void becomeDC_drsuapi1_connect_recv ( struct composite_context * req )
{
struct libnet_BecomeDC_state * s = talloc_get_type ( req - > async . private_data ,
struct libnet_BecomeDC_state ) ;
struct composite_context * c = s - > creq ;
c - > status = dcerpc_pipe_connect_b_recv ( req , s , & s - > drsuapi1 . pipe ) ;
if ( ! composite_is_ok ( c ) ) return ;
2010-03-08 18:41:43 +03:00
s - > drsuapi1 . drsuapi_handle = s - > drsuapi1 . pipe - > binding_handle ;
2007-02-12 13:58:06 +03:00
c - > status = gensec_session_key ( s - > drsuapi1 . pipe - > conn - > security_state . generic_state ,
2011-08-01 09:39:01 +04:00
s ,
2007-02-12 13:58:06 +03:00
& s - > drsuapi1 . gensec_skey ) ;
if ( ! composite_is_ok ( c ) ) return ;
2006-12-06 15:25:41 +03:00
becomeDC_drsuapi_bind_send ( s , & s - > drsuapi1 , becomeDC_drsuapi1_bind_recv ) ;
}
static void becomeDC_drsuapi_bind_send ( struct libnet_BecomeDC_state * s ,
struct becomeDC_drsuapi * drsuapi ,
2010-03-08 18:41:43 +03:00
void ( * recv_fn ) ( struct tevent_req * subreq ) )
2006-12-06 15:25:41 +03:00
{
struct composite_context * c = s - > creq ;
2006-12-06 19:04:43 +03:00
struct drsuapi_DsBindInfo28 * bind_info28 ;
2010-03-08 18:41:43 +03:00
struct tevent_req * subreq ;
2006-12-06 15:25:41 +03:00
GUID_from_string ( DRSUAPI_DS_BIND_GUID_W2K3 , & drsuapi - > bind_guid ) ;
2006-12-06 19:04:43 +03:00
bind_info28 = & drsuapi - > local_info28 ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_BASE ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2 ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1 ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2 ;
2009-09-25 12:44:19 +04:00
if ( s - > domain . behavior_version > = DS_DOMAIN_FUNCTION_2003 ) {
2006-12-06 19:04:43 +03:00
/* TODO: find out how this is really triggered! */
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION ;
}
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2 ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01 ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3 ;
2010-02-02 15:28:57 +03:00
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V5 ;
2006-12-06 19:04:43 +03:00
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2 ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6 ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8 ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5 ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6 ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3 ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7 ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT ;
#if 0 /* we don't support XPRESS compression yet */
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS ;
# endif
bind_info28 - > site_guid = s - > dest_dsa . site_guid ;
2008-07-23 17:34:45 +04:00
bind_info28 - > pid = 0 ;
2006-12-06 19:04:43 +03:00
bind_info28 - > repl_epoch = 0 ;
drsuapi - > bind_info_ctr . length = 28 ;
drsuapi - > bind_info_ctr . info . info28 = * bind_info28 ;
2006-12-06 15:25:41 +03:00
drsuapi - > bind_r . in . bind_guid = & drsuapi - > bind_guid ;
2006-12-06 19:04:43 +03:00
drsuapi - > bind_r . in . bind_info = & drsuapi - > bind_info_ctr ;
2006-12-06 15:25:41 +03:00
drsuapi - > bind_r . out . bind_handle = & drsuapi - > bind_handle ;
2010-03-08 18:41:43 +03:00
subreq = dcerpc_drsuapi_DsBind_r_send ( s , c - > event_ctx ,
drsuapi - > drsuapi_handle ,
& drsuapi - > bind_r ) ;
if ( composite_nomem ( subreq , c ) ) return ;
tevent_req_set_callback ( subreq , recv_fn , s ) ;
2006-12-06 15:25:41 +03:00
}
2006-12-07 23:11:00 +03:00
static WERROR becomeDC_drsuapi_bind_recv ( struct libnet_BecomeDC_state * s ,
struct becomeDC_drsuapi * drsuapi )
{
if ( ! W_ERROR_IS_OK ( drsuapi - > bind_r . out . result ) ) {
return drsuapi - > bind_r . out . result ;
}
ZERO_STRUCT ( drsuapi - > remote_info28 ) ;
if ( drsuapi - > bind_r . out . bind_info ) {
switch ( drsuapi - > bind_r . out . bind_info - > length ) {
case 24 : {
struct drsuapi_DsBindInfo24 * info24 ;
info24 = & drsuapi - > bind_r . out . bind_info - > info . info24 ;
drsuapi - > remote_info28 . supported_extensions = info24 - > supported_extensions ;
drsuapi - > remote_info28 . site_guid = info24 - > site_guid ;
2008-07-22 17:35:23 +04:00
drsuapi - > remote_info28 . pid = info24 - > pid ;
2006-12-07 23:11:00 +03:00
drsuapi - > remote_info28 . repl_epoch = 0 ;
break ;
}
2014-07-04 14:45:59 +04:00
case 28 : {
2006-12-07 23:11:00 +03:00
drsuapi - > remote_info28 = drsuapi - > bind_r . out . bind_info - > info . info28 ;
break ;
}
2014-07-04 14:45:59 +04:00
case 32 : {
struct drsuapi_DsBindInfo32 * info32 ;
info32 = & drsuapi - > bind_r . out . bind_info - > info . info32 ;
drsuapi - > remote_info28 . supported_extensions = info32 - > supported_extensions ;
drsuapi - > remote_info28 . site_guid = info32 - > site_guid ;
drsuapi - > remote_info28 . pid = info32 - > pid ;
drsuapi - > remote_info28 . repl_epoch = info32 - > repl_epoch ;
break ;
}
2014-07-07 00:02:42 +04:00
case 48 : {
struct drsuapi_DsBindInfo48 * info48 ;
info48 = & drsuapi - > bind_r . out . bind_info - > info . info48 ;
drsuapi - > remote_info28 . supported_extensions = info48 - > supported_extensions ;
drsuapi - > remote_info28 . site_guid = info48 - > site_guid ;
drsuapi - > remote_info28 . pid = info48 - > pid ;
drsuapi - > remote_info28 . repl_epoch = info48 - > repl_epoch ;
break ;
}
2014-07-04 14:45:59 +04:00
case 52 : {
struct drsuapi_DsBindInfo52 * info52 ;
info52 = & drsuapi - > bind_r . out . bind_info - > info . info52 ;
drsuapi - > remote_info28 . supported_extensions = info52 - > supported_extensions ;
drsuapi - > remote_info28 . site_guid = info52 - > site_guid ;
drsuapi - > remote_info28 . pid = info52 - > pid ;
drsuapi - > remote_info28 . repl_epoch = info52 - > repl_epoch ;
break ;
}
default :
DEBUG ( 1 , ( " Warning: invalid info length in bind info: %d \n " ,
drsuapi - > bind_r . out . bind_info - > length ) ) ;
break ;
}
2006-12-07 23:11:00 +03:00
}
return WERR_OK ;
}
2006-12-06 18:29:01 +03:00
static void becomeDC_drsuapi1_add_entry_send ( struct libnet_BecomeDC_state * s ) ;
2010-03-08 18:41:43 +03:00
static void becomeDC_drsuapi1_bind_recv ( struct tevent_req * subreq )
2006-12-06 15:25:41 +03:00
{
2010-03-08 18:41:43 +03:00
struct libnet_BecomeDC_state * s = tevent_req_callback_data ( subreq ,
2006-12-06 15:25:41 +03:00
struct libnet_BecomeDC_state ) ;
struct composite_context * c = s - > creq ;
2006-12-07 23:11:00 +03:00
WERROR status ;
2006-12-06 15:25:41 +03:00
2010-03-08 18:41:43 +03:00
c - > status = dcerpc_drsuapi_DsBind_r_recv ( subreq , s ) ;
TALLOC_FREE ( subreq ) ;
2006-12-06 15:25:41 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2006-12-07 23:11:00 +03:00
status = becomeDC_drsuapi_bind_recv ( s , & s - > drsuapi1 ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
composite_error ( c , werror_to_ntstatus ( status ) ) ;
2006-12-06 15:25:41 +03:00
return ;
}
2006-12-06 18:29:01 +03:00
becomeDC_drsuapi1_add_entry_send ( s ) ;
}
2010-03-08 18:41:43 +03:00
static void becomeDC_drsuapi1_add_entry_recv ( struct tevent_req * subreq ) ;
2006-12-06 18:29:01 +03:00
static void becomeDC_drsuapi1_add_entry_send ( struct libnet_BecomeDC_state * s )
{
struct composite_context * c = s - > creq ;
struct drsuapi_DsAddEntry * r ;
struct drsuapi_DsReplicaObjectIdentifier * identifier ;
2006-12-07 13:04:35 +03:00
uint32_t num_attrs , i = 0 ;
struct drsuapi_DsReplicaAttribute * attrs ;
2007-11-09 21:24:51 +03:00
enum ndr_err_code ndr_err ;
2006-12-11 20:04:43 +03:00
bool w2k3 ;
2010-03-08 18:41:43 +03:00
struct tevent_req * subreq ;
2006-12-06 18:29:01 +03:00
2006-12-07 13:04:35 +03:00
/* choose a random invocationId */
s - > dest_dsa . invocation_id = GUID_random ( ) ;
2006-12-11 20:04:43 +03:00
/*
2009-09-25 12:44:19 +04:00
* if the schema version indicates w2k3 , then also send some w2k3
* specific attributes .
2006-12-11 20:04:43 +03:00
*/
2006-12-20 19:34:35 +03:00
if ( s - > forest . schema_object_version > = 30 ) {
2006-12-11 20:04:43 +03:00
w2k3 = true ;
} else {
w2k3 = false ;
}
2006-12-06 18:29:01 +03:00
r = talloc_zero ( s , struct drsuapi_DsAddEntry ) ;
if ( composite_nomem ( r , c ) ) return ;
/* setup identifier */
identifier = talloc ( r , struct drsuapi_DsReplicaObjectIdentifier ) ;
if ( composite_nomem ( identifier , c ) ) return ;
identifier - > guid = GUID_zero ( ) ;
2006-12-07 18:33:24 +03:00
identifier - > sid = s - > zero_sid ;
2006-12-06 18:29:01 +03:00
identifier - > dn = talloc_asprintf ( identifier , " CN=NTDS Settings,%s " ,
s - > dest_dsa . server_dn_str ) ;
if ( composite_nomem ( identifier - > dn , c ) ) return ;
/* allocate attribute array */
2010-02-17 19:01:31 +03:00
num_attrs = 12 ;
2006-12-07 13:04:35 +03:00
attrs = talloc_array ( r , struct drsuapi_DsReplicaAttribute , num_attrs ) ;
if ( composite_nomem ( attrs , c ) ) return ;
/* ntSecurityDescriptor */
{
2007-01-03 12:58:14 +03:00
struct drsuapi_DsAttributeValue * vs ;
2006-12-30 13:51:04 +03:00
DATA_BLOB * vd ;
2006-12-07 13:04:35 +03:00
struct security_descriptor * v ;
2006-12-07 18:29:38 +03:00
struct dom_sid * domain_admins_sid ;
const char * domain_admins_sid_str ;
2006-12-07 13:04:35 +03:00
2007-01-03 12:58:14 +03:00
vs = talloc_array ( attrs , struct drsuapi_DsAttributeValue , 1 ) ;
2006-12-07 13:04:35 +03:00
if ( composite_nomem ( vs , c ) ) return ;
2006-12-30 13:51:04 +03:00
vd = talloc_array ( vs , DATA_BLOB , 1 ) ;
if ( composite_nomem ( vd , c ) ) return ;
2006-12-07 18:29:38 +03:00
domain_admins_sid = dom_sid_add_rid ( vs , s - > domain . sid , DOMAIN_RID_ADMINS ) ;
if ( composite_nomem ( domain_admins_sid , c ) ) return ;
domain_admins_sid_str = dom_sid_string ( domain_admins_sid , domain_admins_sid ) ;
if ( composite_nomem ( domain_admins_sid_str , c ) ) return ;
2007-11-02 14:54:19 +03:00
v = security_descriptor_dacl_create ( vd ,
2007-10-10 15:12:53 +04:00
0 ,
2006-12-07 18:29:38 +03:00
/* owner: domain admins */
domain_admins_sid_str ,
/* owner group: domain admins */
domain_admins_sid_str ,
/* authenticated users */
2006-12-07 13:04:35 +03:00
SID_NT_AUTHENTICATED_USERS ,
SEC_ACE_TYPE_ACCESS_ALLOWED ,
SEC_STD_READ_CONTROL |
SEC_ADS_LIST |
SEC_ADS_READ_PROP |
SEC_ADS_LIST_OBJECT ,
0 ,
2006-12-07 18:29:38 +03:00
/* domain admins */
domain_admins_sid_str ,
2006-12-07 13:04:35 +03:00
SEC_ACE_TYPE_ACCESS_ALLOWED ,
SEC_STD_REQUIRED |
SEC_ADS_CREATE_CHILD |
SEC_ADS_LIST |
SEC_ADS_SELF_WRITE |
SEC_ADS_READ_PROP |
SEC_ADS_WRITE_PROP |
SEC_ADS_DELETE_TREE |
SEC_ADS_LIST_OBJECT |
SEC_ADS_CONTROL_ACCESS ,
0 ,
2006-12-07 18:29:38 +03:00
/* system */
2006-12-07 13:04:35 +03:00
SID_NT_SYSTEM ,
SEC_ACE_TYPE_ACCESS_ALLOWED ,
SEC_STD_REQUIRED |
SEC_ADS_CREATE_CHILD |
SEC_ADS_DELETE_CHILD |
SEC_ADS_LIST |
SEC_ADS_SELF_WRITE |
SEC_ADS_READ_PROP |
SEC_ADS_WRITE_PROP |
SEC_ADS_DELETE_TREE |
SEC_ADS_LIST_OBJECT |
SEC_ADS_CONTROL_ACCESS ,
0 ,
2006-12-07 18:29:38 +03:00
/* end */
2006-12-07 13:04:35 +03:00
NULL ) ;
if ( composite_nomem ( v , c ) ) return ;
2010-05-09 19:20:01 +04:00
ndr_err = ndr_push_struct_blob ( & vd [ 0 ] , vd , v ,
( ndr_push_flags_fn_t ) ndr_push_security_descriptor ) ;
2007-11-09 21:24:51 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
c - > status = ndr_map_error2ntstatus ( ndr_err ) ;
if ( ! composite_is_ok ( c ) ) return ;
}
2006-12-30 13:51:04 +03:00
2007-01-03 12:58:14 +03:00
vs [ 0 ] . blob = & vd [ 0 ] ;
2006-12-07 13:04:35 +03:00
2010-10-29 03:22:35 +04:00
attrs [ i ] . attid = DRSUAPI_ATTID_ntSecurityDescriptor ;
2007-01-03 12:58:14 +03:00
attrs [ i ] . value_ctr . num_values = 1 ;
attrs [ i ] . value_ctr . values = vs ;
2006-12-07 13:04:35 +03:00
i + + ;
}
2010-03-01 14:10:39 +03:00
/* objectClass: nTDSDSA */
2006-12-07 13:04:35 +03:00
{
2007-01-03 12:58:14 +03:00
struct drsuapi_DsAttributeValue * vs ;
2007-01-02 17:14:35 +03:00
DATA_BLOB * vd ;
2006-12-07 13:04:35 +03:00
2007-01-03 12:58:14 +03:00
vs = talloc_array ( attrs , struct drsuapi_DsAttributeValue , 1 ) ;
2006-12-07 13:04:35 +03:00
if ( composite_nomem ( vs , c ) ) return ;
2007-01-02 17:14:35 +03:00
vd = talloc_array ( vs , DATA_BLOB , 1 ) ;
if ( composite_nomem ( vd , c ) ) return ;
vd [ 0 ] = data_blob_talloc ( vd , NULL , 4 ) ;
if ( composite_nomem ( vd [ 0 ] . data , c ) ) return ;
2006-12-07 13:04:35 +03:00
/* value for nTDSDSA */
2007-01-02 17:14:35 +03:00
SIVAL ( vd [ 0 ] . data , 0 , 0x0017002F ) ;
2006-12-07 13:04:35 +03:00
2007-01-03 12:58:14 +03:00
vs [ 0 ] . blob = & vd [ 0 ] ;
2006-12-07 13:04:35 +03:00
2010-10-29 03:22:35 +04:00
attrs [ i ] . attid = DRSUAPI_ATTID_objectClass ;
2007-01-03 12:58:14 +03:00
attrs [ i ] . value_ctr . num_values = 1 ;
attrs [ i ] . value_ctr . values = vs ;
2006-12-07 13:04:35 +03:00
i + + ;
}
2010-02-17 19:01:31 +03:00
/* objectCategory: CN=NTDS-DSA,CN=Schema,... or CN=NTDS-DSA-RO,CN=Schema,... */
2006-12-07 13:04:35 +03:00
{
2007-01-03 12:58:14 +03:00
struct drsuapi_DsAttributeValue * vs ;
2007-01-02 22:29:32 +03:00
DATA_BLOB * vd ;
struct drsuapi_DsReplicaObjectIdentifier3 v [ 1 ] ;
2006-12-07 13:04:35 +03:00
2007-01-03 12:58:14 +03:00
vs = talloc_array ( attrs , struct drsuapi_DsAttributeValue , 1 ) ;
2006-12-07 13:04:35 +03:00
if ( composite_nomem ( vs , c ) ) return ;
2007-01-02 22:29:32 +03:00
vd = talloc_array ( vs , DATA_BLOB , 1 ) ;
if ( composite_nomem ( vd , c ) ) return ;
2006-12-07 13:04:35 +03:00
v [ 0 ] . guid = GUID_zero ( ) ;
2006-12-07 18:33:24 +03:00
v [ 0 ] . sid = s - > zero_sid ;
2010-02-17 19:01:31 +03:00
if ( s - > rodc_join ) {
v [ 0 ] . dn = talloc_asprintf ( vd , " CN=NTDS-DSA-RO,%s " ,
2006-12-07 13:04:35 +03:00
s - > forest . schema_dn_str ) ;
2010-02-17 19:01:31 +03:00
} else {
v [ 0 ] . dn = talloc_asprintf ( vd , " CN=NTDS-DSA,%s " ,
s - > forest . schema_dn_str ) ;
}
2007-02-26 14:49:32 +03:00
if ( composite_nomem ( v [ 0 ] . dn , c ) ) return ;
2006-12-07 13:04:35 +03:00
2010-05-09 19:20:01 +04:00
ndr_err = ndr_push_struct_blob ( & vd [ 0 ] , vd , & v [ 0 ] ,
( ndr_push_flags_fn_t ) ndr_push_drsuapi_DsReplicaObjectIdentifier3 ) ;
2007-11-09 21:24:51 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
c - > status = ndr_map_error2ntstatus ( ndr_err ) ;
if ( ! composite_is_ok ( c ) ) return ;
}
2007-01-02 22:29:32 +03:00
2007-01-03 12:58:14 +03:00
vs [ 0 ] . blob = & vd [ 0 ] ;
2006-12-07 13:04:35 +03:00
2010-10-29 03:22:35 +04:00
attrs [ i ] . attid = DRSUAPI_ATTID_objectCategory ;
2007-01-03 12:58:14 +03:00
attrs [ i ] . value_ctr . num_values = 1 ;
attrs [ i ] . value_ctr . values = vs ;
2006-12-07 13:04:35 +03:00
i + + ;
}
/* invocationId: random guid */
{
2007-01-03 12:58:14 +03:00
struct drsuapi_DsAttributeValue * vs ;
2007-01-02 16:54:37 +03:00
DATA_BLOB * vd ;
const struct GUID * v ;
2006-12-07 13:04:35 +03:00
2007-01-03 12:58:14 +03:00
vs = talloc_array ( attrs , struct drsuapi_DsAttributeValue , 1 ) ;
2006-12-07 13:04:35 +03:00
if ( composite_nomem ( vs , c ) ) return ;
2007-01-02 16:54:37 +03:00
vd = talloc_array ( vs , DATA_BLOB , 1 ) ;
if ( composite_nomem ( vd , c ) ) return ;
2006-12-07 13:04:35 +03:00
2007-01-02 16:54:37 +03:00
v = & s - > dest_dsa . invocation_id ;
2006-12-07 13:04:35 +03:00
2009-12-10 06:32:29 +03:00
c - > status = GUID_to_ndr_blob ( v , vd , & vd [ 0 ] ) ;
2009-12-11 13:17:37 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2007-01-02 16:54:37 +03:00
2007-01-03 12:58:14 +03:00
vs [ 0 ] . blob = & vd [ 0 ] ;
2006-12-07 13:04:35 +03:00
2010-10-29 03:22:35 +04:00
attrs [ i ] . attid = DRSUAPI_ATTID_invocationId ;
2007-01-03 12:58:14 +03:00
attrs [ i ] . value_ctr . num_values = 1 ;
attrs [ i ] . value_ctr . values = vs ;
2006-12-07 13:04:35 +03:00
i + + ;
}
/* hasMasterNCs: ... */
{
2007-01-03 12:58:14 +03:00
struct drsuapi_DsAttributeValue * vs ;
2007-01-02 22:29:32 +03:00
DATA_BLOB * vd ;
struct drsuapi_DsReplicaObjectIdentifier3 v [ 3 ] ;
2006-12-07 13:04:35 +03:00
2007-01-03 12:58:14 +03:00
vs = talloc_array ( attrs , struct drsuapi_DsAttributeValue , 3 ) ;
2006-12-07 13:04:35 +03:00
if ( composite_nomem ( vs , c ) ) return ;
2007-01-02 22:29:32 +03:00
vd = talloc_array ( vs , DATA_BLOB , 3 ) ;
if ( composite_nomem ( vd , c ) ) return ;
2006-12-07 13:04:35 +03:00
v [ 0 ] . guid = GUID_zero ( ) ;
2006-12-07 18:33:24 +03:00
v [ 0 ] . sid = s - > zero_sid ;
2006-12-07 13:04:35 +03:00
v [ 0 ] . dn = s - > forest . config_dn_str ;
v [ 1 ] . guid = GUID_zero ( ) ;
2006-12-07 18:33:24 +03:00
v [ 1 ] . sid = s - > zero_sid ;
2006-12-07 13:04:35 +03:00
v [ 1 ] . dn = s - > domain . dn_str ;
v [ 2 ] . guid = GUID_zero ( ) ;
2006-12-07 18:33:24 +03:00
v [ 2 ] . sid = s - > zero_sid ;
2006-12-07 13:04:35 +03:00
v [ 2 ] . dn = s - > forest . schema_dn_str ;
2010-05-09 19:20:01 +04:00
ndr_err = ndr_push_struct_blob ( & vd [ 0 ] , vd , & v [ 0 ] ,
( ndr_push_flags_fn_t ) ndr_push_drsuapi_DsReplicaObjectIdentifier3 ) ;
2007-11-09 21:24:51 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
c - > status = ndr_map_error2ntstatus ( ndr_err ) ;
if ( ! composite_is_ok ( c ) ) return ;
}
2007-01-02 22:29:32 +03:00
2010-05-09 19:20:01 +04:00
ndr_err = ndr_push_struct_blob ( & vd [ 1 ] , vd , & v [ 1 ] ,
( ndr_push_flags_fn_t ) ndr_push_drsuapi_DsReplicaObjectIdentifier3 ) ;
2007-11-09 21:24:51 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
c - > status = ndr_map_error2ntstatus ( ndr_err ) ;
if ( ! composite_is_ok ( c ) ) return ;
}
2007-01-02 22:29:32 +03:00
2010-05-09 19:20:01 +04:00
ndr_err = ndr_push_struct_blob ( & vd [ 2 ] , vd , & v [ 2 ] ,
( ndr_push_flags_fn_t ) ndr_push_drsuapi_DsReplicaObjectIdentifier3 ) ;
2007-11-09 21:24:51 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
c - > status = ndr_map_error2ntstatus ( ndr_err ) ;
if ( ! composite_is_ok ( c ) ) return ;
}
2007-01-02 22:29:32 +03:00
2007-01-03 12:58:14 +03:00
vs [ 0 ] . blob = & vd [ 0 ] ;
vs [ 1 ] . blob = & vd [ 1 ] ;
vs [ 2 ] . blob = & vd [ 2 ] ;
2006-12-07 13:04:35 +03:00
2010-10-29 03:22:35 +04:00
attrs [ i ] . attid = DRSUAPI_ATTID_hasMasterNCs ;
2007-01-03 12:58:14 +03:00
attrs [ i ] . value_ctr . num_values = 3 ;
attrs [ i ] . value_ctr . values = vs ;
2006-12-07 13:04:35 +03:00
i + + ;
}
/* msDS-hasMasterNCs: ... */
2006-12-11 20:04:43 +03:00
if ( w2k3 ) {
2007-01-03 12:58:14 +03:00
struct drsuapi_DsAttributeValue * vs ;
2007-01-02 22:29:32 +03:00
DATA_BLOB * vd ;
struct drsuapi_DsReplicaObjectIdentifier3 v [ 3 ] ;
2006-12-07 13:04:35 +03:00
2007-01-03 12:58:14 +03:00
vs = talloc_array ( attrs , struct drsuapi_DsAttributeValue , 3 ) ;
2006-12-07 13:04:35 +03:00
if ( composite_nomem ( vs , c ) ) return ;
2007-01-02 22:29:32 +03:00
vd = talloc_array ( vs , DATA_BLOB , 3 ) ;
if ( composite_nomem ( vd , c ) ) return ;
2006-12-07 13:04:35 +03:00
v [ 0 ] . guid = GUID_zero ( ) ;
2006-12-07 18:33:24 +03:00
v [ 0 ] . sid = s - > zero_sid ;
2006-12-07 13:04:35 +03:00
v [ 0 ] . dn = s - > forest . config_dn_str ;
v [ 1 ] . guid = GUID_zero ( ) ;
2006-12-07 18:33:24 +03:00
v [ 1 ] . sid = s - > zero_sid ;
2006-12-07 13:04:35 +03:00
v [ 1 ] . dn = s - > domain . dn_str ;
v [ 2 ] . guid = GUID_zero ( ) ;
2006-12-07 18:33:24 +03:00
v [ 2 ] . sid = s - > zero_sid ;
2006-12-07 13:04:35 +03:00
v [ 2 ] . dn = s - > forest . schema_dn_str ;
2010-05-09 19:20:01 +04:00
ndr_err = ndr_push_struct_blob ( & vd [ 0 ] , vd , & v [ 0 ] ,
( ndr_push_flags_fn_t ) ndr_push_drsuapi_DsReplicaObjectIdentifier3 ) ;
2007-11-09 21:24:51 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
c - > status = ndr_map_error2ntstatus ( ndr_err ) ;
if ( ! composite_is_ok ( c ) ) return ;
}
2007-01-02 22:29:32 +03:00
2010-05-09 19:20:01 +04:00
ndr_err = ndr_push_struct_blob ( & vd [ 1 ] , vd , & v [ 1 ] ,
( ndr_push_flags_fn_t ) ndr_push_drsuapi_DsReplicaObjectIdentifier3 ) ;
2007-11-09 21:24:51 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
c - > status = ndr_map_error2ntstatus ( ndr_err ) ;
if ( ! composite_is_ok ( c ) ) return ;
}
2007-01-02 22:29:32 +03:00
2010-05-09 19:20:01 +04:00
ndr_err = ndr_push_struct_blob ( & vd [ 2 ] , vd , & v [ 2 ] ,
( ndr_push_flags_fn_t ) ndr_push_drsuapi_DsReplicaObjectIdentifier3 ) ;
2007-11-09 21:24:51 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
c - > status = ndr_map_error2ntstatus ( ndr_err ) ;
if ( ! composite_is_ok ( c ) ) return ;
}
2007-01-02 22:29:32 +03:00
2007-01-03 12:58:14 +03:00
vs [ 0 ] . blob = & vd [ 0 ] ;
vs [ 1 ] . blob = & vd [ 1 ] ;
vs [ 2 ] . blob = & vd [ 2 ] ;
2006-12-07 13:04:35 +03:00
2010-10-29 03:22:35 +04:00
attrs [ i ] . attid = DRSUAPI_ATTID_msDS_hasMasterNCs ;
2007-01-03 12:58:14 +03:00
attrs [ i ] . value_ctr . num_values = 3 ;
attrs [ i ] . value_ctr . values = vs ;
2006-12-07 13:04:35 +03:00
i + + ;
}
/* dMDLocation: CN=Schema,... */
{
2007-01-03 12:58:14 +03:00
struct drsuapi_DsAttributeValue * vs ;
2007-01-02 22:29:32 +03:00
DATA_BLOB * vd ;
struct drsuapi_DsReplicaObjectIdentifier3 v [ 1 ] ;
2006-12-07 13:04:35 +03:00
2007-01-03 12:58:14 +03:00
vs = talloc_array ( attrs , struct drsuapi_DsAttributeValue , 1 ) ;
2006-12-07 13:04:35 +03:00
if ( composite_nomem ( vs , c ) ) return ;
2007-01-02 22:29:32 +03:00
vd = talloc_array ( vs , DATA_BLOB , 1 ) ;
if ( composite_nomem ( vd , c ) ) return ;
2006-12-07 13:04:35 +03:00
v [ 0 ] . guid = GUID_zero ( ) ;
2006-12-07 18:33:24 +03:00
v [ 0 ] . sid = s - > zero_sid ;
2006-12-07 13:04:35 +03:00
v [ 0 ] . dn = s - > forest . schema_dn_str ;
2010-05-09 19:20:01 +04:00
ndr_err = ndr_push_struct_blob ( & vd [ 0 ] , vd , & v [ 0 ] ,
( ndr_push_flags_fn_t ) ndr_push_drsuapi_DsReplicaObjectIdentifier3 ) ;
2007-11-09 21:24:51 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
c - > status = ndr_map_error2ntstatus ( ndr_err ) ;
if ( ! composite_is_ok ( c ) ) return ;
}
2007-01-02 22:29:32 +03:00
2007-01-03 12:58:14 +03:00
vs [ 0 ] . blob = & vd [ 0 ] ;
2006-12-07 13:04:35 +03:00
2010-10-29 03:22:35 +04:00
attrs [ i ] . attid = DRSUAPI_ATTID_dMDLocation ;
2007-01-03 12:58:14 +03:00
attrs [ i ] . value_ctr . num_values = 1 ;
attrs [ i ] . value_ctr . values = vs ;
2006-12-07 13:04:35 +03:00
i + + ;
}
/* msDS-HasDomainNCs: <domain_partition> */
2006-12-11 20:04:43 +03:00
if ( w2k3 ) {
2007-01-03 12:58:14 +03:00
struct drsuapi_DsAttributeValue * vs ;
2007-01-02 22:29:32 +03:00
DATA_BLOB * vd ;
struct drsuapi_DsReplicaObjectIdentifier3 v [ 1 ] ;
2006-12-07 13:04:35 +03:00
2007-01-03 12:58:14 +03:00
vs = talloc_array ( attrs , struct drsuapi_DsAttributeValue , 1 ) ;
2006-12-07 13:04:35 +03:00
if ( composite_nomem ( vs , c ) ) return ;
2007-01-02 22:29:32 +03:00
vd = talloc_array ( vs , DATA_BLOB , 1 ) ;
if ( composite_nomem ( vd , c ) ) return ;
2006-12-07 13:04:35 +03:00
v [ 0 ] . guid = GUID_zero ( ) ;
2006-12-07 18:33:24 +03:00
v [ 0 ] . sid = s - > zero_sid ;
2006-12-07 13:04:35 +03:00
v [ 0 ] . dn = s - > domain . dn_str ;
2010-05-09 19:20:01 +04:00
ndr_err = ndr_push_struct_blob ( & vd [ 0 ] , vd , & v [ 0 ] ,
( ndr_push_flags_fn_t ) ndr_push_drsuapi_DsReplicaObjectIdentifier3 ) ;
2007-11-09 21:24:51 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
c - > status = ndr_map_error2ntstatus ( ndr_err ) ;
if ( ! composite_is_ok ( c ) ) return ;
}
2007-01-02 22:29:32 +03:00
2007-01-03 12:58:14 +03:00
vs [ 0 ] . blob = & vd [ 0 ] ;
2006-12-07 13:04:35 +03:00
2010-10-29 03:22:35 +04:00
attrs [ i ] . attid = DRSUAPI_ATTID_msDS_HasDomainNCs ;
2007-01-03 12:58:14 +03:00
attrs [ i ] . value_ctr . num_values = 1 ;
attrs [ i ] . value_ctr . values = vs ;
2006-12-07 13:04:35 +03:00
i + + ;
}
/* msDS-Behavior-Version */
2006-12-11 20:04:43 +03:00
if ( w2k3 ) {
2007-01-03 12:58:14 +03:00
struct drsuapi_DsAttributeValue * vs ;
2007-01-02 17:14:35 +03:00
DATA_BLOB * vd ;
2006-12-07 13:04:35 +03:00
2007-01-03 12:58:14 +03:00
vs = talloc_array ( attrs , struct drsuapi_DsAttributeValue , 1 ) ;
2006-12-07 13:04:35 +03:00
if ( composite_nomem ( vs , c ) ) return ;
2007-01-02 17:14:35 +03:00
vd = talloc_array ( vs , DATA_BLOB , 1 ) ;
if ( composite_nomem ( vd , c ) ) return ;
vd [ 0 ] = data_blob_talloc ( vd , NULL , 4 ) ;
if ( composite_nomem ( vd [ 0 ] . data , c ) ) return ;
2006-12-07 13:04:35 +03:00
2009-09-25 12:44:19 +04:00
SIVAL ( vd [ 0 ] . data , 0 , get_dc_function_level ( s - > libnet - > lp_ctx ) ) ;
2006-12-07 13:04:35 +03:00
2007-01-03 12:58:14 +03:00
vs [ 0 ] . blob = & vd [ 0 ] ;
2006-12-07 13:04:35 +03:00
2010-10-29 03:22:35 +04:00
attrs [ i ] . attid = DRSUAPI_ATTID_msDS_Behavior_Version ;
2007-01-03 12:58:14 +03:00
attrs [ i ] . value_ctr . num_values = 1 ;
attrs [ i ] . value_ctr . values = vs ;
2006-12-07 13:04:35 +03:00
i + + ;
}
/* systemFlags */
{
2007-01-03 12:58:14 +03:00
struct drsuapi_DsAttributeValue * vs ;
2007-01-02 17:14:35 +03:00
DATA_BLOB * vd ;
2006-12-07 13:04:35 +03:00
2007-01-03 12:58:14 +03:00
vs = talloc_array ( attrs , struct drsuapi_DsAttributeValue , 1 ) ;
2006-12-07 13:04:35 +03:00
if ( composite_nomem ( vs , c ) ) return ;
2007-01-02 17:14:35 +03:00
vd = talloc_array ( vs , DATA_BLOB , 1 ) ;
if ( composite_nomem ( vd , c ) ) return ;
2006-12-07 13:04:35 +03:00
2007-01-02 17:14:35 +03:00
vd [ 0 ] = data_blob_talloc ( vd , NULL , 4 ) ;
if ( composite_nomem ( vd [ 0 ] . data , c ) ) return ;
2006-12-07 13:04:35 +03:00
2010-02-17 19:01:31 +03:00
if ( s - > rodc_join ) {
SIVAL ( vd [ 0 ] . data , 0 , SYSTEM_FLAG_CONFIG_ALLOW_RENAME ) ;
} else {
SIVAL ( vd [ 0 ] . data , 0 , SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE ) ;
}
2007-01-02 17:14:35 +03:00
2007-01-03 12:58:14 +03:00
vs [ 0 ] . blob = & vd [ 0 ] ;
2006-12-07 13:04:35 +03:00
2010-10-29 03:22:35 +04:00
attrs [ i ] . attid = DRSUAPI_ATTID_systemFlags ;
2007-01-03 12:58:14 +03:00
attrs [ i ] . value_ctr . num_values = 1 ;
attrs [ i ] . value_ctr . values = vs ;
2006-12-07 13:04:35 +03:00
i + + ;
}
/* serverReference: ... */
{
2007-01-03 12:58:14 +03:00
struct drsuapi_DsAttributeValue * vs ;
2007-01-02 22:29:32 +03:00
DATA_BLOB * vd ;
struct drsuapi_DsReplicaObjectIdentifier3 v [ 1 ] ;
2006-12-07 13:04:35 +03:00
2007-01-03 12:58:14 +03:00
vs = talloc_array ( attrs , struct drsuapi_DsAttributeValue , 1 ) ;
2006-12-07 13:04:35 +03:00
if ( composite_nomem ( vs , c ) ) return ;
2007-01-02 22:29:32 +03:00
vd = talloc_array ( vs , DATA_BLOB , 1 ) ;
if ( composite_nomem ( vd , c ) ) return ;
2006-12-07 13:04:35 +03:00
v [ 0 ] . guid = GUID_zero ( ) ;
2006-12-07 18:33:24 +03:00
v [ 0 ] . sid = s - > zero_sid ;
2006-12-07 13:04:35 +03:00
v [ 0 ] . dn = s - > dest_dsa . computer_dn_str ;
2010-05-09 19:20:01 +04:00
ndr_err = ndr_push_struct_blob ( & vd [ 0 ] , vd , & v [ 0 ] ,
( ndr_push_flags_fn_t ) ndr_push_drsuapi_DsReplicaObjectIdentifier3 ) ;
2007-11-09 21:24:51 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
c - > status = ndr_map_error2ntstatus ( ndr_err ) ;
if ( ! composite_is_ok ( c ) ) return ;
}
2007-01-02 22:29:32 +03:00
2007-01-03 12:58:14 +03:00
vs [ 0 ] . blob = & vd [ 0 ] ;
2006-12-07 13:04:35 +03:00
2010-10-29 03:22:35 +04:00
attrs [ i ] . attid = DRSUAPI_ATTID_serverReference ;
2007-01-03 12:58:14 +03:00
attrs [ i ] . value_ctr . num_values = 1 ;
attrs [ i ] . value_ctr . values = vs ;
2006-12-07 13:04:35 +03:00
i + + ;
}
2006-12-06 18:29:01 +03:00
2010-02-17 19:01:31 +03:00
/* options:... */
if ( s - > rodc_join ) {
struct drsuapi_DsAttributeValue * vs ;
DATA_BLOB * vd ;
vs = talloc_array ( attrs , struct drsuapi_DsAttributeValue , 1 ) ;
if ( composite_nomem ( vs , c ) ) return ;
vd = talloc_array ( vs , DATA_BLOB , 1 ) ;
if ( composite_nomem ( vd , c ) ) return ;
vd [ 0 ] = data_blob_talloc ( vd , NULL , 4 ) ;
if ( composite_nomem ( vd [ 0 ] . data , c ) ) return ;
SIVAL ( vd [ 0 ] . data , 0 , DS_NTDSDSA_OPT_DISABLE_OUTBOUND_REPL ) ;
vs [ 0 ] . blob = & vd [ 0 ] ;
2010-10-29 03:22:35 +04:00
attrs [ i ] . attid = DRSUAPI_ATTID_options ;
2010-02-17 19:01:31 +03:00
attrs [ i ] . value_ctr . num_values = 1 ;
attrs [ i ] . value_ctr . values = vs ;
i + + ;
}
2006-12-07 13:04:35 +03:00
/* truncate the attribute list to the attribute count we have filled in */
num_attrs = i ;
2006-12-06 18:29:01 +03:00
/* setup request structure */
r - > in . bind_handle = & s - > drsuapi1 . bind_handle ;
r - > in . level = 2 ;
2008-10-17 20:54:03 +04:00
r - > in . req = talloc ( s , union drsuapi_DsAddEntryRequest ) ;
r - > in . req - > req2 . first_object . next_object = NULL ;
r - > in . req - > req2 . first_object . object . identifier = identifier ;
r - > in . req - > req2 . first_object . object . flags = 0x00000000 ;
r - > in . req - > req2 . first_object . object . attribute_ctr . num_attributes = num_attrs ;
r - > in . req - > req2 . first_object . object . attribute_ctr . attributes = attrs ;
2010-03-07 22:46:39 +03:00
r - > out . level_out = talloc ( s , uint32_t ) ;
2008-10-17 20:54:03 +04:00
r - > out . ctr = talloc ( s , union drsuapi_DsAddEntryCtr ) ;
2006-12-06 18:29:01 +03:00
2010-02-27 12:00:42 +03:00
s - > ndr_struct_ptr = r ;
2010-03-08 18:41:43 +03:00
subreq = dcerpc_drsuapi_DsAddEntry_r_send ( s , c - > event_ctx ,
s - > drsuapi1 . drsuapi_handle , r ) ;
if ( composite_nomem ( subreq , c ) ) return ;
tevent_req_set_callback ( subreq , becomeDC_drsuapi1_add_entry_recv , s ) ;
2006-12-06 18:29:01 +03:00
}
2006-12-07 22:50:46 +03:00
static void becomeDC_drsuapi2_connect_recv ( struct composite_context * req ) ;
2006-12-20 17:49:40 +03:00
static NTSTATUS becomeDC_prepare_db ( struct libnet_BecomeDC_state * s ) ;
2006-12-07 22:50:46 +03:00
2010-03-08 18:41:43 +03:00
static void becomeDC_drsuapi1_add_entry_recv ( struct tevent_req * subreq )
2006-12-06 18:29:01 +03:00
{
2010-03-08 18:41:43 +03:00
struct libnet_BecomeDC_state * s = tevent_req_callback_data ( subreq ,
2006-12-06 18:29:01 +03:00
struct libnet_BecomeDC_state ) ;
struct composite_context * c = s - > creq ;
2010-02-27 12:00:42 +03:00
struct drsuapi_DsAddEntry * r = talloc_get_type_abort ( s - > ndr_struct_ptr ,
2006-12-06 18:29:01 +03:00
struct drsuapi_DsAddEntry ) ;
2007-02-23 14:04:05 +03:00
char * binding_str ;
2014-02-04 05:51:16 +04:00
uint32_t assoc_group_id ;
2007-02-12 12:53:52 +03:00
2010-02-27 12:00:42 +03:00
s - > ndr_struct_ptr = NULL ;
2006-12-06 18:29:01 +03:00
2010-03-08 18:41:43 +03:00
c - > status = dcerpc_drsuapi_DsAddEntry_r_recv ( subreq , r ) ;
TALLOC_FREE ( subreq ) ;
2006-12-06 18:29:01 +03:00
if ( ! composite_is_ok ( c ) ) return ;
if ( ! W_ERROR_IS_OK ( r - > out . result ) ) {
composite_error ( c , werror_to_ntstatus ( r - > out . result ) ) ;
return ;
}
2008-10-17 20:54:03 +04:00
if ( * r - > out . level_out = = 3 ) {
2010-04-11 18:27:30 +04:00
WERROR status ;
2010-03-12 18:05:58 +03:00
union drsuapi_DsAddEntry_ErrData * err_data = r - > out . ctr - > ctr3 . err_data ;
/* check for errors */
2010-04-11 18:27:30 +04:00
status = err_data ? err_data - > v1 . status : WERR_OK ;
if ( ! W_ERROR_IS_OK ( status ) ) {
2010-03-15 14:57:41 +03:00
struct drsuapi_DsAddEntryErrorInfo_Attr_V1 * attr_err ;
struct drsuapi_DsAddEntry_AttrErrListItem_V1 * attr_err_li ;
struct drsuapi_DsAddEntryErrorInfo_Name_V1 * name_err ;
struct drsuapi_DsAddEntryErrorInfo_Referr_V1 * ref_err ;
struct drsuapi_DsAddEntry_RefErrListItem_V1 * ref_li ;
2006-12-07 22:18:55 +03:00
2010-03-10 17:37:38 +03:00
if ( r - > out . ctr - > ctr3 . err_ver ! = 1 ) {
2006-12-07 22:18:55 +03:00
composite_error ( c , NT_STATUS_INVALID_NETWORK_RESPONSE ) ;
return ;
}
2010-08-23 05:11:35 +04:00
DEBUG ( 0 , ( " DsAddEntry (R3) of '%s' failed: "
2010-04-11 18:24:32 +04:00
" Errors: dir_err = %d, status = %s; \n " ,
2010-08-23 05:11:35 +04:00
r - > in . req - > req3 . first_object . object . identifier - > dn ,
2010-03-12 18:05:58 +03:00
err_data - > v1 . dir_err ,
win_errstr ( err_data - > v1 . status ) ) ) ;
2006-12-07 22:18:55 +03:00
2010-03-12 18:05:58 +03:00
if ( ! err_data - > v1 . info ) {
2010-04-22 10:43:21 +04:00
DEBUG ( 0 , ( " DsAddEntry (R3): no error info returned! \n " ) ) ;
2006-12-07 22:18:55 +03:00
composite_error ( c , werror_to_ntstatus ( status ) ) ;
return ;
}
2010-03-12 18:05:58 +03:00
/* dump more detailed error */
2010-03-15 14:57:41 +03:00
switch ( err_data - > v1 . dir_err ) {
2010-03-12 18:05:58 +03:00
case DRSUAPI_DIRERR_ATTRIBUTE :
2010-03-15 14:57:41 +03:00
/* Dump attribute errors */
attr_err = & err_data - > v1 . info - > attr_err ;
2010-04-11 18:24:32 +04:00
DEBUGADD ( 0 , ( " Attribute Error: object = %s, count = %d; \n " ,
2010-03-15 14:57:41 +03:00
attr_err - > id - > dn ,
attr_err - > count ) ) ;
attr_err_li = & attr_err - > first ;
for ( ; attr_err_li ; attr_err_li = attr_err_li - > next ) {
struct drsuapi_DsAddEntry_AttrErr_V1 * err = & attr_err_li - > err_data ;
2010-04-11 18:24:32 +04:00
DEBUGADD ( 0 , ( " Error: err = %s, problem = 0x%08X, attid = 0x%08X; \n " ,
2010-03-15 14:57:41 +03:00
win_errstr ( err - > extended_err ) ,
err - > problem ,
err - > attid ) ) ;
/* TODO: should we print attribute value here? */
}
2010-03-12 18:05:58 +03:00
break ;
case DRSUAPI_DIRERR_NAME :
2010-03-15 14:57:41 +03:00
/* Dump Name resolution error */
name_err = & err_data - > v1 . info - > name_err ;
2010-04-11 18:24:32 +04:00
DEBUGADD ( 0 , ( " Name Error: err = %s, problem = 0x%08X, id_matched = %s; \n " ,
2010-03-15 14:57:41 +03:00
win_errstr ( name_err - > extended_err ) ,
name_err - > problem ,
name_err - > id_matched - > dn ) ) ;
2010-03-12 18:05:58 +03:00
break ;
case DRSUAPI_DIRERR_REFERRAL :
2010-03-15 14:57:41 +03:00
/* Dump Referral errors */
ref_err = & err_data - > v1 . info - > referral_err ;
2010-04-11 18:24:32 +04:00
DEBUGADD ( 0 , ( " Referral Error: extended_err = %s \n " ,
2010-04-22 10:43:21 +04:00
win_errstr ( ref_err - > extended_err ) ) ) ;
2010-03-15 14:57:41 +03:00
ref_li = & ref_err - > refer ;
for ( ; ref_li ; ref_li = ref_li - > next ) {
struct drsuapi_DsaAddressListItem_V1 * addr ;
DEBUGADD ( 0 , ( " Referral: id_target = %s, ref_type = 0x%04X, " ,
ref_li - > id_target - > dn ,
ref_li - > ref_type ) ) ;
if ( ref_li - > is_choice_set ) {
DEBUGADD ( 0 , ( " choice = 0x%02X, " ,
ref_li - > choice ) ) ;
}
DEBUGADD ( 0 , ( " add_list ( " ) ) ;
for ( addr = ref_li - > addr_list ; addr ; addr = addr - > next ) {
DEBUGADD ( 0 , ( " %s " , addr - > address - > string ) ) ;
if ( addr - > next ) {
DEBUGADD ( 0 , ( " , " ) ) ;
}
}
2010-04-11 18:24:32 +04:00
DEBUGADD ( 0 , ( " ); \n " ) ) ;
2010-03-15 14:57:41 +03:00
}
2010-03-12 18:05:58 +03:00
break ;
case DRSUAPI_DIRERR_SECURITY :
2010-03-15 14:57:41 +03:00
/* Dump Security error. */
2010-04-11 18:24:32 +04:00
DEBUGADD ( 0 , ( " Security Error: extended_err = %s, problem = 0x%08X \n " ,
2010-03-15 14:57:41 +03:00
win_errstr ( err_data - > v1 . info - > security_err . extended_err ) ,
err_data - > v1 . info - > security_err . problem ) ) ;
2006-12-07 22:18:55 +03:00
break ;
2010-03-12 18:05:58 +03:00
case DRSUAPI_DIRERR_SERVICE :
2010-03-15 14:57:41 +03:00
/* Dump Service error. */
2010-04-11 18:24:32 +04:00
DEBUGADD ( 0 , ( " Service Error: extended_err = %s, problem = 0x%08X \n " ,
2010-03-15 14:57:41 +03:00
win_errstr ( err_data - > v1 . info - > service_err . extended_err ) ,
err_data - > v1 . info - > service_err . problem ) ) ;
2010-03-12 18:05:58 +03:00
break ;
case DRSUAPI_DIRERR_UPDATE :
2010-03-15 14:57:41 +03:00
/* Dump Update error. */
2010-04-11 18:24:32 +04:00
DEBUGADD ( 0 , ( " Update Error: extended_err = %s, problem = 0x%08X \n " ,
2010-03-15 14:57:41 +03:00
win_errstr ( err_data - > v1 . info - > update_err . extended_err ) ,
err_data - > v1 . info - > update_err . problem ) ) ;
2010-03-12 18:05:58 +03:00
break ;
case DRSUAPI_DIRERR_SYSTEM :
2010-03-15 14:57:41 +03:00
/* System error. */
2010-04-11 18:24:32 +04:00
DEBUGADD ( 0 , ( " System Error: extended_err = %s, problem = 0x%08X \n " ,
2010-03-15 14:57:41 +03:00
win_errstr ( err_data - > v1 . info - > system_err . extended_err ) ,
err_data - > v1 . info - > system_err . problem ) ) ;
2010-03-12 18:05:58 +03:00
break ;
2010-04-11 18:04:21 +04:00
case DRSUAPI_DIRERR_OK : /* mute compiler warnings */
2010-03-12 18:05:58 +03:00
default :
2010-04-11 18:24:32 +04:00
DEBUGADD ( 0 , ( " Unknown DIRERR error class returned! \n " ) ) ;
2006-12-07 22:18:55 +03:00
break ;
}
composite_error ( c , werror_to_ntstatus ( status ) ) ;
return ;
}
2010-03-12 18:05:58 +03:00
if ( 1 ! = r - > out . ctr - > ctr3 . count ) {
DEBUG ( 0 , ( " DsAddEntry - Ctr3: something very wrong had happened - "
2010-04-11 18:24:32 +04:00
" method succeeded but objects returned are %d (expected 1). \n " ,
2010-03-12 18:05:58 +03:00
r - > out . ctr - > ctr3 . count ) ) ;
composite_error ( c , NT_STATUS_INVALID_NETWORK_RESPONSE ) ;
2012-04-23 11:22:18 +04:00
return ;
2010-03-12 18:05:58 +03:00
}
2008-10-17 20:54:03 +04:00
s - > dest_dsa . ntds_guid = r - > out . ctr - > ctr3 . objects [ 0 ] . guid ;
2010-03-12 18:05:58 +03:00
2008-10-17 20:54:03 +04:00
} else if ( * r - > out . level_out = = 2 ) {
2010-03-12 14:42:05 +03:00
if ( DRSUAPI_DIRERR_OK ! = r - > out . ctr - > ctr2 . dir_err ) {
2010-04-11 18:24:32 +04:00
DEBUG ( 0 , ( " DsAddEntry failed with: dir_err = %d, extended_err = %s \n " ,
2010-03-12 14:42:05 +03:00
r - > out . ctr - > ctr2 . dir_err ,
win_errstr ( r - > out . ctr - > ctr2 . extended_err ) ) ) ;
composite_error ( c , werror_to_ntstatus ( r - > out . ctr - > ctr2 . extended_err ) ) ;
2006-12-07 22:18:55 +03:00
return ;
}
2010-03-12 14:42:05 +03:00
if ( 1 ! = r - > out . ctr - > ctr2 . count ) {
DEBUG ( 0 , ( " DsAddEntry: something very wrong had happened - "
" method succeeded but objects returned are %d (expected 1). "
2010-04-11 18:24:32 +04:00
" Errors: dir_err = %d, extended_err = %s \n " ,
2010-03-12 14:42:05 +03:00
r - > out . ctr - > ctr2 . count ,
r - > out . ctr - > ctr2 . dir_err ,
win_errstr ( r - > out . ctr - > ctr2 . extended_err ) ) ) ;
composite_error ( c , NT_STATUS_INVALID_NETWORK_RESPONSE ) ;
2012-04-23 11:22:18 +04:00
return ;
2010-03-12 14:42:05 +03:00
}
2008-10-17 20:54:03 +04:00
s - > dest_dsa . ntds_guid = r - > out . ctr - > ctr2 . objects [ 0 ] . guid ;
2006-12-07 22:18:55 +03:00
} else {
composite_error ( c , NT_STATUS_INVALID_NETWORK_RESPONSE ) ;
return ;
}
2006-12-08 03:16:36 +03:00
talloc_free ( r ) ;
2006-12-21 00:17:19 +03:00
s - > dest_dsa . ntds_dn_str = talloc_asprintf ( s , " CN=NTDS Settings,%s " ,
s - > dest_dsa . server_dn_str ) ;
if ( composite_nomem ( s - > dest_dsa . ntds_dn_str , c ) ) return ;
2006-12-20 17:49:40 +03:00
c - > status = becomeDC_prepare_db ( s ) ;
if ( ! composite_is_ok ( c ) ) return ;
2007-02-23 14:04:05 +03:00
/* this avoids the epmapper lookup on the 2nd connection */
binding_str = dcerpc_binding_string ( s , s - > drsuapi1 . binding ) ;
if ( composite_nomem ( binding_str , c ) ) return ;
c - > status = dcerpc_parse_binding ( s , binding_str , & s - > drsuapi2 . binding ) ;
talloc_free ( binding_str ) ;
if ( ! composite_is_ok ( c ) ) return ;
2011-04-01 08:56:58 +04:00
if ( DEBUGLEVEL > = 10 ) {
2014-02-04 12:57:07 +04:00
c - > status = dcerpc_binding_set_flags ( s - > drsuapi2 . binding ,
DCERPC_DEBUG_PRINT_BOTH ,
0 ) ;
if ( ! composite_is_ok ( c ) ) return ;
2011-04-01 08:56:58 +04:00
}
2007-02-23 14:04:05 +03:00
/* w2k3 uses the same assoc_group_id as on the first connection, so we do */
2014-02-04 05:51:16 +04:00
assoc_group_id = dcerpc_binding_get_assoc_group_id ( s - > drsuapi1 . pipe - > binding ) ;
c - > status = dcerpc_binding_set_assoc_group_id ( s - > drsuapi2 . binding , assoc_group_id ) ;
if ( ! composite_is_ok ( c ) ) return ;
2007-02-23 14:04:05 +03:00
2006-12-07 22:50:46 +03:00
becomeDC_drsuapi_connect_send ( s , & s - > drsuapi2 , becomeDC_drsuapi2_connect_recv ) ;
}
2006-12-20 17:49:40 +03:00
static NTSTATUS becomeDC_prepare_db ( struct libnet_BecomeDC_state * s )
{
if ( ! s - > callbacks . prepare_db ) return NT_STATUS_OK ;
2006-12-21 00:14:44 +03:00
s - > _pp . domain = & s - > domain ;
s - > _pp . forest = & s - > forest ;
s - > _pp . source_dsa = & s - > source_dsa ;
s - > _pp . dest_dsa = & s - > dest_dsa ;
return s - > callbacks . prepare_db ( s - > callbacks . private_data , & s - > _pp ) ;
2006-12-20 17:49:40 +03:00
}
2010-03-08 18:41:43 +03:00
static void becomeDC_drsuapi2_bind_recv ( struct tevent_req * subreq ) ;
2006-12-07 22:50:46 +03:00
static void becomeDC_drsuapi2_connect_recv ( struct composite_context * req )
{
struct libnet_BecomeDC_state * s = talloc_get_type ( req - > async . private_data ,
struct libnet_BecomeDC_state ) ;
struct composite_context * c = s - > creq ;
c - > status = dcerpc_pipe_connect_b_recv ( req , s , & s - > drsuapi2 . pipe ) ;
if ( ! composite_is_ok ( c ) ) return ;
2010-03-08 18:41:43 +03:00
s - > drsuapi2 . drsuapi_handle = s - > drsuapi2 . pipe - > binding_handle ;
2007-02-12 13:58:06 +03:00
c - > status = gensec_session_key ( s - > drsuapi2 . pipe - > conn - > security_state . generic_state ,
2011-08-01 09:39:01 +04:00
s ,
2007-02-12 13:58:06 +03:00
& s - > drsuapi2 . gensec_skey ) ;
if ( ! composite_is_ok ( c ) ) return ;
2006-12-07 22:50:46 +03:00
becomeDC_drsuapi_bind_send ( s , & s - > drsuapi2 , becomeDC_drsuapi2_bind_recv ) ;
}
static void becomeDC_drsuapi3_connect_recv ( struct composite_context * req ) ;
2010-03-08 18:41:43 +03:00
static void becomeDC_drsuapi2_bind_recv ( struct tevent_req * subreq )
2006-12-07 22:50:46 +03:00
{
2010-03-08 18:41:43 +03:00
struct libnet_BecomeDC_state * s = tevent_req_callback_data ( subreq ,
2006-12-07 22:50:46 +03:00
struct libnet_BecomeDC_state ) ;
struct composite_context * c = s - > creq ;
2006-12-09 18:27:22 +03:00
char * binding_str ;
2014-02-04 05:51:16 +04:00
uint32_t assoc_group_id ;
2006-12-07 23:11:00 +03:00
WERROR status ;
2006-12-07 22:50:46 +03:00
2010-03-08 18:41:43 +03:00
c - > status = dcerpc_drsuapi_DsBind_r_recv ( subreq , s ) ;
TALLOC_FREE ( subreq ) ;
2006-12-07 22:50:46 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2006-12-07 23:11:00 +03:00
status = becomeDC_drsuapi_bind_recv ( s , & s - > drsuapi2 ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
composite_error ( c , werror_to_ntstatus ( status ) ) ;
2006-12-07 22:50:46 +03:00
return ;
}
2007-02-23 14:04:05 +03:00
/* this avoids the epmapper lookup on the 3rd connection */
binding_str = dcerpc_binding_string ( s , s - > drsuapi1 . binding ) ;
2006-12-09 18:27:22 +03:00
if ( composite_nomem ( binding_str , c ) ) return ;
c - > status = dcerpc_parse_binding ( s , binding_str , & s - > drsuapi3 . binding ) ;
talloc_free ( binding_str ) ;
if ( ! composite_is_ok ( c ) ) return ;
2006-12-07 22:50:46 +03:00
2011-04-01 08:56:58 +04:00
if ( DEBUGLEVEL > = 10 ) {
2014-02-04 12:57:07 +04:00
c - > status = dcerpc_binding_set_flags ( s - > drsuapi3 . binding ,
DCERPC_DEBUG_PRINT_BOTH ,
0 ) ;
if ( ! composite_is_ok ( c ) ) return ;
2011-04-01 08:56:58 +04:00
}
2007-02-23 14:04:05 +03:00
/* w2k3 uses the same assoc_group_id as on the first connection, so we do */
2014-02-04 05:51:16 +04:00
assoc_group_id = dcerpc_binding_get_assoc_group_id ( s - > drsuapi1 . pipe - > binding ) ;
c - > status = dcerpc_binding_set_assoc_group_id ( s - > drsuapi3 . binding , assoc_group_id ) ;
if ( ! composite_is_ok ( c ) ) return ;
2007-02-23 14:04:05 +03:00
/* w2k3 uses the concurrent multiplex feature on the 3rd connection, so we do */
2014-02-04 12:57:07 +04:00
c - > status = dcerpc_binding_set_flags ( s - > drsuapi3 . binding ,
DCERPC_CONCURRENT_MULTIPLEX ,
0 ) ;
if ( ! composite_is_ok ( c ) ) return ;
2007-02-23 14:04:05 +03:00
2006-12-07 22:50:46 +03:00
becomeDC_drsuapi_connect_send ( s , & s - > drsuapi3 , becomeDC_drsuapi3_connect_recv ) ;
}
2006-12-08 03:16:36 +03:00
static void becomeDC_drsuapi3_pull_schema_send ( struct libnet_BecomeDC_state * s ) ;
2006-12-07 22:50:46 +03:00
static void becomeDC_drsuapi3_connect_recv ( struct composite_context * req )
{
struct libnet_BecomeDC_state * s = talloc_get_type ( req - > async . private_data ,
struct libnet_BecomeDC_state ) ;
struct composite_context * c = s - > creq ;
c - > status = dcerpc_pipe_connect_b_recv ( req , s , & s - > drsuapi3 . pipe ) ;
if ( ! composite_is_ok ( c ) ) return ;
2010-03-08 18:41:43 +03:00
s - > drsuapi3 . drsuapi_handle = s - > drsuapi3 . pipe - > binding_handle ;
2007-02-12 13:58:06 +03:00
c - > status = gensec_session_key ( s - > drsuapi3 . pipe - > conn - > security_state . generic_state ,
2011-08-01 09:39:01 +04:00
s ,
2007-02-12 13:58:06 +03:00
& s - > drsuapi3 . gensec_skey ) ;
if ( ! composite_is_ok ( c ) ) return ;
2006-12-08 03:16:36 +03:00
becomeDC_drsuapi3_pull_schema_send ( s ) ;
}
static void becomeDC_drsuapi_pull_partition_send ( struct libnet_BecomeDC_state * s ,
struct becomeDC_drsuapi * drsuapi_h ,
struct becomeDC_drsuapi * drsuapi_p ,
2006-12-21 00:54:06 +03:00
struct libnet_BecomeDC_Partition * partition ,
2010-03-08 18:41:43 +03:00
void ( * recv_fn ) ( struct tevent_req * subreq ) )
2006-12-08 03:16:36 +03:00
{
struct composite_context * c = s - > creq ;
struct drsuapi_DsGetNCChanges * r ;
2010-03-08 18:41:43 +03:00
struct tevent_req * subreq ;
2006-12-08 03:16:36 +03:00
r = talloc ( s , struct drsuapi_DsGetNCChanges ) ;
if ( composite_nomem ( r , c ) ) return ;
2010-03-05 21:33:46 +03:00
r - > out . level_out = talloc ( r , uint32_t ) ;
2008-10-17 22:32:36 +04:00
if ( composite_nomem ( r - > out . level_out , c ) ) return ;
r - > in . req = talloc ( r , union drsuapi_DsGetNCChangesRequest ) ;
if ( composite_nomem ( r - > in . req , c ) ) return ;
r - > out . ctr = talloc ( r , union drsuapi_DsGetNCChangesCtr ) ;
if ( composite_nomem ( r - > out . ctr , c ) ) return ;
2007-01-12 17:26:08 +03:00
2006-12-08 03:16:36 +03:00
r - > in . bind_handle = & drsuapi_h - > bind_handle ;
if ( drsuapi_h - > remote_info28 . supported_extensions & DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8 ) {
2008-10-17 22:32:36 +04:00
r - > in . level = 8 ;
r - > in . req - > req8 . destination_dsa_guid = partition - > destination_dsa_guid ;
r - > in . req - > req8 . source_dsa_invocation_id = partition - > source_dsa_invocation_id ;
r - > in . req - > req8 . naming_context = & partition - > nc ;
r - > in . req - > req8 . highwatermark = partition - > highwatermark ;
r - > in . req - > req8 . uptodateness_vector = NULL ;
r - > in . req - > req8 . replica_flags = partition - > replica_flags ;
r - > in . req - > req8 . max_object_count = 133 ;
r - > in . req - > req8 . max_ndr_size = 1336811 ;
r - > in . req - > req8 . extended_op = DRSUAPI_EXOP_NONE ;
r - > in . req - > req8 . fsmo_info = 0 ;
r - > in . req - > req8 . partial_attribute_set = NULL ;
r - > in . req - > req8 . partial_attribute_set_ex = NULL ;
r - > in . req - > req8 . mapping_ctr . num_mappings = 0 ;
r - > in . req - > req8 . mapping_ctr . mappings = NULL ;
2006-12-08 03:16:36 +03:00
} else {
2008-10-17 22:32:36 +04:00
r - > in . level = 5 ;
r - > in . req - > req5 . destination_dsa_guid = partition - > destination_dsa_guid ;
r - > in . req - > req5 . source_dsa_invocation_id = partition - > source_dsa_invocation_id ;
r - > in . req - > req5 . naming_context = & partition - > nc ;
r - > in . req - > req5 . highwatermark = partition - > highwatermark ;
r - > in . req - > req5 . uptodateness_vector = NULL ;
r - > in . req - > req5 . replica_flags = partition - > replica_flags ;
r - > in . req - > req5 . max_object_count = 133 ;
r - > in . req - > req5 . max_ndr_size = 1336770 ;
r - > in . req - > req5 . extended_op = DRSUAPI_EXOP_NONE ;
r - > in . req - > req5 . fsmo_info = 0 ;
2006-12-08 03:16:36 +03:00
}
/*
* we should try to use the drsuapi_p - > pipe here , as w2k3 does
* but it seems that some extra flags in the DCERPC Bind call
* are needed for it . Or the same KRB5 TGS is needed on both
* connections .
*/
2010-02-27 12:00:42 +03:00
s - > ndr_struct_ptr = r ;
2010-03-08 18:41:43 +03:00
subreq = dcerpc_drsuapi_DsGetNCChanges_r_send ( s , c - > event_ctx ,
drsuapi_p - > drsuapi_handle ,
r ) ;
if ( composite_nomem ( subreq , c ) ) return ;
tevent_req_set_callback ( subreq , recv_fn , s ) ;
2006-12-08 03:16:36 +03:00
}
2006-12-08 21:06:38 +03:00
static WERROR becomeDC_drsuapi_pull_partition_recv ( struct libnet_BecomeDC_state * s ,
2007-02-12 14:20:57 +03:00
struct becomeDC_drsuapi * drsuapi_h ,
struct becomeDC_drsuapi * drsuapi_p ,
2006-12-21 00:54:06 +03:00
struct libnet_BecomeDC_Partition * partition ,
2006-12-08 21:06:38 +03:00
struct drsuapi_DsGetNCChanges * r )
{
2017-06-19 01:26:48 +03:00
uint32_t req_level = r - > in . level ;
2011-08-08 12:29:05 +04:00
struct drsuapi_DsGetNCChangesRequest5 * req5 = NULL ;
struct drsuapi_DsGetNCChangesRequest8 * req8 = NULL ;
struct drsuapi_DsGetNCChangesRequest10 * req10 = NULL ;
2006-12-21 00:54:06 +03:00
uint32_t ctr_level = 0 ;
2006-12-08 21:06:38 +03:00
struct drsuapi_DsGetNCChangesCtr1 * ctr1 = NULL ;
struct drsuapi_DsGetNCChangesCtr6 * ctr6 = NULL ;
2009-09-17 20:05:58 +04:00
struct GUID * source_dsa_guid = NULL ;
struct GUID * source_dsa_invocation_id = NULL ;
struct drsuapi_DsReplicaHighWaterMark * new_highwatermark = NULL ;
2008-07-16 15:01:56 +04:00
bool more_data = false ;
2016-10-31 06:19:37 +03:00
WERROR werr ;
2006-12-08 21:06:38 +03:00
if ( ! W_ERROR_IS_OK ( r - > out . result ) ) {
return r - > out . result ;
}
2011-08-08 12:29:05 +04:00
switch ( r - > in . level ) {
case 0 :
/* none */
break ;
case 5 :
req5 = & r - > in . req - > req5 ;
break ;
case 8 :
req8 = & r - > in . req - > req8 ;
break ;
case 10 :
req10 = & r - > in . req - > req10 ;
break ;
default :
return WERR_INVALID_PARAMETER ;
}
2008-10-17 22:32:36 +04:00
if ( * r - > out . level_out = = 1 ) {
2006-12-21 00:54:06 +03:00
ctr_level = 1 ;
2008-10-17 22:32:36 +04:00
ctr1 = & r - > out . ctr - > ctr1 ;
} else if ( * r - > out . level_out = = 2 & &
r - > out . ctr - > ctr2 . mszip1 . ts ) {
2006-12-21 00:54:06 +03:00
ctr_level = 1 ;
2008-10-17 22:32:36 +04:00
ctr1 = & r - > out . ctr - > ctr2 . mszip1 . ts - > ctr1 ;
} else if ( * r - > out . level_out = = 6 ) {
2006-12-21 00:54:06 +03:00
ctr_level = 6 ;
2008-10-17 22:32:36 +04:00
ctr6 = & r - > out . ctr - > ctr6 ;
} else if ( * r - > out . level_out = = 7 & &
r - > out . ctr - > ctr7 . level = = 6 & &
r - > out . ctr - > ctr7 . type = = DRSUAPI_COMPRESSION_TYPE_MSZIP & &
r - > out . ctr - > ctr7 . ctr . mszip6 . ts ) {
2006-12-21 00:54:06 +03:00
ctr_level = 6 ;
2008-10-17 22:32:36 +04:00
ctr6 = & r - > out . ctr - > ctr7 . ctr . mszip6 . ts - > ctr6 ;
} else if ( * r - > out . level_out = = 7 & &
r - > out . ctr - > ctr7 . level = = 6 & &
2023-03-17 03:10:09 +03:00
r - > out . ctr - > ctr7 . type = = DRSUAPI_COMPRESSION_TYPE_WIN2K3_LZ77_DIRECT2 & &
2008-10-17 22:32:36 +04:00
r - > out . ctr - > ctr7 . ctr . xpress6 . ts ) {
2008-07-16 14:58:29 +04:00
ctr_level = 6 ;
2008-10-17 22:32:36 +04:00
ctr6 = & r - > out . ctr - > ctr7 . ctr . xpress6 . ts - > ctr6 ;
2006-12-08 21:06:38 +03:00
} else {
return WERR_BAD_NET_RESP ;
}
2008-08-19 12:36:24 +04:00
if ( ! ctr1 & & ! ctr6 ) {
return WERR_BAD_NET_RESP ;
}
2008-07-16 15:00:07 +04:00
if ( ctr_level = = 6 ) {
if ( ! W_ERROR_IS_OK ( ctr6 - > drs_error ) ) {
return ctr6 - > drs_error ;
}
}
2006-12-21 00:54:06 +03:00
switch ( ctr_level ) {
2006-12-08 21:06:38 +03:00
case 1 :
source_dsa_guid = & ctr1 - > source_dsa_guid ;
source_dsa_invocation_id = & ctr1 - > source_dsa_invocation_id ;
new_highwatermark = & ctr1 - > new_highwatermark ;
2008-07-16 15:01:56 +04:00
more_data = ctr1 - > more_data ;
2006-12-08 21:06:38 +03:00
break ;
case 6 :
source_dsa_guid = & ctr6 - > source_dsa_guid ;
source_dsa_invocation_id = & ctr6 - > source_dsa_invocation_id ;
new_highwatermark = & ctr6 - > new_highwatermark ;
2008-07-16 15:01:56 +04:00
more_data = ctr6 - > more_data ;
2006-12-08 21:06:38 +03:00
break ;
}
partition - > highwatermark = * new_highwatermark ;
partition - > source_dsa_guid = * source_dsa_guid ;
partition - > source_dsa_invocation_id = * source_dsa_invocation_id ;
2008-07-16 15:01:56 +04:00
partition - > more_data = more_data ;
2006-12-08 21:06:38 +03:00
2006-12-21 00:54:06 +03:00
if ( ! partition - > store_chunk ) return WERR_OK ;
s - > _sc . domain = & s - > domain ;
s - > _sc . forest = & s - > forest ;
s - > _sc . source_dsa = & s - > source_dsa ;
s - > _sc . dest_dsa = & s - > dest_dsa ;
s - > _sc . partition = partition ;
2011-08-08 12:29:05 +04:00
s - > _sc . req_level = req_level ;
s - > _sc . req5 = req5 ;
s - > _sc . req8 = req8 ;
s - > _sc . req10 = req10 ;
2006-12-21 00:54:06 +03:00
s - > _sc . ctr_level = ctr_level ;
s - > _sc . ctr1 = ctr1 ;
s - > _sc . ctr6 = ctr6 ;
2007-02-12 14:20:57 +03:00
/*
* we need to use the drsuapi_p - > gensec_skey here ,
* when we use drsuapi_p - > pipe in the for this request
*/
2007-02-23 14:04:05 +03:00
s - > _sc . gensec_skey = & drsuapi_p - > gensec_skey ;
2006-12-21 00:54:06 +03:00
2016-10-31 06:19:37 +03:00
werr = partition - > store_chunk ( s - > callbacks . private_data , & s - > _sc ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werr ;
2006-12-20 17:49:40 +03:00
}
2006-12-08 21:06:38 +03:00
return WERR_OK ;
}
2010-03-08 18:41:43 +03:00
static void becomeDC_drsuapi3_pull_schema_recv ( struct tevent_req * subreq ) ;
2006-12-08 21:08:30 +03:00
static void becomeDC_drsuapi3_pull_schema_send ( struct libnet_BecomeDC_state * s )
{
2006-12-08 21:22:26 +03:00
s - > schema_part . nc . guid = GUID_zero ( ) ;
s - > schema_part . nc . sid = s - > zero_sid ;
s - > schema_part . nc . dn = s - > forest . schema_dn_str ;
2006-12-08 21:08:30 +03:00
2006-12-08 21:22:26 +03:00
s - > schema_part . destination_dsa_guid = s - > drsuapi2 . bind_guid ;
2006-12-08 21:08:30 +03:00
2010-01-17 13:59:56 +03:00
s - > schema_part . replica_flags = DRSUAPI_DRS_WRIT_REP
| DRSUAPI_DRS_INIT_SYNC
| DRSUAPI_DRS_PER_SYNC
| DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS
| DRSUAPI_DRS_NEVER_SYNCED
2015-12-09 07:04:14 +03:00
| DRSUAPI_DRS_USE_COMPRESSION
| DRSUAPI_DRS_GET_ANC ;
2010-02-17 19:01:31 +03:00
if ( s - > rodc_join ) {
s - > schema_part . replica_flags & = ~ DRSUAPI_DRS_WRIT_REP ;
}
2006-12-08 21:08:30 +03:00
2006-12-20 17:49:40 +03:00
s - > schema_part . store_chunk = s - > callbacks . schema_chunk ;
2006-12-08 21:22:26 +03:00
becomeDC_drsuapi_pull_partition_send ( s , & s - > drsuapi2 , & s - > drsuapi3 , & s - > schema_part ,
2006-12-08 21:08:30 +03:00
becomeDC_drsuapi3_pull_schema_recv ) ;
}
2006-12-08 21:13:49 +03:00
static void becomeDC_drsuapi3_pull_config_send ( struct libnet_BecomeDC_state * s ) ;
2010-03-08 18:41:43 +03:00
static void becomeDC_drsuapi3_pull_schema_recv ( struct tevent_req * subreq )
2006-12-08 03:16:36 +03:00
{
2010-03-08 18:41:43 +03:00
struct libnet_BecomeDC_state * s = tevent_req_callback_data ( subreq ,
2006-12-08 03:16:36 +03:00
struct libnet_BecomeDC_state ) ;
struct composite_context * c = s - > creq ;
2010-02-27 12:00:42 +03:00
struct drsuapi_DsGetNCChanges * r = talloc_get_type_abort ( s - > ndr_struct_ptr ,
2006-12-08 03:16:36 +03:00
struct drsuapi_DsGetNCChanges ) ;
2006-12-08 21:06:38 +03:00
WERROR status ;
2006-12-08 03:16:36 +03:00
2010-02-27 12:00:42 +03:00
s - > ndr_struct_ptr = NULL ;
2007-02-12 12:53:52 +03:00
2010-03-08 18:41:43 +03:00
c - > status = dcerpc_drsuapi_DsGetNCChanges_r_recv ( subreq , r ) ;
TALLOC_FREE ( subreq ) ;
2006-12-08 03:16:36 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2007-02-12 14:20:57 +03:00
status = becomeDC_drsuapi_pull_partition_recv ( s , & s - > drsuapi2 , & s - > drsuapi3 , & s - > schema_part , r ) ;
2006-12-08 21:06:38 +03:00
if ( ! W_ERROR_IS_OK ( status ) ) {
composite_error ( c , werror_to_ntstatus ( status ) ) ;
2006-12-08 03:16:36 +03:00
return ;
}
talloc_free ( r ) ;
2008-07-16 15:01:56 +04:00
if ( s - > schema_part . more_data ) {
2006-12-08 21:22:26 +03:00
becomeDC_drsuapi_pull_partition_send ( s , & s - > drsuapi2 , & s - > drsuapi3 , & s - > schema_part ,
2006-12-08 21:06:38 +03:00
becomeDC_drsuapi3_pull_schema_recv ) ;
return ;
}
2006-12-08 21:13:49 +03:00
becomeDC_drsuapi3_pull_config_send ( s ) ;
}
2010-03-08 18:41:43 +03:00
static void becomeDC_drsuapi3_pull_config_recv ( struct tevent_req * subreq ) ;
2006-12-08 21:13:49 +03:00
static void becomeDC_drsuapi3_pull_config_send ( struct libnet_BecomeDC_state * s )
{
2006-12-08 21:22:26 +03:00
s - > config_part . nc . guid = GUID_zero ( ) ;
s - > config_part . nc . sid = s - > zero_sid ;
s - > config_part . nc . dn = s - > forest . config_dn_str ;
2006-12-08 21:13:49 +03:00
2006-12-08 21:22:26 +03:00
s - > config_part . destination_dsa_guid = s - > drsuapi2 . bind_guid ;
2006-12-08 21:13:49 +03:00
2010-01-17 13:59:56 +03:00
s - > config_part . replica_flags = DRSUAPI_DRS_WRIT_REP
| DRSUAPI_DRS_INIT_SYNC
| DRSUAPI_DRS_PER_SYNC
| DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS
| DRSUAPI_DRS_NEVER_SYNCED
2015-12-09 07:04:14 +03:00
| DRSUAPI_DRS_USE_COMPRESSION
| DRSUAPI_DRS_GET_ANC ;
2010-02-17 19:01:31 +03:00
if ( s - > rodc_join ) {
s - > schema_part . replica_flags & = ~ DRSUAPI_DRS_WRIT_REP ;
}
2006-12-08 21:13:49 +03:00
2006-12-20 17:49:40 +03:00
s - > config_part . store_chunk = s - > callbacks . config_chunk ;
2006-12-08 21:22:26 +03:00
becomeDC_drsuapi_pull_partition_send ( s , & s - > drsuapi2 , & s - > drsuapi3 , & s - > config_part ,
2006-12-08 21:13:49 +03:00
becomeDC_drsuapi3_pull_config_recv ) ;
}
2010-03-08 18:41:43 +03:00
static void becomeDC_drsuapi3_pull_config_recv ( struct tevent_req * subreq )
2006-12-08 21:13:49 +03:00
{
2010-03-08 18:41:43 +03:00
struct libnet_BecomeDC_state * s = tevent_req_callback_data ( subreq ,
2006-12-08 21:13:49 +03:00
struct libnet_BecomeDC_state ) ;
struct composite_context * c = s - > creq ;
2010-02-27 12:00:42 +03:00
struct drsuapi_DsGetNCChanges * r = talloc_get_type_abort ( s - > ndr_struct_ptr ,
2006-12-08 21:13:49 +03:00
struct drsuapi_DsGetNCChanges ) ;
WERROR status ;
2010-02-27 12:00:42 +03:00
s - > ndr_struct_ptr = NULL ;
2007-02-12 12:53:52 +03:00
2010-03-08 18:41:43 +03:00
c - > status = dcerpc_drsuapi_DsGetNCChanges_r_recv ( subreq , r ) ;
TALLOC_FREE ( subreq ) ;
2006-12-08 21:13:49 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2007-02-12 14:20:57 +03:00
status = becomeDC_drsuapi_pull_partition_recv ( s , & s - > drsuapi2 , & s - > drsuapi3 , & s - > config_part , r ) ;
2006-12-08 21:13:49 +03:00
if ( ! W_ERROR_IS_OK ( status ) ) {
composite_error ( c , werror_to_ntstatus ( status ) ) ;
return ;
}
talloc_free ( r ) ;
2008-07-16 15:01:56 +04:00
if ( s - > config_part . more_data ) {
2006-12-08 21:22:26 +03:00
becomeDC_drsuapi_pull_partition_send ( s , & s - > drsuapi2 , & s - > drsuapi3 , & s - > config_part ,
2006-12-08 21:13:49 +03:00
becomeDC_drsuapi3_pull_config_recv ) ;
return ;
}
2006-12-05 16:46:27 +03:00
becomeDC_connect_ldap2 ( s ) ;
}
2010-03-08 18:41:43 +03:00
static void becomeDC_drsuapi3_pull_domain_recv ( struct tevent_req * subreq ) ;
2006-12-08 21:29:44 +03:00
static void becomeDC_drsuapi3_pull_domain_send ( struct libnet_BecomeDC_state * s )
{
s - > domain_part . nc . guid = GUID_zero ( ) ;
s - > domain_part . nc . sid = s - > zero_sid ;
s - > domain_part . nc . dn = s - > domain . dn_str ;
s - > domain_part . destination_dsa_guid = s - > drsuapi2 . bind_guid ;
2010-01-17 13:59:56 +03:00
s - > domain_part . replica_flags = DRSUAPI_DRS_WRIT_REP
| DRSUAPI_DRS_INIT_SYNC
| DRSUAPI_DRS_PER_SYNC
| DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS
| DRSUAPI_DRS_NEVER_SYNCED
2015-12-09 07:04:14 +03:00
| DRSUAPI_DRS_USE_COMPRESSION
| DRSUAPI_DRS_GET_ANC ;
2011-11-05 03:22:47 +04:00
if ( s - > critical_only ) {
2015-12-09 07:04:14 +03:00
s - > domain_part . replica_flags | = DRSUAPI_DRS_CRITICAL_ONLY ;
2011-11-05 03:22:47 +04:00
}
2010-02-17 19:01:31 +03:00
if ( s - > rodc_join ) {
s - > schema_part . replica_flags & = ~ DRSUAPI_DRS_WRIT_REP ;
}
2006-12-08 21:29:44 +03:00
2006-12-20 17:49:40 +03:00
s - > domain_part . store_chunk = s - > callbacks . domain_chunk ;
2006-12-08 21:29:44 +03:00
becomeDC_drsuapi_pull_partition_send ( s , & s - > drsuapi2 , & s - > drsuapi3 , & s - > domain_part ,
becomeDC_drsuapi3_pull_domain_recv ) ;
}
2006-12-08 21:52:29 +03:00
static void becomeDC_drsuapi_update_refs_send ( struct libnet_BecomeDC_state * s ,
struct becomeDC_drsuapi * drsuapi ,
2006-12-21 00:54:06 +03:00
struct libnet_BecomeDC_Partition * partition ,
2010-03-08 18:41:43 +03:00
void ( * recv_fn ) ( struct tevent_req * subreq ) ) ;
static void becomeDC_drsuapi2_update_refs_schema_recv ( struct tevent_req * subreq ) ;
2006-12-08 21:52:29 +03:00
2010-03-08 18:41:43 +03:00
static void becomeDC_drsuapi3_pull_domain_recv ( struct tevent_req * subreq )
2006-12-08 21:29:44 +03:00
{
2010-03-08 18:41:43 +03:00
struct libnet_BecomeDC_state * s = tevent_req_callback_data ( subreq ,
2006-12-08 21:29:44 +03:00
struct libnet_BecomeDC_state ) ;
struct composite_context * c = s - > creq ;
2010-02-27 12:00:42 +03:00
struct drsuapi_DsGetNCChanges * r = talloc_get_type_abort ( s - > ndr_struct_ptr ,
2006-12-08 21:29:44 +03:00
struct drsuapi_DsGetNCChanges ) ;
WERROR status ;
2007-02-12 12:53:52 +03:00
2010-02-27 12:00:42 +03:00
s - > ndr_struct_ptr = NULL ;
2006-12-08 21:29:44 +03:00
2010-03-08 18:41:43 +03:00
c - > status = dcerpc_drsuapi_DsGetNCChanges_r_recv ( subreq , r ) ;
TALLOC_FREE ( subreq ) ;
2006-12-08 21:29:44 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2007-02-12 14:20:57 +03:00
status = becomeDC_drsuapi_pull_partition_recv ( s , & s - > drsuapi2 , & s - > drsuapi3 , & s - > domain_part , r ) ;
2006-12-08 21:29:44 +03:00
if ( ! W_ERROR_IS_OK ( status ) ) {
composite_error ( c , werror_to_ntstatus ( status ) ) ;
return ;
}
talloc_free ( r ) ;
2008-07-16 15:01:56 +04:00
if ( s - > domain_part . more_data ) {
2006-12-08 21:29:44 +03:00
becomeDC_drsuapi_pull_partition_send ( s , & s - > drsuapi2 , & s - > drsuapi3 , & s - > domain_part ,
becomeDC_drsuapi3_pull_domain_recv ) ;
return ;
}
2011-11-05 03:22:47 +04:00
if ( s - > critical_only ) {
/* Remove the critical and ANC */
s - > domain_part . replica_flags ^ = DRSUAPI_DRS_CRITICAL_ONLY | DRSUAPI_DRS_GET_ANC ;
s - > critical_only = false ;
becomeDC_drsuapi_pull_partition_send ( s , & s - > drsuapi2 , & s - > drsuapi3 , & s - > domain_part ,
becomeDC_drsuapi3_pull_domain_recv ) ;
return ;
}
2006-12-08 21:52:29 +03:00
becomeDC_drsuapi_update_refs_send ( s , & s - > drsuapi2 , & s - > schema_part ,
becomeDC_drsuapi2_update_refs_schema_recv ) ;
}
static void becomeDC_drsuapi_update_refs_send ( struct libnet_BecomeDC_state * s ,
struct becomeDC_drsuapi * drsuapi ,
2006-12-21 00:54:06 +03:00
struct libnet_BecomeDC_Partition * partition ,
2010-03-08 18:41:43 +03:00
void ( * recv_fn ) ( struct tevent_req * subreq ) )
2006-12-08 21:52:29 +03:00
{
struct composite_context * c = s - > creq ;
struct drsuapi_DsReplicaUpdateRefs * r ;
const char * ntds_guid_str ;
const char * ntds_dns_name ;
2010-03-08 18:41:43 +03:00
struct tevent_req * subreq ;
2006-12-08 21:52:29 +03:00
r = talloc ( s , struct drsuapi_DsReplicaUpdateRefs ) ;
if ( composite_nomem ( r , c ) ) return ;
ntds_guid_str = GUID_string ( r , & s - > dest_dsa . ntds_guid ) ;
if ( composite_nomem ( ntds_guid_str , c ) ) return ;
ntds_dns_name = talloc_asprintf ( r , " %s._msdcs.%s " ,
ntds_guid_str ,
2011-08-24 07:51:01 +04:00
s - > forest . dns_name ) ;
2006-12-08 21:52:29 +03:00
if ( composite_nomem ( ntds_dns_name , c ) ) return ;
r - > in . bind_handle = & drsuapi - > bind_handle ;
r - > in . level = 1 ;
r - > in . req . req1 . naming_context = & partition - > nc ;
r - > in . req . req1 . dest_dsa_dns_name = ntds_dns_name ;
r - > in . req . req1 . dest_dsa_guid = s - > dest_dsa . ntds_guid ;
2010-01-14 06:37:40 +03:00
r - > in . req . req1 . options = DRSUAPI_DRS_ADD_REF | DRSUAPI_DRS_DEL_REF ;
2009-09-09 05:26:50 +04:00
/* I think this is how we mark ourselves as a RODC */
2010-07-16 08:32:42 +04:00
if ( ! lpcfg_parm_bool ( s - > libnet - > lp_ctx , NULL , " repl " , " RODC " , false ) ) {
2010-01-14 06:37:40 +03:00
r - > in . req . req1 . options | = DRSUAPI_DRS_WRIT_REP ;
2009-09-09 05:26:50 +04:00
}
2006-12-08 21:52:29 +03:00
2010-02-27 12:00:42 +03:00
s - > ndr_struct_ptr = r ;
2010-03-08 18:41:43 +03:00
subreq = dcerpc_drsuapi_DsReplicaUpdateRefs_r_send ( s , c - > event_ctx ,
drsuapi - > drsuapi_handle ,
r ) ;
if ( composite_nomem ( subreq , c ) ) return ;
tevent_req_set_callback ( subreq , recv_fn , s ) ;
2006-12-08 21:52:29 +03:00
}
2010-03-08 18:41:43 +03:00
static void becomeDC_drsuapi2_update_refs_config_recv ( struct tevent_req * subreq ) ;
2006-12-08 21:52:29 +03:00
2010-03-08 18:41:43 +03:00
static void becomeDC_drsuapi2_update_refs_schema_recv ( struct tevent_req * subreq )
2006-12-08 21:52:29 +03:00
{
2010-03-08 18:41:43 +03:00
struct libnet_BecomeDC_state * s = tevent_req_callback_data ( subreq ,
2006-12-08 21:52:29 +03:00
struct libnet_BecomeDC_state ) ;
struct composite_context * c = s - > creq ;
2010-02-27 12:00:42 +03:00
struct drsuapi_DsReplicaUpdateRefs * r = talloc_get_type_abort ( s - > ndr_struct_ptr ,
2006-12-08 21:52:29 +03:00
struct drsuapi_DsReplicaUpdateRefs ) ;
2007-02-12 12:53:52 +03:00
2010-02-27 12:00:42 +03:00
s - > ndr_struct_ptr = NULL ;
2006-12-08 21:52:29 +03:00
2010-03-08 18:41:43 +03:00
c - > status = dcerpc_drsuapi_DsReplicaUpdateRefs_r_recv ( subreq , r ) ;
TALLOC_FREE ( subreq ) ;
2006-12-08 21:52:29 +03:00
if ( ! composite_is_ok ( c ) ) return ;
if ( ! W_ERROR_IS_OK ( r - > out . result ) ) {
composite_error ( c , werror_to_ntstatus ( r - > out . result ) ) ;
return ;
}
talloc_free ( r ) ;
becomeDC_drsuapi_update_refs_send ( s , & s - > drsuapi2 , & s - > config_part ,
becomeDC_drsuapi2_update_refs_config_recv ) ;
}
2010-03-08 18:41:43 +03:00
static void becomeDC_drsuapi2_update_refs_domain_recv ( struct tevent_req * subreq ) ;
2006-12-08 21:52:29 +03:00
2010-03-08 18:41:43 +03:00
static void becomeDC_drsuapi2_update_refs_config_recv ( struct tevent_req * subreq )
2006-12-08 21:52:29 +03:00
{
2010-03-08 18:41:43 +03:00
struct libnet_BecomeDC_state * s = tevent_req_callback_data ( subreq ,
2006-12-08 21:52:29 +03:00
struct libnet_BecomeDC_state ) ;
struct composite_context * c = s - > creq ;
2010-02-27 12:00:42 +03:00
struct drsuapi_DsReplicaUpdateRefs * r = talloc_get_type ( s - > ndr_struct_ptr ,
2006-12-08 21:52:29 +03:00
struct drsuapi_DsReplicaUpdateRefs ) ;
2010-02-27 12:00:42 +03:00
s - > ndr_struct_ptr = NULL ;
2010-03-08 18:41:43 +03:00
c - > status = dcerpc_drsuapi_DsReplicaUpdateRefs_r_recv ( subreq , r ) ;
TALLOC_FREE ( subreq ) ;
2006-12-08 21:52:29 +03:00
if ( ! composite_is_ok ( c ) ) return ;
if ( ! W_ERROR_IS_OK ( r - > out . result ) ) {
composite_error ( c , werror_to_ntstatus ( r - > out . result ) ) ;
return ;
}
talloc_free ( r ) ;
becomeDC_drsuapi_update_refs_send ( s , & s - > drsuapi2 , & s - > domain_part ,
becomeDC_drsuapi2_update_refs_domain_recv ) ;
}
2010-03-08 18:41:43 +03:00
static void becomeDC_drsuapi2_update_refs_domain_recv ( struct tevent_req * subreq )
2006-12-08 21:52:29 +03:00
{
2010-03-08 18:41:43 +03:00
struct libnet_BecomeDC_state * s = tevent_req_callback_data ( subreq ,
2006-12-08 21:52:29 +03:00
struct libnet_BecomeDC_state ) ;
struct composite_context * c = s - > creq ;
2010-02-27 12:00:42 +03:00
struct drsuapi_DsReplicaUpdateRefs * r = talloc_get_type ( s - > ndr_struct_ptr ,
2006-12-08 21:52:29 +03:00
struct drsuapi_DsReplicaUpdateRefs ) ;
2010-02-27 12:00:42 +03:00
s - > ndr_struct_ptr = NULL ;
2010-03-08 18:41:43 +03:00
c - > status = dcerpc_drsuapi_DsReplicaUpdateRefs_r_recv ( subreq , r ) ;
TALLOC_FREE ( subreq ) ;
2006-12-08 21:52:29 +03:00
if ( ! composite_is_ok ( c ) ) return ;
if ( ! W_ERROR_IS_OK ( r - > out . result ) ) {
composite_error ( c , werror_to_ntstatus ( r - > out . result ) ) ;
return ;
}
talloc_free ( r ) ;
2006-12-13 01:57:43 +03:00
/* TODO: use DDNS updates and register dns names */
composite_done ( c ) ;
2006-12-08 21:29:44 +03:00
}
2006-12-05 16:46:27 +03:00
static NTSTATUS becomeDC_ldap2_modify_computer ( struct libnet_BecomeDC_state * s )
{
int ret ;
struct ldb_message * msg ;
2010-03-10 22:22:06 +03:00
unsigned int i ;
2006-12-05 16:46:27 +03:00
uint32_t user_account_control = UF_SERVER_TRUST_ACCOUNT |
UF_TRUSTED_FOR_DELEGATION ;
/* as the value is already as we want it to be, we're done */
if ( s - > dest_dsa . user_account_control = = user_account_control ) {
return NT_STATUS_OK ;
}
/* make a 'modify' msg, and only for serverReference */
msg = ldb_msg_new ( s ) ;
NT_STATUS_HAVE_NO_MEMORY ( msg ) ;
msg - > dn = ldb_dn_new ( msg , s - > ldap2 . ldb , s - > dest_dsa . computer_dn_str ) ;
NT_STATUS_HAVE_NO_MEMORY ( msg - > dn ) ;
2010-10-14 19:01:39 +04:00
ret = samdb_msg_add_uint ( s - > ldap2 . ldb , msg , msg , " userAccountControl " ,
user_account_control ) ;
if ( ret ! = LDB_SUCCESS ) {
2006-12-05 16:46:27 +03:00
talloc_free ( msg ) ;
return NT_STATUS_NO_MEMORY ;
}
/* mark all the message elements (should be just one)
as LDB_FLAG_MOD_REPLACE */
for ( i = 0 ; i < msg - > num_elements ; i + + ) {
msg - > elements [ i ] . flags = LDB_FLAG_MOD_REPLACE ;
}
ret = ldb_modify ( s - > ldap2 . ldb , msg ) ;
talloc_free ( msg ) ;
if ( ret ! = LDB_SUCCESS ) {
return NT_STATUS_LDAP ( ret ) ;
}
s - > dest_dsa . user_account_control = user_account_control ;
return NT_STATUS_OK ;
}
static NTSTATUS becomeDC_ldap2_move_computer ( struct libnet_BecomeDC_state * s )
{
int ret ;
struct ldb_dn * old_dn ;
struct ldb_dn * new_dn ;
2010-04-13 10:41:10 +04:00
ret = dsdb_wellknown_dn ( s - > ldap2 . ldb , s ,
ldb_get_default_basedn ( s - > ldap2 . ldb ) ,
2010-01-09 07:57:52 +03:00
DS_GUID_DOMAIN_CONTROLLERS_CONTAINER ,
& new_dn ) ;
2006-12-05 16:46:27 +03:00
if ( ret ! = LDB_SUCCESS ) {
return NT_STATUS_LDAP ( ret ) ;
}
if ( ! ldb_dn_add_child_fmt ( new_dn , " CN=%s " , s - > dest_dsa . netbios_name ) ) {
2010-01-09 07:57:52 +03:00
talloc_free ( new_dn ) ;
2006-12-05 16:46:27 +03:00
return NT_STATUS_NO_MEMORY ;
}
2010-01-09 07:57:52 +03:00
old_dn = ldb_dn_new ( new_dn , s - > ldap2 . ldb , s - > dest_dsa . computer_dn_str ) ;
NT_STATUS_HAVE_NO_MEMORY ( old_dn ) ;
2006-12-05 16:46:27 +03:00
if ( ldb_dn_compare ( old_dn , new_dn ) = = 0 ) {
/* we don't need to rename if the old and new dn match */
2010-01-09 07:57:52 +03:00
talloc_free ( new_dn ) ;
2006-12-05 16:46:27 +03:00
return NT_STATUS_OK ;
}
ret = ldb_rename ( s - > ldap2 . ldb , old_dn , new_dn ) ;
if ( ret ! = LDB_SUCCESS ) {
2010-01-09 07:57:52 +03:00
talloc_free ( new_dn ) ;
2006-12-05 16:46:27 +03:00
return NT_STATUS_LDAP ( ret ) ;
}
2006-12-08 03:09:07 +03:00
s - > dest_dsa . computer_dn_str = ldb_dn_alloc_linearized ( s , new_dn ) ;
NT_STATUS_HAVE_NO_MEMORY ( s - > dest_dsa . computer_dn_str ) ;
2010-01-09 07:57:52 +03:00
talloc_free ( new_dn ) ;
2006-12-08 03:09:07 +03:00
2006-12-05 16:46:27 +03:00
return NT_STATUS_OK ;
}
static void becomeDC_connect_ldap2 ( struct libnet_BecomeDC_state * s )
{
struct composite_context * c = s - > creq ;
c - > status = becomeDC_ldap_connect ( s , & s - > ldap2 ) ;
if ( ! composite_is_ok ( c ) ) return ;
c - > status = becomeDC_ldap2_modify_computer ( s ) ;
if ( ! composite_is_ok ( c ) ) return ;
c - > status = becomeDC_ldap2_move_computer ( s ) ;
2006-12-04 21:20:03 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2011-11-05 03:22:47 +04:00
s - > critical_only = true ;
2006-12-08 21:29:44 +03:00
becomeDC_drsuapi3_pull_domain_send ( s ) ;
2006-12-02 18:35:27 +03:00
}
2006-12-02 15:46:13 +03:00
struct composite_context * libnet_BecomeDC_send ( struct libnet_context * ctx , TALLOC_CTX * mem_ctx , struct libnet_BecomeDC * r )
{
2006-12-02 16:00:20 +03:00
struct composite_context * c ;
2006-12-02 18:35:27 +03:00
struct libnet_BecomeDC_state * s ;
2006-12-03 22:22:51 +03:00
char * tmp_name ;
2006-12-02 16:00:20 +03:00
c = composite_create ( mem_ctx , ctx - > event_ctx ) ;
if ( c = = NULL ) return NULL ;
2006-12-02 18:35:27 +03:00
s = talloc_zero ( c , struct libnet_BecomeDC_state ) ;
if ( composite_nomem ( s , c ) ) return c ;
c - > private_data = s ;
2006-12-03 22:22:51 +03:00
s - > creq = c ;
s - > libnet = ctx ;
2006-12-02 18:35:27 +03:00
2006-12-03 22:22:51 +03:00
/* Domain input */
s - > domain . dns_name = talloc_strdup ( s , r - > in . domain_dns_name ) ;
if ( composite_nomem ( s - > domain . dns_name , c ) ) return c ;
s - > domain . netbios_name = talloc_strdup ( s , r - > in . domain_netbios_name ) ;
if ( composite_nomem ( s - > domain . netbios_name , c ) ) return c ;
2006-12-07 18:29:38 +03:00
s - > domain . sid = dom_sid_dup ( s , r - > in . domain_sid ) ;
if ( composite_nomem ( s - > domain . sid , c ) ) return c ;
2006-12-02 18:35:27 +03:00
2006-12-03 22:22:51 +03:00
/* Source DSA input */
s - > source_dsa . address = talloc_strdup ( s , r - > in . source_dsa_address ) ;
2006-12-02 18:35:27 +03:00
if ( composite_nomem ( s - > source_dsa . address , c ) ) return c ;
2006-12-03 22:22:51 +03:00
/* Destination DSA input */
s - > dest_dsa . netbios_name = talloc_strdup ( s , r - > in . dest_dsa_netbios_name ) ;
if ( composite_nomem ( s - > dest_dsa . netbios_name , c ) ) return c ;
/* Destination DSA dns_name construction */
2007-01-12 20:25:43 +03:00
tmp_name = strlower_talloc ( s , s - > dest_dsa . netbios_name ) ;
2006-12-03 22:22:51 +03:00
if ( composite_nomem ( tmp_name , c ) ) return c ;
2007-09-15 03:21:00 +04:00
tmp_name = talloc_asprintf_append_buffer ( tmp_name , " .%s " , s - > domain . dns_name ) ;
2007-01-12 20:25:43 +03:00
if ( composite_nomem ( tmp_name , c ) ) return c ;
s - > dest_dsa . dns_name = tmp_name ;
2006-12-20 18:34:32 +03:00
/* Callback function pointers */
s - > callbacks = r - > in . callbacks ;
2010-02-17 19:01:31 +03:00
/* RODC join*/
s - > rodc_join = r - > in . rodc_join ;
2006-12-03 22:22:51 +03:00
becomeDC_send_cldap ( s ) ;
2006-12-02 16:00:20 +03:00
return c ;
2006-12-02 15:46:13 +03:00
}
NTSTATUS libnet_BecomeDC_recv ( struct composite_context * c , TALLOC_CTX * mem_ctx , struct libnet_BecomeDC * r )
{
2006-12-02 16:00:20 +03:00
NTSTATUS status ;
status = composite_wait ( c ) ;
2006-12-02 18:35:27 +03:00
ZERO_STRUCT ( r - > out ) ;
2006-12-02 16:00:20 +03:00
talloc_free ( c ) ;
return status ;
2006-12-02 15:46:13 +03:00
}
NTSTATUS libnet_BecomeDC ( struct libnet_context * ctx , TALLOC_CTX * mem_ctx , struct libnet_BecomeDC * r )
{
NTSTATUS status ;
struct composite_context * c ;
c = libnet_BecomeDC_send ( ctx , mem_ctx , r ) ;
status = libnet_BecomeDC_recv ( c , mem_ctx , r ) ;
return status ;
}