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"
2006-12-03 23:37:44 +03:00
# include "lib/ldb/include/ldb.h"
# include "lib/ldb/include/ldb_errors.h"
2007-11-16 22:12:00 +03:00
# include "lib/ldb_wrap.h"
2006-12-04 12:40:16 +03:00
# include "dsdb/samdb/samdb.h"
2006-12-05 16:46:27 +03:00
# include "dsdb/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"
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"
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 : . . .
* highestCommitedUSN : . . .
* supportedSASLMechanisms : GSSAPI
* GSS - SPNEGO
* EXTERNAL
* DIGEST - MD5
* dnsHostName : < dns_host_name >
* ldapServiceName : < domain_dns_name > : < netbios_name > $ @ < REALM >
* serverName : CN = Servers , CN = < site_name > , CN = Sites , CN = Configuration , < domain_partition >
* supportedCapabilities : . . .
* isSyncronized : TRUE
* isGlobalCatalogReady : TRUE
* domainFunctionality : 0
* forestFunctionality : 0
* domainControllerFunctionality : 2
*/
/*
* LDAP search 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 >
* objectCategory : CN = Site , C = Schema , CN = Configuration , < domain_partition >
*/
/***************************************************************
* Add this stage we call the check_options ( ) callback function
* of the caller , to see if he wants us to continue
*
* see : becomeDC_check_options ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* LDAP search 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 >
* userAccoountControl : 4096 < 0x1000 >
*/
/*
* 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 >
* userAccoountControl : 4096 < 0x00001000 >
*/
/*
* 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 >
* userAccoountControl : 4096 < 0x00001000 >
*/
/*
* LDAP modify 2 nd LDAP connection :
*
* see : becomeDC_ldap2_modify_computer ( )
*
* Request ( replace ) :
* CN = < new_dc_netbios_name > , CN = Computers , < domain_partition >
* userAccoountControl : 532480 < 0x82000 >
* Result :
* < success >
*/
/*
* LDAP search 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 ;
struct nbt_cldap_netlogon_5 netlogon5 ;
} 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 ;
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
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 ;
2006-12-02 18:35:27 +03:00
} ;
2007-03-13 17:32:20 +03:00
static void becomeDC_recv_cldap ( struct cldap_request * req ) ;
static void becomeDC_send_cldap ( struct libnet_BecomeDC_state * s )
{
struct composite_context * c = s - > creq ;
struct cldap_request * req ;
s - > cldap . io . in . dest_address = s - > source_dsa . address ;
2007-12-07 04:37:13 +03:00
s - > cldap . io . in . dest_port = lp_cldap_port ( s - > libnet - > lp_ctx ) ;
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 ;
s - > cldap . io . in . version = 6 ;
s - > cldap . sock = cldap_socket_init ( s , s - > libnet - > event_ctx ) ;
if ( composite_nomem ( s - > cldap . sock , c ) ) return ;
req = cldap_netlogon_send ( s - > cldap . sock , & s - > cldap . io ) ;
if ( composite_nomem ( req , c ) ) return ;
req - > async . fn = becomeDC_recv_cldap ;
req - > async . private = s ;
}
2006-12-03 23:37:44 +03:00
static void becomeDC_connect_ldap1 ( struct libnet_BecomeDC_state * s ) ;
2006-12-03 22:22:51 +03:00
static void becomeDC_recv_cldap ( struct cldap_request * req )
{
struct libnet_BecomeDC_state * s = talloc_get_type ( req - > async . private ,
struct libnet_BecomeDC_state ) ;
struct composite_context * c = s - > creq ;
c - > status = cldap_netlogon_recv ( req , s , & s - > cldap . io ) ;
if ( ! composite_is_ok ( c ) ) return ;
s - > cldap . netlogon5 = s - > cldap . io . out . netlogon . logon5 ;
s - > domain . dns_name = s - > cldap . netlogon5 . dns_domain ;
s - > domain . netbios_name = s - > cldap . netlogon5 . domain ;
s - > domain . guid = s - > cldap . netlogon5 . domain_uuid ;
s - > forest . dns_name = s - > cldap . netlogon5 . forest ;
s - > source_dsa . dns_name = s - > cldap . netlogon5 . pdc_dns_name ;
s - > source_dsa . netbios_name = s - > cldap . netlogon5 . pdc_name ;
s - > source_dsa . site_name = s - > cldap . netlogon5 . server_site ;
s - > dest_dsa . site_name = s - > cldap . netlogon5 . client_site ;
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 ) ;
2007-12-07 04:37:13 +03:00
ldap - > ldb = ldb_wrap_connect ( s , s - > libnet - > lp_ctx , url ,
2006-12-03 23:37:44 +03:00
NULL ,
s - > libnet - > cred ,
0 , NULL ) ;
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
ret = ldb_search ( s - > ldap1 . ldb , basedn , LDB_SCOPE_BASE ,
" (objectClass=*) " , attrs , & r ) ;
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 ;
}
talloc_steal ( s , r ) ;
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
ret = ldb_search ( s - > ldap1 . ldb , basedn , LDB_SCOPE_ONELEVEL ,
" (cn=Partitions) " , attrs , & r ) ;
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 ) ;
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
ret = ldb_search ( s - > ldap1 . ldb , basedn , LDB_SCOPE_BASE ,
" (objectClass=*) " , attrs , & r ) ;
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 ) ;
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
ret = ldb_search ( s - > ldap1 . ldb , basedn , LDB_SCOPE_BASE ,
" (objectClass=*) " , attrs , & r ) ;
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 ) ;
ret = ldb_search ( s - > ldap1 . ldb , basedn , LDB_SCOPE_BASE ,
" (objectClass=*) " , attrs , & r ) ;
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 * _1_1_attrs [ ] = {
2006-12-04 00:05:18 +03:00
" 1.1 " ,
NULL
} ;
2007-12-20 02:02:15 +03:00
static const char * fsmo_attrs [ ] = {
2006-12-04 00:05:18 +03:00
" fSMORoleOwner " ,
NULL
} ;
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
basedn = ldb_dn_new_fmt ( s , s - > ldap1 . ldb , " <WKGUID=2fbac1870ade11d297c400c04fd8d5cd,%s> " ,
s - > domain . dn_str ) ;
NT_STATUS_HAVE_NO_MEMORY ( basedn ) ;
ret = ldb_search ( s - > ldap1 . ldb , basedn , LDB_SCOPE_BASE ,
" (objectClass=*) " , _1_1_attrs , & r ) ;
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 ;
}
basedn = talloc_steal ( s , r - > msgs [ 0 ] - > dn ) ;
talloc_free ( r ) ;
ret = ldb_search ( s - > ldap1 . ldb , basedn , LDB_SCOPE_BASE ,
" (objectClass=*) " , fsmo_attrs , & r ) ;
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 12:40:16 +03:00
s - > infrastructure_fsmo . ntds_dn_str = samdb_result_string ( r - > msgs [ 0 ] , " fSMORoleOwner " , NULL ) ;
if ( ! s - > infrastructure_fsmo . ntds_dn_str ) return NT_STATUS_INVALID_NETWORK_RESPONSE ;
talloc_steal ( s , s - > infrastructure_fsmo . ntds_dn_str ) ;
talloc_free ( r ) ;
ntds_dn = ldb_dn_new ( s , s - > ldap1 . ldb , s - > infrastructure_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 ) ;
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 ) ;
2006-12-04 12:40:16 +03:00
ret = ldb_search ( s - > ldap1 . ldb , server_dn , LDB_SCOPE_BASE ,
" (objectClass=*) " , dns_attrs , & r ) ;
if ( ret ! = LDB_SUCCESS ) {
return NT_STATUS_LDAP ( ret ) ;
} else if ( r - > count ! = 1 ) {
talloc_free ( r ) ;
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
s - > infrastructure_fsmo . dns_name = samdb_result_string ( r - > msgs [ 0 ] , " dnsHostName " , NULL ) ;
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
ret = ldb_search ( s - > ldap1 . ldb , ntds_dn , LDB_SCOPE_BASE ,
" (objectClass=*) " , guid_attrs , & r ) ;
if ( ret ! = LDB_SUCCESS ) {
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 ) ;
ret = ldb_search ( s - > ldap1 . ldb , basedn , LDB_SCOPE_BASE ,
" (objectClass=*) " , rid_attrs , & r ) ;
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 ;
}
reference_dn_str = samdb_result_string ( r - > msgs [ 0 ] , " rIDManagerReference " , NULL ) ;
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 ) ;
ret = ldb_search ( s - > ldap1 . ldb , basedn , LDB_SCOPE_BASE ,
" (objectClass=*) " , fsmo_attrs , & r ) ;
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 - > rid_manager_fsmo . ntds_dn_str = samdb_result_string ( r - > msgs [ 0 ] , " fSMORoleOwner " , NULL ) ;
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 ) ;
ret = ldb_search ( s - > ldap1 . ldb , server_dn , LDB_SCOPE_BASE ,
" (objectClass=*) " , dns_attrs , & r ) ;
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 . dns_name = samdb_result_string ( r - > msgs [ 0 ] , " dnsHostName " , NULL ) ;
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 ) ;
ret = ldb_search ( s - > ldap1 . ldb , ntds_dn , LDB_SCOPE_BASE ,
" (objectClass=*) " , guid_attrs , & r ) ;
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 ) ;
ret = ldb_search ( s - > ldap1 . ldb , basedn , LDB_SCOPE_BASE ,
" (objectClass=*) " , NULL , & r ) ;
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 ;
char * filter ;
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 ) ;
filter = talloc_asprintf ( basedn , " (&(|(objectClass=user)(objectClass=computer))(sAMAccountName=%s$)) " ,
s - > dest_dsa . netbios_name ) ;
NT_STATUS_HAVE_NO_MEMORY ( filter ) ;
ret = ldb_search ( s - > ldap1 . ldb , basedn , LDB_SCOPE_SUBTREE ,
filter , attrs , & r ) ;
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 - > dest_dsa . computer_dn_str = samdb_result_string ( r - > msgs [ 0 ] , " distinguishedName " , NULL ) ;
if ( ! s - > dest_dsa . computer_dn_str ) return NT_STATUS_INVALID_NETWORK_RESPONSE ;
talloc_steal ( s , s - > dest_dsa . computer_dn_str ) ;
s - > dest_dsa . user_account_control = samdb_result_uint ( r - > msgs [ 0 ] , " userAccountControl " , 0 ) ;
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 ) ;
ret = ldb_search ( s - > ldap1 . ldb , basedn , LDB_SCOPE_BASE ,
" (objectClass=*) " , NULL , & r ) ;
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 ;
}
2006-12-06 15:08:32 +03:00
server_reference_dn_str = samdb_result_string ( r - > msgs [ 0 ] , " serverReference " , NULL ) ;
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 ) ;
/*
* if the server object belongs to another DC in another domain in the forest ,
* we should not touch this object !
*/
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 */
s - > dest_dsa . server_dn_str = samdb_result_string ( r - > msgs [ 0 ] , " distinguishedName " , NULL ) ;
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 ) ;
ret = ldb_search ( s - > ldap1 . ldb , basedn , LDB_SCOPE_BASE ,
" (objectClass=*) " , attrs , & r ) ;
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 ;
}
server_reference_bl_dn_str = samdb_result_string ( r - > msgs [ 0 ] , " serverReferenceBL " , NULL ) ;
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 */
s - > dest_dsa . server_dn_str = samdb_result_string ( r - > msgs [ 0 ] , " serverReferenceBL " , NULL ) ;
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 ;
uint32_t i ;
/* 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 ) {
2007-12-07 04:37:13 +03:00
if ( lp_parm_bool ( s - > libnet - > lp_ctx , NULL , " become_dc " , " print " , false ) ) {
2007-02-12 12:53:52 +03:00
binding_str = talloc_asprintf ( s , " ncacn_ip_tcp:%s[krb5,print,seal] " , s - > source_dsa . dns_name ) ;
if ( composite_nomem ( binding_str , c ) ) return ;
} else {
binding_str = talloc_asprintf ( s , " ncacn_ip_tcp:%s[krb5,seal] " , s - > source_dsa . dns_name ) ;
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
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 ,
void ( * recv_fn ) ( struct rpc_request * req ) ) ;
static void becomeDC_drsuapi1_bind_recv ( struct rpc_request * req ) ;
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 ;
2007-02-12 13:58:06 +03:00
c - > status = gensec_session_key ( s - > drsuapi1 . pipe - > conn - > security_state . generic_state ,
& 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 ,
void ( * recv_fn ) ( struct rpc_request * req ) )
{
struct composite_context * c = s - > creq ;
struct rpc_request * req ;
2006-12-06 19:04:43 +03:00
struct drsuapi_DsBindInfo28 * bind_info28 ;
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 ;
2006-12-20 19:34:35 +03:00
if ( s - > domain . behavior_version = = 2 ) {
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 ;
bind_info28 - > supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_00100000 ;
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 ;
2006-12-20 19:34:35 +03:00
if ( s - > domain . behavior_version = = 2 ) {
2006-12-06 19:04:43 +03:00
/* TODO: find out how this is really triggered! */
bind_info28 - > u1 = 528 ;
} else {
bind_info28 - > u1 = 516 ;
}
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 ;
req = dcerpc_drsuapi_DsBind_send ( drsuapi - > pipe , s , & drsuapi - > bind_r ) ;
composite_continue_rpc ( c , req , recv_fn , s ) ;
}
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 ;
drsuapi - > remote_info28 . u1 = info24 - > u1 ;
drsuapi - > remote_info28 . repl_epoch = 0 ;
break ;
}
case 28 :
drsuapi - > remote_info28 = drsuapi - > bind_r . out . bind_info - > info . info28 ;
break ;
}
}
return WERR_OK ;
}
2006-12-06 18:29:01 +03:00
static void becomeDC_drsuapi1_add_entry_send ( struct libnet_BecomeDC_state * s ) ;
2006-12-06 15:25:41 +03:00
static void becomeDC_drsuapi1_bind_recv ( struct rpc_request * req )
{
2007-05-16 18:52:54 +04:00
struct libnet_BecomeDC_state * s = talloc_get_type ( req - > async . private_data ,
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
2007-02-12 12:53:52 +03:00
bool print = false ;
if ( req - > p - > conn - > flags & DCERPC_DEBUG_PRINT_OUT ) {
print = true ;
}
2006-12-06 15:25:41 +03:00
c - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! composite_is_ok ( c ) ) return ;
2007-02-12 12:53:52 +03:00
if ( print ) {
NDR_PRINT_OUT_DEBUG ( drsuapi_DsBind , & s - > drsuapi1 . bind_r ) ;
}
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 ) ;
}
static void becomeDC_drsuapi1_add_entry_recv ( struct rpc_request * req ) ;
static void becomeDC_drsuapi1_add_entry_send ( struct libnet_BecomeDC_state * s )
{
struct composite_context * c = s - > creq ;
struct rpc_request * req ;
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 ;
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
/*
* if the schema version indicates w2k3 , then
* also send some w2k3 specific attributes
*/
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 */
2006-12-07 13:04:35 +03:00
num_attrs = 11 ;
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 ;
2008-01-02 07:05:05 +03:00
ndr_err = ndr_push_struct_blob ( & vd [ 0 ] , vd , NULL , 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
2007-01-03 12:58:14 +03:00
attrs [ i ] . attid = DRSUAPI_ATTRIBUTE_ntSecurityDescriptor ;
attrs [ i ] . value_ctr . num_values = 1 ;
attrs [ i ] . value_ctr . values = vs ;
2006-12-07 13:04:35 +03:00
i + + ;
}
/* objectClass: nTDSDSA */
{
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
2007-01-03 12:58:14 +03:00
attrs [ i ] . attid = DRSUAPI_ATTRIBUTE_objectClass ;
attrs [ i ] . value_ctr . num_values = 1 ;
attrs [ i ] . value_ctr . values = vs ;
2006-12-07 13:04:35 +03:00
i + + ;
}
/* objectCategory: CN=NTDS-DSA,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 ;
2007-01-02 22:29:32 +03:00
v [ 0 ] . dn = talloc_asprintf ( vd , " CN=NTDS-DSA,%s " ,
2006-12-07 13:04:35 +03:00
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
2008-01-02 07:05:05 +03:00
ndr_err = ndr_push_struct_blob ( & vd [ 0 ] , vd , NULL , & v [ 0 ] ,
2007-11-09 21:24:51 +03:00
( ndr_push_flags_fn_t ) ndr_push_drsuapi_DsReplicaObjectIdentifier3 ) ;
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
2007-01-03 12:58:14 +03:00
attrs [ i ] . attid = DRSUAPI_ATTRIBUTE_objectCategory ;
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
2008-01-02 07:05:05 +03:00
ndr_err = ndr_push_struct_blob ( & vd [ 0 ] , vd , NULL , v , ( ndr_push_flags_fn_t ) ndr_push_GUID ) ;
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 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
2007-01-03 12:58:14 +03:00
attrs [ i ] . attid = DRSUAPI_ATTRIBUTE_invocationId ;
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 ;
2008-01-02 07:05:05 +03:00
ndr_err = ndr_push_struct_blob ( & vd [ 0 ] , vd , NULL , & v [ 0 ] ,
2007-11-09 21:24:51 +03:00
( ndr_push_flags_fn_t ) ndr_push_drsuapi_DsReplicaObjectIdentifier3 ) ;
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
2008-01-02 07:05:05 +03:00
ndr_err = ndr_push_struct_blob ( & vd [ 1 ] , vd , NULL , & v [ 1 ] ,
2007-11-09 21:24:51 +03:00
( ndr_push_flags_fn_t ) ndr_push_drsuapi_DsReplicaObjectIdentifier3 ) ;
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
2008-01-02 07:05:05 +03:00
ndr_err = ndr_push_struct_blob ( & vd [ 2 ] , vd , NULL , & v [ 2 ] ,
2007-11-09 21:24:51 +03:00
( ndr_push_flags_fn_t ) ndr_push_drsuapi_DsReplicaObjectIdentifier3 ) ;
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
2007-01-03 12:58:14 +03:00
attrs [ i ] . attid = DRSUAPI_ATTRIBUTE_hasMasterNCs ;
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 ;
2008-01-02 07:05:05 +03:00
ndr_err = ndr_push_struct_blob ( & vd [ 0 ] , vd , NULL , & v [ 0 ] ,
2007-11-09 21:24:51 +03:00
( ndr_push_flags_fn_t ) ndr_push_drsuapi_DsReplicaObjectIdentifier3 ) ;
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
2008-01-02 07:05:05 +03:00
ndr_err = ndr_push_struct_blob ( & vd [ 1 ] , vd , NULL , & v [ 1 ] ,
2007-11-09 21:24:51 +03:00
( ndr_push_flags_fn_t ) ndr_push_drsuapi_DsReplicaObjectIdentifier3 ) ;
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
2008-01-02 07:05:05 +03:00
ndr_err = ndr_push_struct_blob ( & vd [ 2 ] , vd , NULL , & v [ 2 ] ,
2007-11-09 21:24:51 +03:00
( ndr_push_flags_fn_t ) ndr_push_drsuapi_DsReplicaObjectIdentifier3 ) ;
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
2007-01-03 12:58:14 +03:00
attrs [ i ] . attid = DRSUAPI_ATTRIBUTE_msDS_hasMasterNCs ;
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 ;
2008-01-06 00:36:33 +03:00
ndr_err = ndr_push_struct_blob ( & vd [ 0 ] , vd , NULL , & v [ 0 ] ,
2007-11-09 21:24:51 +03:00
( ndr_push_flags_fn_t ) ndr_push_drsuapi_DsReplicaObjectIdentifier3 ) ;
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
2007-01-03 12:58:14 +03:00
attrs [ i ] . attid = DRSUAPI_ATTRIBUTE_dMDLocation ;
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 ;
2008-01-06 00:36:33 +03:00
ndr_err = ndr_push_struct_blob ( & vd [ 0 ] , vd , NULL , & v [ 0 ] ,
2007-11-09 21:24:51 +03:00
( ndr_push_flags_fn_t ) ndr_push_drsuapi_DsReplicaObjectIdentifier3 ) ;
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
2007-01-03 12:58:14 +03:00
attrs [ i ] . attid = DRSUAPI_ATTRIBUTE_msDS_HasDomainNCs ;
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
2007-01-02 17:14:35 +03:00
SIVAL ( vd [ 0 ] . data , 0 , DS_BEHAVIOR_WIN2003 ) ;
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
2007-01-03 12:58:14 +03:00
attrs [ i ] . attid = DRSUAPI_ATTRIBUTE_msDS_Behavior_Version ;
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
2007-01-02 17:14:35 +03:00
SIVAL ( vd [ 0 ] . data , 0 , SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE ) ;
2007-01-03 12:58:14 +03:00
vs [ 0 ] . blob = & vd [ 0 ] ;
2006-12-07 13:04:35 +03:00
2007-01-03 12:58:14 +03:00
attrs [ i ] . attid = DRSUAPI_ATTRIBUTE_systemFlags ;
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 ;
2008-01-06 00:36:33 +03:00
ndr_err = ndr_push_struct_blob ( & vd [ 0 ] , vd , NULL , & v [ 0 ] ,
2007-11-09 21:24:51 +03:00
( ndr_push_flags_fn_t ) ndr_push_drsuapi_DsReplicaObjectIdentifier3 ) ;
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
2007-01-03 12:58:14 +03:00
attrs [ i ] . attid = DRSUAPI_ATTRIBUTE_serverReference ;
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
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 ;
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 . unknown1 = 0x00000000 ;
2006-12-07 13:04:35 +03:00
r - > in . req . req2 . first_object . object . attribute_ctr . num_attributes = num_attrs ;
r - > in . req . req2 . first_object . object . attribute_ctr . attributes = attrs ;
2006-12-06 18:29:01 +03:00
req = dcerpc_drsuapi_DsAddEntry_send ( s - > drsuapi1 . pipe , r , r ) ;
composite_continue_rpc ( c , req , becomeDC_drsuapi1_add_entry_recv , s ) ;
}
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
2006-12-06 18:29:01 +03:00
static void becomeDC_drsuapi1_add_entry_recv ( struct rpc_request * req )
{
2007-05-16 18:52:54 +04:00
struct libnet_BecomeDC_state * s = talloc_get_type ( req - > async . private_data ,
2006-12-06 18:29:01 +03:00
struct libnet_BecomeDC_state ) ;
struct composite_context * c = s - > creq ;
struct drsuapi_DsAddEntry * r = talloc_get_type ( req - > ndr . struct_ptr ,
struct drsuapi_DsAddEntry ) ;
2007-02-23 14:04:05 +03:00
char * binding_str ;
2007-02-12 12:53:52 +03:00
bool print = false ;
if ( req - > p - > conn - > flags & DCERPC_DEBUG_PRINT_OUT ) {
print = true ;
}
2006-12-06 18:29:01 +03:00
c - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! composite_is_ok ( c ) ) return ;
2007-02-12 12:53:52 +03:00
if ( print ) {
NDR_PRINT_OUT_DEBUG ( drsuapi_DsAddEntry , r ) ;
}
2006-12-06 18:29:01 +03:00
if ( ! W_ERROR_IS_OK ( r - > out . result ) ) {
composite_error ( c , werror_to_ntstatus ( r - > out . result ) ) ;
return ;
}
2006-12-07 22:18:55 +03:00
if ( r - > out . level = = 3 ) {
if ( r - > out . ctr . ctr3 . count ! = 1 ) {
WERROR status ;
if ( r - > out . ctr . ctr3 . level ! = 1 ) {
composite_error ( c , NT_STATUS_INVALID_NETWORK_RESPONSE ) ;
return ;
}
if ( ! r - > out . ctr . ctr3 . error ) {
composite_error ( c , NT_STATUS_INVALID_NETWORK_RESPONSE ) ;
return ;
}
status = r - > out . ctr . ctr3 . error - > info1 . status ;
if ( ! r - > out . ctr . ctr3 . error - > info1 . info ) {
composite_error ( c , werror_to_ntstatus ( status ) ) ;
return ;
}
/* see if we can get a more detailed error */
switch ( r - > out . ctr . ctr3 . error - > info1 . level ) {
case 1 :
status = r - > out . ctr . ctr3 . error - > info1 . info - > error1 . status ;
break ;
case 4 :
case 5 :
case 6 :
case 7 :
status = r - > out . ctr . ctr3 . error - > info1 . info - > errorX . status ;
break ;
}
composite_error ( c , werror_to_ntstatus ( status ) ) ;
return ;
}
s - > dest_dsa . ntds_guid = r - > out . ctr . ctr3 . objects [ 0 ] . guid ;
} else if ( r - > out . level = = 2 ) {
if ( r - > out . ctr . ctr2 . count ! = 1 ) {
composite_error ( c , werror_to_ntstatus ( r - > out . ctr . ctr2 . error . status ) ) ;
return ;
}
s - > dest_dsa . ntds_guid = r - > out . ctr . ctr2 . objects [ 0 ] . guid ;
} 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 ;
/* w2k3 uses the same assoc_group_id as on the first connection, so we do */
s - > drsuapi2 . binding - > assoc_group_id = s - > drsuapi1 . pipe - > assoc_group_id ;
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
}
2006-12-07 22:50:46 +03:00
static void becomeDC_drsuapi2_bind_recv ( struct rpc_request * req ) ;
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 ;
2007-02-12 13:58:06 +03:00
c - > status = gensec_session_key ( s - > drsuapi2 . pipe - > conn - > security_state . generic_state ,
& 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 ) ;
static void becomeDC_drsuapi2_bind_recv ( struct rpc_request * req )
{
2007-05-16 18:52:54 +04:00
struct libnet_BecomeDC_state * s = talloc_get_type ( req - > async . private_data ,
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 ;
2006-12-07 23:11:00 +03:00
WERROR status ;
2006-12-07 22:50:46 +03:00
2007-02-12 12:53:52 +03:00
bool print = false ;
if ( req - > p - > conn - > flags & DCERPC_DEBUG_PRINT_OUT ) {
print = true ;
}
2006-12-07 22:50:46 +03:00
c - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! composite_is_ok ( c ) ) return ;
2007-02-12 12:53:52 +03:00
if ( print ) {
NDR_PRINT_OUT_DEBUG ( drsuapi_DsBind , & s - > drsuapi2 . bind_r ) ;
}
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
2007-02-23 14:04:05 +03:00
/* w2k3 uses the same assoc_group_id as on the first connection, so we do */
s - > drsuapi3 . binding - > assoc_group_id = s - > drsuapi1 . pipe - > assoc_group_id ;
/* w2k3 uses the concurrent multiplex feature on the 3rd connection, so we do */
s - > drsuapi3 . binding - > flags | = DCERPC_CONCURRENT_MULTIPLEX ;
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 ;
2007-02-12 13:58:06 +03:00
c - > status = gensec_session_key ( s - > drsuapi3 . pipe - > conn - > security_state . generic_state ,
& 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 ,
2006-12-08 03:16:36 +03:00
void ( * recv_fn ) ( struct rpc_request * req ) )
{
struct composite_context * c = s - > creq ;
struct rpc_request * req ;
struct drsuapi_DsGetNCChanges * r ;
r = talloc ( s , struct drsuapi_DsGetNCChanges ) ;
if ( composite_nomem ( r , c ) ) return ;
2007-01-12 17:26:08 +03:00
r - > in . level = talloc ( r , int32_t ) ;
if ( composite_nomem ( r - > in . level , c ) ) return ;
r - > out . level = talloc ( r , int32_t ) ;
if ( composite_nomem ( r - > out . level , c ) ) return ;
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 ) {
2007-01-12 17:26:08 +03:00
* r - > in . level = 8 ;
2006-12-08 03:16:36 +03:00
r - > in . req . req8 . destination_dsa_guid = partition - > destination_dsa_guid ;
2006-12-08 20:34:15 +03:00
r - > in . req . req8 . source_dsa_invocation_id = partition - > source_dsa_invocation_id ;
2006-12-08 03:16:36 +03:00
r - > in . req . req8 . naming_context = & partition - > nc ;
r - > in . req . req8 . highwatermark = partition - > highwatermark ;
2006-12-21 00:54:06 +03:00
r - > in . req . req8 . uptodateness_vector = NULL ;
2006-12-08 03:16:36 +03:00
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 . unknown4 = 0 ;
r - > in . req . req8 . h1 = 0 ;
r - > in . req . req8 . unique_ptr1 = 0 ;
r - > in . req . req8 . unique_ptr2 = 0 ;
r20251: I found out that the oid-prefix to uint32-id-prefix mapping is transferred
in replication replies, but I don't know the exact encoding.
for example the oids are transferred as:
2.5.4 => uint8_t v[] = { 0x55, 0x04 };
2.5.5 => uint8_t v[] = { 0x55, 0x05 };
2.5.6 => uint8_t v[] = { 0x55, 0x06 };
2.5.18 => uint8_t v[] = { 0x55, 0x12 };
2.5.20 => uint8_t v[] = { 0x55, 0x14 };
2.5.21 => uint8_t v[] = { 0x55, 0x15 };
1.2.840.113556.1.2 => uint8_t v[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x14, 0x01, 0x02 };
1.2.840.113556.1.3 => uint8_t v[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x14, 0x01, 0x03 };
1.2.840.113556.1.4 => uint8_t v[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x14, 0x01, 0x04 };
1.2.840.113556.1.5 => uint8_t v[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x14, 0x01, 0x05 };
1.2.840.113556.1.5.7000 => uint8_t v[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x14, 0x01, 0x05, 0xb6, 0x58 };
1.2.840.113549.1.9 => uint8_t v[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09 };
2.16.840.1.113730.3 => uint8_t v[] = { 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x03 };
2.16.840.1.113730.3.1 => uint8_t v[] = { 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x03, 0x01 };
2.16.840.1.113730.3.2 => uint8_t v[] = { 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x03, 0x02 };
0.9.2342.19200300.100.1 => uint8_t v[] = { 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01 };
0.9.2342.19200300.100.4 => uint8_t v[] = { 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x04 };
1.3.6.1.4.1.250.1 => uint8_t v[] = { 0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0x7a, 0x01 };
1.3.6.1.4.1.1466.101.119=> uint8_t v[] = { 0x2b, 0x06, 0x01, 0x04, 0x01, 0x8b, 0x3a, 0x65, 0x77 };
if someone knows how the encoding works, please tell me:-)
I assume some ASN.1 encoding...
metze
(This used to be commit aa720a15319392fee5c532959192d0df5bf4c718)
2006-12-19 16:38:42 +03:00
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 {
2007-01-12 17:26:08 +03:00
* r - > in . level = 5 ;
2006-12-08 03:16:36 +03:00
r - > in . req . req5 . destination_dsa_guid = partition - > destination_dsa_guid ;
2006-12-08 20:34:15 +03:00
r - > in . req . req5 . source_dsa_invocation_id = partition - > source_dsa_invocation_id ;
2006-12-08 03:16:36 +03:00
r - > in . req . req5 . naming_context = & partition - > nc ;
r - > in . req . req5 . highwatermark = partition - > highwatermark ;
2006-12-21 00:54:06 +03:00
r - > in . req . req5 . uptodateness_vector = NULL ;
2006-12-08 03:16:36 +03:00
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 . unknown4 = 0 ;
r - > in . req . req5 . h1 = 0 ;
}
/*
* 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 .
*/
2007-02-23 14:04:05 +03:00
req = dcerpc_drsuapi_DsGetNCChanges_send ( drsuapi_p - > pipe , r , r ) ;
2006-12-08 03:16:36 +03:00
composite_continue_rpc ( c , req , recv_fn , s ) ;
}
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 )
{
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 ;
struct GUID * source_dsa_guid ;
struct GUID * source_dsa_invocation_id ;
struct drsuapi_DsReplicaHighWaterMark * new_highwatermark ;
2006-12-21 00:54:06 +03:00
NTSTATUS nt_status ;
2006-12-08 21:06:38 +03:00
if ( ! W_ERROR_IS_OK ( r - > out . result ) ) {
return r - > out . result ;
}
2007-01-11 07:12:35 +03:00
if ( * r - > out . level = = 1 ) {
2006-12-21 00:54:06 +03:00
ctr_level = 1 ;
2006-12-08 21:06:38 +03:00
ctr1 = & r - > out . ctr . ctr1 ;
2007-01-11 07:12:35 +03:00
} else if ( * r - > out . level = = 2 ) {
2006-12-21 00:54:06 +03:00
ctr_level = 1 ;
2006-12-08 21:06:38 +03:00
ctr1 = r - > out . ctr . ctr2 . ctr . mszip1 . ctr1 ;
2007-01-11 07:12:35 +03:00
} else if ( * r - > out . level = = 6 ) {
2006-12-21 00:54:06 +03:00
ctr_level = 6 ;
2006-12-08 21:06:38 +03:00
ctr6 = & r - > out . ctr . ctr6 ;
2007-01-11 07:12:35 +03:00
} else if ( * r - > out . level = = 7 & &
2006-12-08 21:06:38 +03:00
r - > out . ctr . ctr7 . level = = 6 & &
r - > out . ctr . ctr7 . type = = DRSUAPI_COMPRESSION_TYPE_MSZIP ) {
2006-12-21 00:54:06 +03:00
ctr_level = 6 ;
2006-12-08 21:06:38 +03:00
ctr6 = r - > out . ctr . ctr7 . ctr . mszip6 . ctr6 ;
} else {
return WERR_BAD_NET_RESP ;
}
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 ;
break ;
case 6 :
source_dsa_guid = & ctr6 - > source_dsa_guid ;
source_dsa_invocation_id = & ctr6 - > source_dsa_invocation_id ;
new_highwatermark = & ctr6 - > new_highwatermark ;
break ;
}
partition - > highwatermark = * new_highwatermark ;
partition - > source_dsa_guid = * source_dsa_guid ;
partition - > source_dsa_invocation_id = * source_dsa_invocation_id ;
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 ;
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
nt_status = partition - > store_chunk ( s - > callbacks . private_data , & s - > _sc ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
return ntstatus_to_werror ( nt_status ) ;
2006-12-20 17:49:40 +03:00
}
2006-12-08 21:06:38 +03:00
return WERR_OK ;
}
2006-12-08 21:08:30 +03:00
static void becomeDC_drsuapi3_pull_schema_recv ( struct rpc_request * req ) ;
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
2006-12-08 21:22:26 +03:00
s - > schema_part . replica_flags = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
| DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
| DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS
| DRSUAPI_DS_REPLICA_NEIGHBOUR_FULL_IN_PROGRESS
| DRSUAPI_DS_REPLICA_NEIGHBOUR_NEVER_SYNCED
| DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES ;
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 ) ;
2006-12-08 03:16:36 +03:00
static void becomeDC_drsuapi3_pull_schema_recv ( struct rpc_request * req )
{
2007-05-16 18:52:54 +04:00
struct libnet_BecomeDC_state * s = talloc_get_type ( req - > async . private_data ,
2006-12-08 03:16:36 +03:00
struct libnet_BecomeDC_state ) ;
struct composite_context * c = s - > creq ;
struct drsuapi_DsGetNCChanges * r = talloc_get_type ( req - > ndr . struct_ptr ,
struct drsuapi_DsGetNCChanges ) ;
2006-12-08 21:06:38 +03:00
WERROR status ;
2006-12-08 03:16:36 +03:00
2007-02-12 12:53:52 +03:00
bool print = false ;
if ( req - > p - > conn - > flags & DCERPC_DEBUG_PRINT_OUT ) {
print = true ;
}
2006-12-08 03:16:36 +03:00
c - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! composite_is_ok ( c ) ) return ;
2007-02-12 12:53:52 +03:00
if ( print ) {
NDR_PRINT_OUT_DEBUG ( drsuapi_DsGetNCChanges , r ) ;
}
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 ) ;
2006-12-08 21:22:26 +03:00
if ( s - > schema_part . highwatermark . tmp_highest_usn > s - > schema_part . highwatermark . highest_usn ) {
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 ) ;
}
static void becomeDC_drsuapi3_pull_config_recv ( struct rpc_request * req ) ;
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
2006-12-08 21:22:26 +03:00
s - > config_part . replica_flags = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
| DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
| DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS
| DRSUAPI_DS_REPLICA_NEIGHBOUR_FULL_IN_PROGRESS
| DRSUAPI_DS_REPLICA_NEIGHBOUR_NEVER_SYNCED
| DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES ;
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 ) ;
}
static void becomeDC_drsuapi3_pull_config_recv ( struct rpc_request * req )
{
2007-05-16 18:52:54 +04:00
struct libnet_BecomeDC_state * s = talloc_get_type ( req - > async . private_data ,
2006-12-08 21:13:49 +03:00
struct libnet_BecomeDC_state ) ;
struct composite_context * c = s - > creq ;
struct drsuapi_DsGetNCChanges * r = talloc_get_type ( req - > ndr . struct_ptr ,
struct drsuapi_DsGetNCChanges ) ;
WERROR status ;
2007-02-12 12:53:52 +03:00
bool print = false ;
if ( req - > p - > conn - > flags & DCERPC_DEBUG_PRINT_OUT ) {
print = true ;
}
2006-12-08 21:13:49 +03:00
c - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! composite_is_ok ( c ) ) return ;
2007-02-12 12:53:52 +03:00
if ( print ) {
NDR_PRINT_OUT_DEBUG ( drsuapi_DsGetNCChanges , r ) ;
}
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 ) ;
2006-12-08 21:22:26 +03:00
if ( s - > config_part . highwatermark . tmp_highest_usn > s - > config_part . highwatermark . highest_usn ) {
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 ) ;
}
2006-12-08 21:29:44 +03:00
static void becomeDC_drsuapi3_pull_domain_recv ( struct rpc_request * req ) ;
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 ;
s - > domain_part . replica_flags = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
| DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
| DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS
| DRSUAPI_DS_REPLICA_NEIGHBOUR_FULL_IN_PROGRESS
| DRSUAPI_DS_REPLICA_NEIGHBOUR_NEVER_SYNCED
| DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES ;
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 ,
2006-12-08 21:52:29 +03:00
void ( * recv_fn ) ( struct rpc_request * req ) ) ;
static void becomeDC_drsuapi2_update_refs_schema_recv ( struct rpc_request * req ) ;
2006-12-08 21:29:44 +03:00
static void becomeDC_drsuapi3_pull_domain_recv ( struct rpc_request * req )
{
2007-05-16 18:52:54 +04:00
struct libnet_BecomeDC_state * s = talloc_get_type ( req - > async . private_data ,
2006-12-08 21:29:44 +03:00
struct libnet_BecomeDC_state ) ;
struct composite_context * c = s - > creq ;
struct drsuapi_DsGetNCChanges * r = talloc_get_type ( req - > ndr . struct_ptr ,
struct drsuapi_DsGetNCChanges ) ;
WERROR status ;
2007-02-12 12:53:52 +03:00
bool print = false ;
if ( req - > p - > conn - > flags & DCERPC_DEBUG_PRINT_OUT ) {
print = true ;
}
2006-12-08 21:29:44 +03:00
c - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! composite_is_ok ( c ) ) return ;
2007-02-12 12:53:52 +03:00
if ( print ) {
NDR_PRINT_OUT_DEBUG ( drsuapi_DsGetNCChanges , r ) ;
}
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 ) ;
if ( s - > domain_part . highwatermark . tmp_highest_usn > s - > domain_part . highwatermark . highest_usn ) {
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 ,
2006-12-08 21:52:29 +03:00
void ( * recv_fn ) ( struct rpc_request * req ) )
{
struct composite_context * c = s - > creq ;
struct rpc_request * req ;
struct drsuapi_DsReplicaUpdateRefs * r ;
const char * ntds_guid_str ;
const char * ntds_dns_name ;
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 ,
s - > domain . dns_name ) ;
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 ;
r - > in . req . req1 . options = DRSUAPI_DS_REPLICA_UPDATE_ADD_REFERENCE
| DRSUAPI_DS_REPLICA_UPDATE_DELETE_REFERENCE
| DRSUAPI_DS_REPLICA_UPDATE_0x00000010 ;
req = dcerpc_drsuapi_DsReplicaUpdateRefs_send ( drsuapi - > pipe , r , r ) ;
composite_continue_rpc ( c , req , recv_fn , s ) ;
}
static void becomeDC_drsuapi2_update_refs_config_recv ( struct rpc_request * req ) ;
static void becomeDC_drsuapi2_update_refs_schema_recv ( struct rpc_request * req )
{
2007-05-16 18:52:54 +04:00
struct libnet_BecomeDC_state * s = talloc_get_type ( req - > async . private_data ,
2006-12-08 21:52:29 +03:00
struct libnet_BecomeDC_state ) ;
struct composite_context * c = s - > creq ;
struct drsuapi_DsReplicaUpdateRefs * r = talloc_get_type ( req - > ndr . struct_ptr ,
struct drsuapi_DsReplicaUpdateRefs ) ;
2007-02-12 12:53:52 +03:00
bool print = false ;
if ( req - > p - > conn - > flags & DCERPC_DEBUG_PRINT_OUT ) {
print = true ;
}
2006-12-08 21:52:29 +03:00
c - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! composite_is_ok ( c ) ) return ;
2007-02-12 12:53:52 +03:00
if ( print ) {
NDR_PRINT_OUT_DEBUG ( drsuapi_DsReplicaUpdateRefs , r ) ;
}
2006-12-08 21:52:29 +03:00
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 ) ;
}
static void becomeDC_drsuapi2_update_refs_domain_recv ( struct rpc_request * req ) ;
static void becomeDC_drsuapi2_update_refs_config_recv ( struct rpc_request * req )
{
2007-05-16 18:52:54 +04:00
struct libnet_BecomeDC_state * s = talloc_get_type ( req - > async . private_data ,
2006-12-08 21:52:29 +03:00
struct libnet_BecomeDC_state ) ;
struct composite_context * c = s - > creq ;
struct drsuapi_DsReplicaUpdateRefs * r = talloc_get_type ( req - > ndr . struct_ptr ,
struct drsuapi_DsReplicaUpdateRefs ) ;
c - > status = dcerpc_ndr_request_recv ( req ) ;
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 ) ;
}
static void becomeDC_drsuapi2_update_refs_domain_recv ( struct rpc_request * req )
{
2007-05-16 18:52:54 +04:00
struct libnet_BecomeDC_state * s = talloc_get_type ( req - > async . private_data ,
2006-12-08 21:52:29 +03:00
struct libnet_BecomeDC_state ) ;
struct composite_context * c = s - > creq ;
struct drsuapi_DsReplicaUpdateRefs * r = talloc_get_type ( req - > ndr . struct_ptr ,
struct drsuapi_DsReplicaUpdateRefs ) ;
c - > status = dcerpc_ndr_request_recv ( req ) ;
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 ;
uint32_t i ;
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 ) ;
ret = ldb_msg_add_fmt ( msg , " userAccountControl " , " %u " , user_account_control ) ;
if ( ret ! = 0 ) {
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_result * r ;
struct ldb_dn * basedn ;
struct ldb_dn * old_dn ;
struct ldb_dn * new_dn ;
2007-12-20 02:02:15 +03:00
static const char * _1_1_attrs [ ] = {
2006-12-05 16:46:27 +03:00
" 1.1 " ,
NULL
} ;
basedn = ldb_dn_new_fmt ( s , s - > ldap2 . ldb , " <WKGUID=a361b2ffffd211d1aa4b00c04fd7d83a,%s> " ,
s - > domain . dn_str ) ;
NT_STATUS_HAVE_NO_MEMORY ( basedn ) ;
ret = ldb_search ( s - > ldap2 . ldb , basedn , LDB_SCOPE_BASE ,
" (objectClass=*) " , _1_1_attrs , & r ) ;
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 ;
}
old_dn = ldb_dn_new ( r , s - > ldap2 . ldb , s - > dest_dsa . computer_dn_str ) ;
NT_STATUS_HAVE_NO_MEMORY ( old_dn ) ;
new_dn = r - > msgs [ 0 ] - > dn ;
if ( ! ldb_dn_add_child_fmt ( new_dn , " CN=%s " , s - > dest_dsa . netbios_name ) ) {
talloc_free ( r ) ;
return NT_STATUS_NO_MEMORY ;
}
if ( ldb_dn_compare ( old_dn , new_dn ) = = 0 ) {
/* we don't need to rename if the old and new dn match */
talloc_free ( r ) ;
return NT_STATUS_OK ;
}
ret = ldb_rename ( s - > ldap2 . ldb , old_dn , new_dn ) ;
if ( ret ! = LDB_SUCCESS ) {
2006-12-08 03:09:07 +03:00
talloc_free ( r ) ;
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 ) ;
talloc_free ( r ) ;
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 ;
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 ;
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 ;
}