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-30 14:56:00 +03:00
# include "lib/util/dlinklist.h"
2007-01-05 00:09:29 +03:00
# include "lib/ldb/include/ldb.h"
# include "lib/ldb/include/ldb_errors.h"
# include "librpc/ndr/libndr.h"
# include "librpc/gen_ndr/ndr_drsuapi.h"
# include "librpc/gen_ndr/ndr_drsblobs.h"
# include "librpc/gen_ndr/ndr_misc.h"
# include "system/time.h"
2007-01-06 02:00:46 +03:00
# include "auth/auth.h"
# include "lib/db_wrap.h"
2007-01-06 00:27:24 +03:00
# include "lib/appweb/ejs/ejs.h"
# include "lib/appweb/ejs/ejsInternal.h"
# include "scripting/ejs/smbcalls.h"
static EjsId eid ;
static int ejs_error ;
static void test_ejs_exception ( const char * reason )
{
Ejs * ep = ejsPtr ( eid ) ;
ejsSetErrorMsg ( eid , " %s " , reason ) ;
fprintf ( stderr , " %s " , ep - > error ) ;
ejs_error = 127 ;
}
static int test_run_ejs ( char * script )
{
EjsHandle handle = 0 ;
MprVar result ;
char * emsg ;
TALLOC_CTX * mem_ctx = talloc_new ( NULL ) ;
struct MprVar * return_var ;
mprSetCtx ( mem_ctx ) ;
if ( ejsOpen ( NULL , NULL , NULL ) ! = 0 ) {
d_printf ( " ejsOpen(): unable to initialise EJS subsystem \n " ) ;
ejs_error = 127 ;
goto failed ;
}
smb_setup_ejs_functions ( test_ejs_exception ) ;
if ( ( eid = ejsOpenEngine ( handle , 0 ) ) = = ( EjsId ) - 1 ) {
d_printf ( " smbscript: ejsOpenEngine(): unable to initialise an EJS engine \n " ) ;
ejs_error = 127 ;
goto failed ;
}
mprSetVar ( ejsGetGlobalObject ( eid ) , " ARGV " , mprList ( " ARGV " , NULL ) ) ;
/* run the script */
if ( ejsEvalScript ( eid , script , & result , & emsg ) = = - 1 ) {
d_printf ( " smbscript: ejsEvalScript(): %s \n " , emsg ) ;
if ( ejs_error = = 0 ) ejs_error = 127 ;
goto failed ;
}
return_var = ejsGetReturnValue ( eid ) ;
ejs_error = mprVarToNumber ( return_var ) ;
failed :
ejsClose ( ) ;
talloc_free ( mem_ctx ) ;
return ejs_error ;
}
2006-12-13 02:23:50 +03:00
# define TORTURE_NETBIOS_NAME "smbtorturedc"
2007-01-06 02:00:46 +03:00
# define TORTURE_SAMDB_LDB "test_samdb.ldb"
2007-01-15 17:17:26 +03:00
# define TORTURE_SECRETS_LDB "test_secrets.ldb"
# define TORTURE_SECRETS_KEYTAB "test_secrets.keytab"
2006-12-13 02:23:50 +03:00
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 ;
2007-01-14 18:35:10 +03:00
struct dsdb_schema * self_made_schema ;
const struct dsdb_schema * schema ;
2006-12-30 14:56:00 +03:00
2006-12-31 15:32:15 +03:00
struct ldb_context * ldb ;
2006-12-30 14:56:00 +03:00
struct {
2007-01-11 16:15:53 +03:00
uint32_t object_count ;
2006-12-30 14:56:00 +03:00
struct drsuapi_DsReplicaObjectListItemEx * first_object ;
struct drsuapi_DsReplicaObjectListItemEx * last_object ;
} schema_part ;
2007-01-19 18:33:11 +03:00
const char * computer_dn ;
2006-12-23 00:31:57 +03:00
} ;
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 ) ;
2007-01-06 00:27:24 +03:00
char * ejs ;
int ret ;
2007-01-12 16:17:25 +03:00
bool ok ;
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 ) ) ;
2007-01-06 00:27:24 +03:00
ejs = talloc_asprintf ( s ,
" libinclude( \" base.js \" ); \n "
" libinclude( \" provision.js \" ); \n "
" \n "
" function message() { print(vsprintf(arguments)); } \n "
" \n "
" var subobj = provision_guess(); \n "
" subobj.ROOTDN = \" %s \" ; \n "
" subobj.DOMAINDN = \" %s \" ; \n "
" subobj.DOMAINDN_LDB = \" test_domain.ldb \" ; \n "
" subobj.CONFIGDN = \" %s \" ; \n "
" subobj.CONFIGDN_LDB = \" test_config.ldb \" ; \n "
" subobj.SCHEMADN = \" %s \" ; \n "
" subobj.SCHEMADN_LDB = \" test_schema.ldb \" ; \n "
" subobj.HOSTNAME = \" %s \" ; \n "
" subobj.DNSNAME = \" %s \" ; \n "
" subobj.DEFAULTSITE = \" %s \" ; \n "
" \n "
2007-01-06 02:00:46 +03:00
" modules_list = new Array( \" rootdse \" , \n "
" \" kludge_acl \" , \n "
" \" paged_results \" , \n "
" \" server_sort \" , \n "
" \" extended_dn \" , \n "
" \" asq \" , \n "
2007-01-06 04:13:59 +03:00
" \" samldb \" , \n "
2007-01-06 02:00:46 +03:00
" \" operational \" , \n "
" \" objectclass \" , \n "
" \" rdn_name \" , \n "
2007-01-20 13:27:22 +03:00
" \" show_deleted \" , \n "
2007-01-06 02:00:46 +03:00
" \" partition \" ); \n "
" subobj.MODULES_LIST = join( \" , \" , modules_list); \n "
2007-01-18 04:35:54 +03:00
" subobj.DOMAINDN_MOD = \" pdc_fsmo,password_hash,repl_meta_data \" ; \n "
2007-01-18 03:01:18 +03:00
" subobj.CONFIGDN_MOD = \" naming_fsmo,repl_meta_data \" ; \n "
2007-01-14 21:03:26 +03:00
" subobj.SCHEMADN_MOD = \" schema_fsmo,repl_meta_data \" ; \n "
2007-01-06 02:00:46 +03:00
" \n "
2007-02-15 15:47:58 +03:00
" subobj.KRBTGTPASS = \" _NOT_USED_ \" ; \n "
" subobj.MACHINEPASS = \" %s \" ; \n "
" subobj.ADMINPASS = \" _NOT_USED_ \" ; \n "
2007-01-15 17:19:03 +03:00
" \n "
2007-01-06 00:27:24 +03:00
" var paths = provision_default_paths(subobj); \n "
2007-01-06 02:00:46 +03:00
" paths.samdb = \" %s \" ; \n "
2007-01-15 17:17:26 +03:00
" paths.secrets = \" %s \" ; \n "
" paths.keytab = \" %s \" ; \n "
2007-01-06 00:27:24 +03:00
" \n "
" var system_session = system_session(); \n "
" \n "
" var ok = provision_become_dc(subobj, message, paths, system_session); \n "
" assert(ok); \n "
" \n "
" return 0; \n " ,
2007-01-15 17:17:26 +03:00
p - > forest - > root_dn_str , /* subobj.ROOTDN */
p - > domain - > dn_str , /* subobj.DOMAINDN */
p - > forest - > config_dn_str , /* subobj.CONFIGDN */
p - > forest - > schema_dn_str , /* subobj.SCHEMADN */
p - > dest_dsa - > netbios_name , /* subobj.HOSTNAME */
p - > dest_dsa - > dns_name , /* subobj.DNSNAME */
p - > dest_dsa - > site_name , /* subobj.DEFAULTSITE */
2007-02-15 15:47:58 +03:00
cli_credentials_get_password ( s - > machine_account ) , /* subobj.MACHINEPASS */
2007-01-15 17:17:26 +03:00
TORTURE_SAMDB_LDB , /* paths.samdb */
TORTURE_SECRETS_LDB , /* paths.secrets */
TORTURE_SECRETS_KEYTAB ) ; /* paths.keytab */
2007-01-06 00:27:24 +03:00
NT_STATUS_HAVE_NO_MEMORY ( ejs ) ;
ret = test_run_ejs ( ejs ) ;
if ( ret ! = 0 ) {
DEBUG ( 0 , ( " Failed to run ejs script: %d: \n %s " ,
ret , ejs ) ) ;
talloc_free ( ejs ) ;
return NT_STATUS_FOOBAR ;
}
talloc_free ( ejs ) ;
2007-01-06 02:00:46 +03:00
talloc_free ( s - > ldb ) ;
2007-01-14 21:03:26 +03:00
DEBUG ( 0 , ( " Open the SAM LDB with system credentials: %s \n " , TORTURE_SAMDB_LDB ) ) ;
2007-01-06 02:00:46 +03:00
s - > ldb = ldb_wrap_connect ( s , TORTURE_SAMDB_LDB ,
system_session ( s ) ,
NULL , 0 , NULL ) ;
if ( ! s - > ldb ) {
DEBUG ( 0 , ( " Failed to open '%s' \n " ,
TORTURE_SAMDB_LDB ) ) ;
return NT_STATUS_INTERNAL_DB_ERROR ;
}
2007-01-12 16:17:25 +03:00
ok = samdb_set_ntds_invocation_id ( s - > ldb , & p - > dest_dsa - > invocation_id ) ;
if ( ! ok ) {
DEBUG ( 0 , ( " Failed to set cached ntds invocationId \n " ) ) ;
return NT_STATUS_FOOBAR ;
}
ok = samdb_set_ntds_objectGUID ( s - > ldb , & p - > dest_dsa - > ntds_guid ) ;
if ( ! ok ) {
DEBUG ( 0 , ( " Failed to set cached ntds objectGUID \n " ) ) ;
return NT_STATUS_FOOBAR ;
}
2006-12-21 00:14:44 +03:00
return NT_STATUS_OK ;
}
2006-12-30 14:56:00 +03:00
static NTSTATUS test_apply_schema ( struct test_become_dc_state * s ,
const struct libnet_BecomeDC_StoreChunk * c )
{
WERROR status ;
2007-01-11 16:15:53 +03:00
const struct drsuapi_DsReplicaOIDMapping_Ctr * mapping_ctr ;
uint32_t total_object_count ;
uint32_t object_count ;
struct drsuapi_DsReplicaObjectListItemEx * first_object ;
2006-12-30 14:56:00 +03:00
struct drsuapi_DsReplicaObjectListItemEx * cur ;
2007-01-11 16:15:53 +03:00
uint32_t linked_attributes_count ;
struct drsuapi_DsReplicaLinkedAttribute * linked_attributes ;
const struct drsuapi_DsReplicaCursor2CtrEx * uptodateness_vector ;
struct dsdb_extended_replicated_objects * objs ;
2007-01-12 19:02:10 +03:00
struct repsFromTo1 * s_dsa ;
char * tmp_dns_name ;
2007-01-14 18:49:06 +03:00
struct ldb_message * msg ;
struct ldb_val prefixMap_val ;
struct ldb_message_element * prefixMap_el ;
struct ldb_val schemaInfo_val ;
2007-01-11 16:15:53 +03:00
uint32_t i ;
2007-01-12 20:26:55 +03:00
int ret ;
2007-01-14 21:03:26 +03:00
bool ok ;
DEBUG ( 0 , ( " Analyze and apply schema objects \n " ) ) ;
2006-12-30 14:56:00 +03:00
2007-01-12 19:02:10 +03:00
s_dsa = talloc_zero ( s , struct repsFromTo1 ) ;
NT_STATUS_HAVE_NO_MEMORY ( s_dsa ) ;
s_dsa - > other_info = talloc ( s_dsa , struct repsFromTo1OtherInfo ) ;
NT_STATUS_HAVE_NO_MEMORY ( s_dsa - > other_info ) ;
2007-01-11 16:15:53 +03:00
switch ( c - > ctr_level ) {
case 1 :
2007-01-12 19:02:10 +03:00
mapping_ctr = & c - > ctr1 - > mapping_ctr ;
total_object_count = c - > ctr1 - > total_object_count ;
object_count = s - > schema_part . object_count ;
first_object = s - > schema_part . first_object ;
linked_attributes_count = 0 ;
linked_attributes = NULL ;
s_dsa - > highwatermark = c - > ctr1 - > new_highwatermark ;
s_dsa - > source_dsa_obj_guid = c - > ctr1 - > source_dsa_guid ;
s_dsa - > source_dsa_invocation_id = c - > ctr1 - > source_dsa_invocation_id ;
uptodateness_vector = NULL ; /* TODO: map it */
2007-01-11 16:15:53 +03:00
break ;
case 6 :
2007-01-12 19:02:10 +03:00
mapping_ctr = & c - > ctr6 - > mapping_ctr ;
total_object_count = c - > ctr6 - > total_object_count ;
object_count = s - > schema_part . object_count ;
first_object = s - > schema_part . first_object ;
linked_attributes_count = 0 ; /* TODO: ! */
linked_attributes = NULL ; /* TODO: ! */ ;
s_dsa - > highwatermark = c - > ctr6 - > new_highwatermark ;
s_dsa - > source_dsa_obj_guid = c - > ctr6 - > source_dsa_guid ;
s_dsa - > source_dsa_invocation_id = c - > ctr6 - > source_dsa_invocation_id ;
uptodateness_vector = c - > ctr6 - > uptodateness_vector ;
2007-01-11 16:15:53 +03:00
break ;
default :
return NT_STATUS_INVALID_PARAMETER ;
}
2007-01-12 19:02:10 +03:00
s_dsa - > replica_flags = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
| DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
| DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS ;
memset ( s_dsa - > schedule , 0x11 , sizeof ( s_dsa - > schedule ) ) ;
tmp_dns_name = GUID_string ( s_dsa - > other_info , & s_dsa - > source_dsa_obj_guid ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_dns_name ) ;
tmp_dns_name = talloc_asprintf_append ( tmp_dns_name , " ._msdcs.%s " , c - > forest - > dns_name ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_dns_name ) ;
s_dsa - > other_info - > dns_name = tmp_dns_name ;
2007-01-11 16:15:53 +03:00
for ( cur = first_object ; cur ; cur = cur - > next_object ) {
2006-12-30 14:56:00 +03:00
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 ] ;
2007-01-14 18:35:10 +03:00
status = dsdb_map_int2oid ( s - > self_made_schema , a - > attid , s , & oid ) ;
2006-12-30 14:56:00 +03:00
if ( ! W_ERROR_IS_OK ( status ) ) {
return werror_to_ntstatus ( status ) ;
}
switch ( a - > attid ) {
case DRSUAPI_ATTRIBUTE_objectClass :
2007-01-03 12:58:14 +03:00
for ( j = 0 ; j < a - > value_ctr . num_values ; j + + ) {
2007-01-02 22:24:32 +03:00
uint32_t val = 0xFFFFFFFF ;
2007-01-02 19:39:32 +03:00
2007-01-03 12:58:14 +03:00
if ( a - > value_ctr . values [ i ] . blob
& & a - > value_ctr . values [ i ] . blob - > length = = 4 ) {
val = IVAL ( a - > value_ctr . values [ i ] . blob - > data , 0 ) ;
2007-01-02 22:24:32 +03:00
}
2006-12-30 14:56:00 +03:00
if ( val = = DRSUAPI_OBJECTCLASS_attributeSchema ) {
is_attr = true ;
}
if ( val = = DRSUAPI_OBJECTCLASS_classSchema ) {
is_class = true ;
}
}
2007-01-02 22:24:32 +03:00
2006-12-30 14:56:00 +03:00
break ;
default :
break ;
}
}
if ( is_attr ) {
struct dsdb_attribute * sa ;
2007-01-14 18:35:10 +03:00
sa = talloc_zero ( s - > self_made_schema , struct dsdb_attribute ) ;
2006-12-30 14:56:00 +03:00
NT_STATUS_HAVE_NO_MEMORY ( sa ) ;
2007-01-14 18:35:10 +03:00
status = dsdb_attribute_from_drsuapi ( s - > self_made_schema , & cur - > object , s , sa ) ;
2006-12-30 14:56:00 +03:00
if ( ! W_ERROR_IS_OK ( status ) ) {
return werror_to_ntstatus ( status ) ;
}
2007-01-14 18:35:10 +03:00
DLIST_ADD_END ( s - > self_made_schema - > attributes , sa , struct dsdb_attribute * ) ;
2006-12-30 14:56:00 +03:00
}
if ( is_class ) {
struct dsdb_class * sc ;
2007-01-14 18:35:10 +03:00
sc = talloc_zero ( s - > self_made_schema , struct dsdb_class ) ;
2006-12-30 14:56:00 +03:00
NT_STATUS_HAVE_NO_MEMORY ( sc ) ;
2007-01-14 18:35:10 +03:00
status = dsdb_class_from_drsuapi ( s - > self_made_schema , & cur - > object , s , sc ) ;
2006-12-30 14:56:00 +03:00
if ( ! W_ERROR_IS_OK ( status ) ) {
return werror_to_ntstatus ( status ) ;
}
2007-01-14 18:35:10 +03:00
DLIST_ADD_END ( s - > self_made_schema - > classes , sc , struct dsdb_class * ) ;
2006-12-30 14:56:00 +03:00
}
}
2007-01-14 18:35:10 +03:00
/* attach the schema to the ldb */
ret = dsdb_set_schema ( s - > ldb , s - > self_made_schema ) ;
2007-01-12 20:26:55 +03:00
if ( ret ! = LDB_SUCCESS ) {
return NT_STATUS_FOOBAR ;
}
2007-01-14 18:35:10 +03:00
/* we don't want to access the self made schema anymore */
s - > self_made_schema = NULL ;
s - > schema = dsdb_get_schema ( s - > ldb ) ;
2007-01-12 20:26:55 +03:00
2007-01-11 16:15:53 +03:00
status = dsdb_extended_replicated_objects_commit ( s - > ldb ,
c - > partition - > nc . dn ,
mapping_ctr ,
object_count ,
first_object ,
linked_attributes_count ,
linked_attributes ,
2007-01-12 19:02:10 +03:00
s_dsa ,
2007-01-11 16:15:53 +03:00
uptodateness_vector ,
2007-02-12 14:46:35 +03:00
c - > gensec_skey ,
2007-01-11 16:15:53 +03:00
s , & objs ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Failed to commit objects: %s \n " , win_errstr ( status ) ) ) ;
return werror_to_ntstatus ( status ) ;
2007-01-06 02:00:46 +03:00
}
2007-01-11 16:15:53 +03:00
if ( lp_parm_bool ( - 1 , " become dc " , " dump objects " , False ) ) {
for ( i = 0 ; i < objs - > num_objects ; i + + ) {
struct ldb_ldif ldif ;
fprintf ( stdout , " # \n " ) ;
ldif . changetype = LDB_CHANGETYPE_NONE ;
ldif . msg = objs - > objects [ i ] . msg ;
ldb_ldif_write_file ( s - > ldb , stdout , & ldif ) ;
NDR_PRINT_DEBUG ( replPropertyMetaDataBlob , objs - > objects [ i ] . meta_data ) ;
}
2007-01-06 02:00:46 +03:00
}
2007-01-14 18:49:06 +03:00
msg = ldb_msg_new ( objs ) ;
NT_STATUS_HAVE_NO_MEMORY ( msg ) ;
msg - > dn = objs - > partition_dn ;
status = dsdb_get_oid_mappings_ldb ( s - > schema , msg , & prefixMap_val , & schemaInfo_val ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Failed dsdb_get_oid_mappings_ldb(%s) \n " , win_errstr ( status ) ) ) ;
return werror_to_ntstatus ( status ) ;
}
2007-01-14 18:56:55 +03:00
/* we only add prefixMap here, because schemaInfo is a replicated attribute and already applied */
2007-01-14 18:49:06 +03:00
ret = ldb_msg_add_value ( msg , " prefixMap " , & prefixMap_val , & prefixMap_el ) ;
if ( ret ! = LDB_SUCCESS ) {
return NT_STATUS_FOOBAR ;
}
prefixMap_el - > flags = LDB_FLAG_MOD_REPLACE ;
ret = ldb_modify ( s - > ldb , msg ) ;
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 0 , ( " Failed to add prefixMap and schemaInfo %s \n " , ldb_strerror ( ret ) ) ) ;
return NT_STATUS_FOOBAR ;
}
2007-01-12 19:02:10 +03:00
talloc_free ( s_dsa ) ;
2007-01-11 16:15:53 +03:00
talloc_free ( objs ) ;
2007-01-14 21:03:26 +03:00
/* reopen the ldb */
talloc_free ( s - > ldb ) ; /* this also free's the s->schema, because dsdb_set_schema() steals it */
s - > schema = NULL ;
DEBUG ( 0 , ( " Reopen the SAM LDB with system credentials and a already stored schema: %s \n " , TORTURE_SAMDB_LDB ) ) ;
s - > ldb = ldb_wrap_connect ( s , TORTURE_SAMDB_LDB ,
system_session ( s ) ,
NULL , 0 , NULL ) ;
if ( ! s - > ldb ) {
DEBUG ( 0 , ( " Failed to open '%s' \n " ,
TORTURE_SAMDB_LDB ) ) ;
return NT_STATUS_INTERNAL_DB_ERROR ;
}
ok = samdb_set_ntds_invocation_id ( s - > ldb , & c - > dest_dsa - > invocation_id ) ;
if ( ! ok ) {
DEBUG ( 0 , ( " Failed to set cached ntds invocationId \n " ) ) ;
return NT_STATUS_FOOBAR ;
}
ok = samdb_set_ntds_objectGUID ( s - > ldb , & c - > dest_dsa - > ntds_guid ) ;
if ( ! ok ) {
DEBUG ( 0 , ( " Failed to set cached ntds objectGUID \n " ) ) ;
return NT_STATUS_FOOBAR ;
}
s - > schema = dsdb_get_schema ( s - > ldb ) ;
if ( ! s - > schema ) {
DEBUG ( 0 , ( " Failed to get loaded dsdb_schema \n " ) ) ;
return NT_STATUS_FOOBAR ;
}
2006-12-30 14:56:00 +03:00
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 ) {
2007-01-14 18:35:10 +03:00
s - > self_made_schema = talloc_zero ( s , struct dsdb_schema ) ;
NT_STATUS_HAVE_NO_MEMORY ( s - > self_made_schema ) ;
2006-12-23 00:31:57 +03:00
2007-01-14 18:35:10 +03:00
status = dsdb_load_oid_mappings_drsuapi ( s - > self_made_schema , mapping_ctr ) ;
2006-12-23 00:31:57 +03:00
if ( ! W_ERROR_IS_OK ( status ) ) {
return werror_to_ntstatus ( status ) ;
}
2007-01-14 18:35:10 +03:00
s - > schema = s - > self_made_schema ;
2006-12-28 15:50:39 +03:00
} else {
2007-01-13 18:29:47 +03:00
status = dsdb_verify_oid_mappings_drsuapi ( s - > schema , mapping_ctr ) ;
2006-12-28 15:50:39 +03:00
if ( ! W_ERROR_IS_OK ( status ) ) {
return werror_to_ntstatus ( status ) ;
}
2006-12-23 00:31:57 +03:00
}
2006-12-30 14:56:00 +03:00
if ( ! s - > schema_part . first_object ) {
2007-01-11 16:15:53 +03:00
s - > schema_part . object_count = object_count ;
2006-12-30 14:56:00 +03:00
s - > schema_part . first_object = talloc_steal ( s , first_object ) ;
} else {
2007-01-11 16:15:53 +03:00
s - > schema_part . object_count + = object_count ;
2006-12-30 14:56:00 +03:00
s - > schema_part . last_object - > next_object = talloc_steal ( s - > schema_part . last_object ,
first_object ) ;
}
for ( cur = first_object ; cur - > next_object ; cur = cur - > next_object ) { }
s - > schema_part . last_object = cur ;
2006-12-23 00:31:57 +03:00
2006-12-30 14:56:00 +03:00
if ( c - > partition - > highwatermark . tmp_highest_usn = = c - > partition - > highwatermark . highest_usn ) {
return test_apply_schema ( s , c ) ;
2006-12-23 00:31:57 +03:00
}
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-28 15:54:55 +03:00
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 ;
2006-12-23 00:31:57 +03:00
uint32_t total_object_count ;
uint32_t object_count ;
2006-12-30 14:56:00 +03:00
struct drsuapi_DsReplicaObjectListItemEx * first_object ;
2007-01-05 00:09:29 +03:00
uint32_t linked_attributes_count ;
struct drsuapi_DsReplicaLinkedAttribute * linked_attributes ;
2007-01-11 16:15:53 +03:00
const struct drsuapi_DsReplicaCursor2CtrEx * uptodateness_vector ;
struct dsdb_extended_replicated_objects * objs ;
2007-01-12 19:02:10 +03:00
struct repsFromTo1 * s_dsa ;
char * tmp_dns_name ;
2007-01-05 00:09:29 +03:00
uint32_t i ;
2006-12-23 00:31:57 +03:00
2007-01-12 19:02:10 +03:00
s_dsa = talloc_zero ( s , struct repsFromTo1 ) ;
NT_STATUS_HAVE_NO_MEMORY ( s_dsa ) ;
s_dsa - > other_info = talloc ( s_dsa , struct repsFromTo1OtherInfo ) ;
NT_STATUS_HAVE_NO_MEMORY ( s_dsa - > other_info ) ;
2006-12-23 00:31:57 +03:00
switch ( c - > ctr_level ) {
case 1 :
2007-01-12 19:02:10 +03:00
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 ;
linked_attributes_count = 0 ;
linked_attributes = NULL ;
s_dsa - > highwatermark = c - > ctr1 - > new_highwatermark ;
s_dsa - > source_dsa_obj_guid = c - > ctr1 - > source_dsa_guid ;
s_dsa - > source_dsa_invocation_id = c - > ctr1 - > source_dsa_invocation_id ;
uptodateness_vector = NULL ; /* TODO: map it */
2006-12-23 00:31:57 +03:00
break ;
case 6 :
2007-01-12 19:02:10 +03:00
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 ;
linked_attributes_count = c - > ctr6 - > linked_attributes_count ;
linked_attributes = c - > ctr6 - > linked_attributes ;
s_dsa - > highwatermark = c - > ctr6 - > new_highwatermark ;
s_dsa - > source_dsa_obj_guid = c - > ctr6 - > source_dsa_guid ;
s_dsa - > source_dsa_invocation_id = c - > ctr6 - > source_dsa_invocation_id ;
uptodateness_vector = c - > ctr6 - > uptodateness_vector ;
2006-12-23 00:31:57 +03:00
break ;
default :
return NT_STATUS_INVALID_PARAMETER ;
}
2007-01-12 19:02:10 +03:00
s_dsa - > replica_flags = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
| DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
| DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS ;
memset ( s_dsa - > schedule , 0x11 , sizeof ( s_dsa - > schedule ) ) ;
tmp_dns_name = GUID_string ( s_dsa - > other_info , & s_dsa - > source_dsa_obj_guid ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_dns_name ) ;
tmp_dns_name = talloc_asprintf_append ( tmp_dns_name , " ._msdcs.%s " , c - > forest - > dns_name ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_dns_name ) ;
s_dsa - > other_info - > dns_name = tmp_dns_name ;
2006-12-23 00:31:57 +03:00
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
2007-01-11 16:15:53 +03:00
status = dsdb_extended_replicated_objects_commit ( s - > ldb ,
c - > partition - > nc . dn ,
mapping_ctr ,
object_count ,
first_object ,
linked_attributes_count ,
linked_attributes ,
2007-01-12 19:02:10 +03:00
s_dsa ,
2007-01-11 16:15:53 +03:00
uptodateness_vector ,
2007-02-12 14:46:35 +03:00
c - > gensec_skey ,
2007-01-11 16:15:53 +03:00
s , & objs ) ;
2006-12-28 15:54:55 +03:00
if ( ! W_ERROR_IS_OK ( status ) ) {
2007-01-11 16:15:53 +03:00
DEBUG ( 0 , ( " Failed to commit objects: %s \n " , win_errstr ( status ) ) ) ;
2006-12-28 15:54:55 +03:00
return werror_to_ntstatus ( status ) ;
}
2007-01-11 16:15:53 +03:00
if ( lp_parm_bool ( - 1 , " become dc " , " dump objects " , False ) ) {
for ( i = 0 ; i < objs - > num_objects ; i + + ) {
struct ldb_ldif ldif ;
fprintf ( stdout , " # \n " ) ;
ldif . changetype = LDB_CHANGETYPE_NONE ;
ldif . msg = objs - > objects [ i ] . msg ;
ldb_ldif_write_file ( s - > ldb , stdout , & ldif ) ;
NDR_PRINT_DEBUG ( replPropertyMetaDataBlob , objs - > objects [ i ] . meta_data ) ;
2006-12-30 14:56:00 +03:00
}
}
2007-01-12 19:02:10 +03:00
talloc_free ( s_dsa ) ;
2007-01-11 16:15:53 +03:00
talloc_free ( objs ) ;
2006-12-30 14:56:00 +03:00
2007-01-05 00:09:29 +03:00
for ( i = 0 ; i < linked_attributes_count ; i + + ) {
const struct dsdb_attribute * sa ;
if ( ! linked_attributes [ i ] . identifier ) {
return NT_STATUS_FOOBAR ;
}
if ( ! linked_attributes [ i ] . value . blob ) {
return NT_STATUS_FOOBAR ;
}
sa = dsdb_attribute_by_attributeID_id ( s - > schema ,
linked_attributes [ i ] . attid ) ;
if ( ! sa ) {
return NT_STATUS_FOOBAR ;
}
if ( lp_parm_bool ( - 1 , " become dc " , " dump objects " , False ) ) {
DEBUG ( 0 , ( " # %s \n " , sa - > lDAPDisplayName ) ) ;
NDR_PRINT_DEBUG ( drsuapi_DsReplicaLinkedAttribute , & linked_attributes [ i ] ) ;
dump_data ( 0 ,
linked_attributes [ i ] . value . blob - > data ,
linked_attributes [ i ] . value . blob - > length ) ;
}
}
2006-12-21 00:54:06 +03:00
return NT_STATUS_OK ;
}
2007-01-19 18:33:11 +03:00
static NTSTATUS test_become_dc_domain_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 ) ;
s - > computer_dn = talloc_strdup ( s , c - > dest_dsa - > computer_dn_str ) ;
NT_STATUS_HAVE_NO_MEMORY ( s - > computer_dn ) ;
return test_become_dc_store_chunk ( private_data , c ) ;
}
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 ;
2007-01-18 03:26:07 +03:00
struct ldb_message * msg ;
int ldb_ret ;
uint32_t i ;
2006-12-23 00:31:57 +03:00
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-31 15:32:15 +03:00
s - > ldb = ldb_init ( s ) ;
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 ;
2007-01-19 18:33:11 +03:00
b . in . callbacks . domain_chunk = test_become_dc_domain_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 ;
2007-01-18 03:26:07 +03:00
goto cleanup ;
}
msg = ldb_msg_new ( s ) ;
if ( ! msg ) {
printf ( " ldb_msg_new() failed \n " ) ;
ret = False ;
goto cleanup ;
}
msg - > dn = ldb_dn_new ( msg , s - > ldb , " cn=ROOTDSE " ) ;
if ( ! msg - > dn ) {
printf ( " ldb_msg_new(cn=ROOTDSE) failed \n " ) ;
ret = False ;
goto cleanup ;
}
ldb_ret = ldb_msg_add_string ( msg , " isSynchronized " , " TRUE " ) ;
if ( ldb_ret ! = LDB_SUCCESS ) {
printf ( " ldb_msg_add_string(msg, isSynchronized, TRUE) failed: %d \n " , ldb_ret ) ;
ret = False ;
goto cleanup ;
}
for ( i = 0 ; i < msg - > num_elements ; i + + ) {
msg - > elements [ i ] . flags = LDB_FLAG_MOD_REPLACE ;
}
printf ( " mark ROOTDSE with isSynchronized=TRUE \n " ) ;
ldb_ret = ldb_modify ( s - > ldb , msg ) ;
if ( ldb_ret ! = LDB_SUCCESS ) {
printf ( " ldb_modify() failed: %d \n " , ldb_ret ) ;
ret = False ;
goto cleanup ;
}
/* reopen the ldb */
talloc_free ( s - > ldb ) ; /* this also free's the s->schema, because dsdb_set_schema() steals it */
s - > schema = NULL ;
DEBUG ( 0 , ( " Reopen the SAM LDB with system credentials and all replicated data: %s \n " , TORTURE_SAMDB_LDB ) ) ;
s - > ldb = ldb_wrap_connect ( s , TORTURE_SAMDB_LDB ,
system_session ( s ) ,
NULL , 0 , NULL ) ;
if ( ! s - > ldb ) {
DEBUG ( 0 , ( " Failed to open '%s' \n " ,
TORTURE_SAMDB_LDB ) ) ;
ret = False ;
goto cleanup ;
}
s - > schema = dsdb_get_schema ( s - > ldb ) ;
if ( ! s - > schema ) {
DEBUG ( 0 , ( " Failed to get loaded dsdb_schema \n " ) ) ;
ret = False ;
goto cleanup ;
2006-12-13 02:23:50 +03:00
}
2007-02-22 18:25:55 +03:00
if ( lp_parm_bool ( - 1 , " become dc " , " donnot leave " , False ) ) {
talloc_free ( s ) ;
return ret ;
}
2007-01-18 03:26:07 +03:00
cleanup :
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 ;
}