2006-12-13 02:23:50 +03:00
/*
Unix SMB / CIFS implementation .
libnet_BecomeDC ( ) tests
Copyright ( C ) Stefan ( metze ) Metzmacher 2006
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( 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
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
# include "lib/cmdline/popt_common.h"
# include "torture/torture.h"
# include "torture/rpc/rpc.h"
# include "libnet/libnet.h"
# include "lib/events/events.h"
2006-12-23 00:31:57 +03:00
# include "dsdb/samdb/samdb.h"
2006-12-13 02:23:50 +03:00
# define TORTURE_NETBIOS_NAME "smbtorturedc"
2006-12-23 00:31:57 +03:00
struct test_become_dc_state {
struct libnet_context * ctx ;
struct test_join * tj ;
struct cli_credentials * machine_account ;
struct dsdb_schema * schema ;
} ;
2006-12-20 19:34:35 +03:00
static NTSTATUS test_become_dc_check_options ( void * private_data ,
2006-12-21 00:14:44 +03:00
const struct libnet_BecomeDC_CheckOptions * o )
2006-12-20 18:34:32 +03:00
{
2006-12-20 19:34:35 +03:00
DEBUG ( 0 , ( " Become DC of Domain[%s]/[%s] \n " ,
o - > domain - > netbios_name , o - > domain - > dns_name ) ) ;
DEBUG ( 0 , ( " Promotion Partner is Server[%s] from Site[%s] \n " ,
o - > source_dsa - > dns_name , o - > source_dsa - > site_name ) ) ;
DEBUG ( 0 , ( " Options:crossRef behavior_version[%u] \n "
" \t schema object_version[%u] \n "
" \t domain behavior_version[%u] \n "
" \t domain w2k3_update_revision[%u] \n " ,
o - > forest - > crossref_behavior_version ,
o - > forest - > schema_object_version ,
o - > domain - > behavior_version ,
o - > domain - > w2k3_update_revision ) ) ;
2006-12-20 18:34:32 +03:00
return NT_STATUS_OK ;
}
2006-12-21 00:14:44 +03:00
static NTSTATUS test_become_dc_prepare_db ( void * private_data ,
const struct libnet_BecomeDC_PrepareDB * p )
{
2006-12-23 00:31:57 +03:00
struct test_become_dc_state * s = talloc_get_type ( private_data , struct test_become_dc_state ) ;
2006-12-21 00:14:44 +03:00
DEBUG ( 0 , ( " New Server[%s] in Site[%s] \n " ,
p - > dest_dsa - > dns_name , p - > dest_dsa - > site_name ) ) ;
DEBUG ( 0 , ( " DSA Instance [%s] \n "
" \t objectGUID[%s] \n "
" \t invocationId[%s] \n " ,
p - > dest_dsa - > ntds_dn_str ,
2006-12-23 00:31:57 +03:00
GUID_string ( s , & p - > dest_dsa - > ntds_guid ) ,
GUID_string ( s , & p - > dest_dsa - > invocation_id ) ) ) ;
2006-12-21 00:14:44 +03:00
DEBUG ( 0 , ( " Schema Partition[%s] \n " ,
p - > forest - > schema_dn_str ) ) ;
DEBUG ( 0 , ( " Config Partition[%s] \n " ,
p - > forest - > config_dn_str ) ) ;
DEBUG ( 0 , ( " Domain Partition[%s] \n " ,
p - > domain - > dn_str ) ) ;
return NT_STATUS_OK ;
}
2006-12-23 00:31:57 +03:00
static NTSTATUS test_become_dc_schema_chunk ( void * private_data ,
const struct libnet_BecomeDC_StoreChunk * c )
{
struct test_become_dc_state * s = talloc_get_type ( private_data , struct test_become_dc_state ) ;
WERROR status ;
const struct drsuapi_DsReplicaOIDMapping_Ctr * mapping_ctr ;
uint32_t total_object_count ;
uint32_t object_count ;
struct drsuapi_DsReplicaObjectListItemEx * first_object ;
struct drsuapi_DsReplicaObjectListItemEx * cur ;
switch ( c - > ctr_level ) {
case 1 :
mapping_ctr = & c - > ctr1 - > mapping_ctr ;
total_object_count = c - > ctr1 - > total_object_count ;
object_count = c - > ctr1 - > object_count ;
first_object = c - > ctr1 - > first_object ;
break ;
case 6 :
mapping_ctr = & c - > ctr6 - > mapping_ctr ;
total_object_count = c - > ctr6 - > total_object_count ;
object_count = c - > ctr6 - > object_count ;
first_object = c - > ctr6 - > first_object ;
break ;
default :
return NT_STATUS_INVALID_PARAMETER ;
}
if ( total_object_count ) {
DEBUG ( 0 , ( " Schema-DN[%s] objects[%u/%u] \n " ,
c - > partition - > nc . dn , object_count , total_object_count ) ) ;
} else {
DEBUG ( 0 , ( " Schema-DN[%s] objects[%u] \n " ,
c - > partition - > nc . dn , object_count ) ) ;
}
if ( ! s - > schema ) {
s - > schema = talloc_zero ( s , struct dsdb_schema ) ;
NT_STATUS_HAVE_NO_MEMORY ( s - > schema ) ;
status = dsdb_load_oid_mappings ( s - > schema , mapping_ctr ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
return werror_to_ntstatus ( status ) ;
}
}
for ( cur = first_object ; cur ; cur = cur - > next_object ) {
uint32_t i ;
bool dn_printed = false ;
bool is_attr = false ;
bool is_class = false ;
for ( i = 0 ; i < cur - > object . attribute_ctr . num_attributes ; i + + ) {
struct drsuapi_DsReplicaAttribute * a ;
uint32_t j ;
const char * oid = NULL ;
a = & cur - > object . attribute_ctr . attributes [ i ] ;
status = dsdb_map_int2oid ( s - > schema , a - > attid , s , & oid ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
if ( ! dn_printed ) {
DEBUG ( 0 , ( " %s: \n " , cur - > object . identifier - > dn ) ) ;
dn_printed = true ;
}
DEBUG ( 0 , ( " \t attr 0x%08X => %s \n " , a - > attid , win_errstr ( status ) ) ) ;
}
switch ( a - > attid ) {
case DRSUAPI_ATTRIBUTE_objectClass :
case DRSUAPI_ATTRIBUTE_attributeID :
case DRSUAPI_ATTRIBUTE_attributeSyntax :
for ( j = 0 ; j < a - > value_ctr . uint32 . num_values ; j + + ) {
uint32_t val = * a - > value_ctr . uint32 . values [ j ] . value ;
if ( val = = DRSUAPI_OBJECTCLASS_attributeSchema ) {
is_attr = true ;
}
if ( val = = DRSUAPI_OBJECTCLASS_classSchema ) {
is_class = true ;
}
status = dsdb_map_int2oid ( s - > schema , val , s , & oid ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
if ( ! dn_printed ) {
DEBUG ( 0 , ( " %s: \n " , cur - > object . identifier - > dn ) ) ;
dn_printed = true ;
}
DEBUG ( 0 , ( " \t attr 0x%08X => %s value[%u] 0x%08X => %s \n " ,
a - > attid , oid , j , val , win_errstr ( status ) ) ) ;
}
}
break ;
default :
break ;
}
}
if ( is_attr ) {
struct dsdb_attribute sa ;
status = dsdb_attribute_from_drsuapi ( s - > schema , & cur - > object , s , & sa ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
return werror_to_ntstatus ( status ) ;
}
}
if ( is_class ) {
struct dsdb_class sc ;
status = dsdb_class_from_drsuapi ( s - > schema , & cur - > object , s , & sc ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
return werror_to_ntstatus ( status ) ;
}
}
}
return NT_STATUS_OK ;
}
2006-12-21 00:54:06 +03:00
static NTSTATUS test_become_dc_store_chunk ( void * private_data ,
const struct libnet_BecomeDC_StoreChunk * c )
{
2006-12-23 00:31:57 +03:00
uint32_t total_object_count ;
uint32_t object_count ;
switch ( c - > ctr_level ) {
case 1 :
total_object_count = c - > ctr1 - > total_object_count ;
object_count = c - > ctr1 - > object_count ;
break ;
case 6 :
total_object_count = c - > ctr6 - > total_object_count ;
object_count = c - > ctr6 - > object_count ;
break ;
default :
return NT_STATUS_INVALID_PARAMETER ;
}
if ( total_object_count ) {
DEBUG ( 0 , ( " Partition[%s] objects[%u/%u] \n " ,
c - > partition - > nc . dn , object_count , total_object_count ) ) ;
} else {
DEBUG ( 0 , ( " Partition[%s] objects[%u] \n " ,
c - > partition - > nc . dn , object_count ) ) ;
}
2006-12-21 00:54:06 +03:00
return NT_STATUS_OK ;
}
2006-12-13 02:23:50 +03:00
BOOL torture_net_become_dc ( struct torture_context * torture )
{
BOOL ret = True ;
NTSTATUS status ;
struct libnet_BecomeDC b ;
struct libnet_UnbecomeDC u ;
2006-12-23 00:31:57 +03:00
struct test_become_dc_state * s ;
s = talloc_zero ( torture , struct test_become_dc_state ) ;
if ( ! s ) return False ;
2006-12-13 02:23:50 +03:00
/* Join domain as a member server. */
2006-12-23 00:31:57 +03:00
s - > tj = torture_join_domain ( TORTURE_NETBIOS_NAME ,
2006-12-13 02:23:50 +03:00
ACB_WSTRUST ,
2006-12-23 00:31:57 +03:00
& s - > machine_account ) ;
if ( ! s - > tj ) {
2006-12-13 02:23:50 +03:00
DEBUG ( 0 , ( " %s failed to join domain as workstation \n " ,
TORTURE_NETBIOS_NAME ) ) ;
return False ;
}
2006-12-23 00:31:57 +03:00
s - > ctx = libnet_context_init ( event_context_init ( s ) ) ;
s - > ctx - > cred = cmdline_credentials ;
2006-12-13 02:23:50 +03:00
2006-12-20 18:34:32 +03:00
ZERO_STRUCT ( b ) ;
2006-12-23 00:31:57 +03:00
b . in . domain_dns_name = torture_join_dom_dns_name ( s - > tj ) ;
b . in . domain_netbios_name = torture_join_dom_netbios_name ( s - > tj ) ;
b . in . domain_sid = torture_join_sid ( s - > tj ) ;
2006-12-13 02:23:50 +03:00
b . in . source_dsa_address = lp_parm_string ( - 1 , " torture " , " host " ) ;
b . in . dest_dsa_netbios_name = TORTURE_NETBIOS_NAME ;
2006-12-23 00:31:57 +03:00
b . in . callbacks . private_data = s ;
2006-12-20 19:34:35 +03:00
b . in . callbacks . check_options = test_become_dc_check_options ;
2006-12-21 00:14:44 +03:00
b . in . callbacks . prepare_db = test_become_dc_prepare_db ;
2006-12-23 00:31:57 +03:00
b . in . callbacks . schema_chunk = test_become_dc_schema_chunk ;
2006-12-21 00:54:06 +03:00
b . in . callbacks . config_chunk = test_become_dc_store_chunk ;
b . in . callbacks . domain_chunk = test_become_dc_store_chunk ;
2006-12-20 18:34:32 +03:00
2006-12-23 00:31:57 +03:00
status = libnet_BecomeDC ( s - > ctx , s , & b ) ;
2006-12-13 02:23:50 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " libnet_BecomeDC() failed - %s \n " , nt_errstr ( status ) ) ;
ret = False ;
}
2006-12-20 18:34:32 +03:00
ZERO_STRUCT ( u ) ;
2006-12-23 00:31:57 +03:00
u . in . domain_dns_name = torture_join_dom_dns_name ( s - > tj ) ;
u . in . domain_netbios_name = torture_join_dom_netbios_name ( s - > tj ) ;
2006-12-13 02:23:50 +03:00
u . in . source_dsa_address = lp_parm_string ( - 1 , " torture " , " host " ) ;
u . in . dest_dsa_netbios_name = TORTURE_NETBIOS_NAME ;
2006-12-23 00:31:57 +03:00
status = libnet_UnbecomeDC ( s - > ctx , s , & u ) ;
2006-12-13 02:23:50 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " libnet_UnbecomeDC() failed - %s \n " , nt_errstr ( status ) ) ;
ret = False ;
}
/* Leave domain. */
2006-12-23 00:31:57 +03:00
torture_leave_domain ( s - > tj ) ;
talloc_free ( s ) ;
2006-12-13 02:23:50 +03:00
return ret ;
}