0001-01-01 02:30:17 +02:30
/*
Unix SMB / CIFS implementation .
test suite for netlogon rpc operations
Copyright ( C ) Andrew Tridgell 2003
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"
static BOOL test_LogonUasLogon ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx )
{
NTSTATUS status ;
struct netr_LogonUasLogon r ;
r . in . server_name = NULL ;
r . in . username = lp_parm_string ( - 1 , " torture " , " username " ) ;
r . in . workstation = lp_netbios_name ( ) ;
0001-01-01 02:30:17 +02:30
printf ( " Testing LogonUasLogon \n " ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
status = dcerpc_netr_LogonUasLogon ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " LogonUasLogon - %s \n " , nt_errstr ( status ) ) ;
return False ;
}
return True ;
}
0001-01-01 02:30:17 +02:30
static BOOL test_LogonUasLogoff ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx )
{
NTSTATUS status ;
struct netr_LogonUasLogoff r ;
r . in . server_name = NULL ;
r . in . username = lp_parm_string ( - 1 , " torture " , " username " ) ;
r . in . workstation = lp_netbios_name ( ) ;
0001-01-01 02:30:17 +02:30
printf ( " Testing LogonUasLogoff \n " ) ;
0001-01-01 02:30:17 +02:30
status = dcerpc_netr_LogonUasLogoff ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " LogonUasLogoff - %s \n " , nt_errstr ( status ) ) ;
return False ;
}
return True ;
}
0001-01-01 02:30:17 +02:30
static BOOL test_SetupCredentials ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx ,
struct netr_CredentialState * creds )
0001-01-01 02:30:17 +02:30
{
NTSTATUS status ;
struct netr_ServerReqChallenge r ;
0001-01-01 02:30:17 +02:30
struct netr_ServerAuthenticate a ;
const char * plain_pass ;
uint8 mach_pwd [ 16 ] ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
printf ( " Testing ServerReqChallenge \n " ) ;
0001-01-01 02:30:17 +02:30
r . in . server_name = NULL ;
r . in . computer_name = lp_netbios_name ( ) ;
0001-01-01 02:30:17 +02:30
generate_random_buffer ( r . in . credentials . data , sizeof ( r . in . credentials . data ) , False ) ;
0001-01-01 02:30:17 +02:30
status = dcerpc_netr_ServerReqChallenge ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " ServerReqChallenge - %s \n " , nt_errstr ( status ) ) ;
return False ;
}
0001-01-01 02:30:17 +02:30
plain_pass = secrets_fetch_machine_password ( ) ;
if ( ! plain_pass ) {
printf ( " Unable to fetch machine password! \n " ) ;
return False ;
}
E_md4hash ( plain_pass , mach_pwd ) ;
0001-01-01 02:30:17 +02:30
creds_client_init ( creds , & r . in . credentials , & r . out . credentials , mach_pwd ,
& a . in . credentials ) ;
0001-01-01 02:30:17 +02:30
a . in . server_name = NULL ;
a . in . username = talloc_asprintf ( mem_ctx , " %s$ " , lp_netbios_name ( ) ) ;
0001-01-01 02:30:17 +02:30
a . in . secure_challenge_type = SEC_CHAN_BDC ;
0001-01-01 02:30:17 +02:30
a . in . computer_name = lp_netbios_name ( ) ;
0001-01-01 02:30:17 +02:30
printf ( " Testing ServerAuthenticate \n " ) ;
0001-01-01 02:30:17 +02:30
status = dcerpc_netr_ServerAuthenticate ( p , mem_ctx , & a ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " ServerAuthenticate - %s \n " , nt_errstr ( status ) ) ;
return False ;
}
0001-01-01 02:30:17 +02:30
if ( ! creds_client_check ( creds , & a . out . credentials ) ) {
0001-01-01 02:30:17 +02:30
printf ( " Credential chaining failed \n " ) ;
0001-01-01 02:30:17 +02:30
return False ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
return True ;
}
/*
try a netlogon SamLogon
*/
static BOOL test_SamLogon ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx )
{
NTSTATUS status ;
struct netr_LogonSamLogon r ;
struct netr_Authenticator auth , auth2 ;
struct netr_NetworkInfo ninfo ;
const char * username = lp_parm_string ( - 1 , " torture " , " username " ) ;
const char * password = lp_parm_string ( - 1 , " torture " , " password " ) ;
struct netr_CredentialState creds ;
if ( ! test_SetupCredentials ( p , mem_ctx , & creds ) ) {
return False ;
}
0001-01-01 02:30:17 +02:30
ninfo . logon_info . domain_name . string = lp_workgroup ( ) ;
ninfo . logon_info . parameter_control = 0 ;
ninfo . logon_info . logon_id_low = 0 ;
ninfo . logon_info . logon_id_high = 0 ;
ninfo . logon_info . username . string = username ;
ninfo . logon_info . workstation . string = lp_netbios_name ( ) ;
0001-01-01 02:30:17 +02:30
generate_random_buffer ( ninfo . challenge ,
sizeof ( ninfo . challenge ) , False ) ;
0001-01-01 02:30:17 +02:30
ninfo . nt . length = 24 ;
ninfo . nt . data = talloc ( mem_ctx , 24 ) ;
0001-01-01 02:30:17 +02:30
SMBNTencrypt ( password , ninfo . challenge , ninfo . nt . data ) ;
0001-01-01 02:30:17 +02:30
ninfo . lm . length = 24 ;
ninfo . lm . data = talloc ( mem_ctx , 24 ) ;
0001-01-01 02:30:17 +02:30
SMBencrypt ( password , ninfo . challenge , ninfo . lm . data ) ;
0001-01-01 02:30:17 +02:30
ZERO_STRUCT ( auth2 ) ;
0001-01-01 02:30:17 +02:30
creds_client_authenticator ( & creds , & auth ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
r . in . server_name = talloc_asprintf ( mem_ctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
r . in . workstation = lp_netbios_name ( ) ;
r . in . credential = & auth ;
r . in . authenticator = & auth2 ;
r . in . logon_level = 2 ;
r . in . logon . network = & ninfo ;
r . in . validation_level = 2 ;
0001-01-01 02:30:17 +02:30
printf ( " Testing SamLogon \n " ) ;
0001-01-01 02:30:17 +02:30
status = dcerpc_netr_LogonSamLogon ( p , mem_ctx , & r ) ;
0001-01-01 02:30:17 +02:30
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " LogonSamLogon - %s \n " , nt_errstr ( status ) ) ;
return False ;
}
0001-01-01 02:30:17 +02:30
if ( ! creds_client_check ( & creds , & r . out . authenticator - > cred ) ) {
0001-01-01 02:30:17 +02:30
printf ( " Credential chaining failed \n " ) ;
}
return True ;
}
/*
try a change password for our machine account
*/
static BOOL test_SetPassword ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx )
{
NTSTATUS status ;
struct netr_ServerPasswordSet r ;
const char * password ;
struct netr_CredentialState creds ;
if ( ! test_SetupCredentials ( p , mem_ctx , & creds ) ) {
return False ;
}
r . in . server_name = talloc_asprintf ( mem_ctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
r . in . username = talloc_asprintf ( mem_ctx , " %s$ " , lp_netbios_name ( ) ) ;
0001-01-01 02:30:17 +02:30
r . in . secure_challenge_type = SEC_CHAN_BDC ;
0001-01-01 02:30:17 +02:30
r . in . computer_name = lp_netbios_name ( ) ;
password = generate_random_str ( 8 ) ;
E_md4hash ( password , r . in . new_password . data ) ;
0001-01-01 02:30:17 +02:30
creds_client_encrypt ( & creds , & r . in . new_password ) ;
0001-01-01 02:30:17 +02:30
printf ( " Testing ServerPasswordSet on machine account \n " ) ;
0001-01-01 02:30:17 +02:30
creds_client_authenticator ( & creds , & r . in . credential ) ;
0001-01-01 02:30:17 +02:30
status = dcerpc_netr_ServerPasswordSet ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " ServerPasswordSet - %s \n " , nt_errstr ( status ) ) ;
return False ;
}
if ( ! secrets_store_machine_password ( password ) ) {
printf ( " Failed to save machine password \n " ) ;
}
0001-01-01 02:30:17 +02:30
if ( ! creds_client_check ( & creds , & r . out . return_authenticator . cred ) ) {
printf ( " Credential chaining failed \n " ) ;
}
0001-01-01 02:30:17 +02:30
/* by changing the machine password twice we test the credentials
chaining fully */
0001-01-01 02:30:17 +02:30
printf ( " Testing a second ServerPasswordSet on machine account \n " ) ;
creds_client_authenticator ( & creds , & r . in . credential ) ;
status = dcerpc_netr_ServerPasswordSet ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " ServerPasswordSet - %s \n " , nt_errstr ( status ) ) ;
return False ;
}
if ( ! creds_client_check ( & creds , & r . out . return_authenticator . cred ) ) {
0001-01-01 02:30:17 +02:30
printf ( " Credential chaining failed \n " ) ;
}
0001-01-01 02:30:17 +02:30
return True ;
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/* we remember the sequence numbers so we can easily do a DatabaseDelta */
static struct ULONG8 sequence_nums [ 3 ] ;
0001-01-01 02:30:17 +02:30
/*
try a netlogon DatabaseSync
*/
static BOOL test_DatabaseSync ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx )
{
NTSTATUS status ;
struct netr_DatabaseSync r ;
struct netr_CredentialState creds ;
0001-01-01 02:30:17 +02:30
const uint32 database_ids [ ] = { 0 , 1 , 2 } ;
int i ;
BOOL ret = True ;
0001-01-01 02:30:17 +02:30
if ( ! test_SetupCredentials ( p , mem_ctx , & creds ) ) {
return False ;
}
r . in . logonserver = talloc_asprintf ( mem_ctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
r . in . computername = lp_netbios_name ( ) ;
r . in . preferredmaximumlength = ( uint32 ) - 1 ;
0001-01-01 02:30:17 +02:30
ZERO_STRUCT ( r . in . return_authenticator ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
for ( i = 0 ; i < ARRAY_SIZE ( database_ids ) ; i + + ) {
0001-01-01 02:30:17 +02:30
r . in . sync_context = 0 ;
0001-01-01 02:30:17 +02:30
r . in . database_id = database_ids [ i ] ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
printf ( " Testing DatabaseSync of id %d \n " , r . in . database_id ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
do {
creds_client_authenticator ( & creds , & r . in . credential ) ;
status = dcerpc_netr_DatabaseSync ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) & &
! NT_STATUS_EQUAL ( status , STATUS_MORE_ENTRIES ) ) {
printf ( " DatabaseSync - %s \n " , nt_errstr ( status ) ) ;
ret = False ;
break ;
}
if ( ! creds_client_check ( & creds , & r . out . return_authenticator . cred ) ) {
printf ( " Credential chaining failed \n " ) ;
}
r . in . sync_context = r . out . sync_context ;
0001-01-01 02:30:17 +02:30
if ( r . out . delta_enum_array & &
r . out . delta_enum_array - > num_deltas > 0 & &
r . out . delta_enum_array - > delta_enum [ 0 ] . delta_type = = 1 & &
r . out . delta_enum_array - > delta_enum [ 0 ] . delta_union . domain ) {
sequence_nums [ r . in . database_id ] =
r . out . delta_enum_array - > delta_enum [ 0 ] . delta_union . domain - > sequence_num ;
printf ( " sequence_nums[%d]=0x%08x%08x \n " ,
r . in . database_id ,
sequence_nums [ r . in . database_id ] . high ,
sequence_nums [ r . in . database_id ] . low ) ;
}
} while ( NT_STATUS_EQUAL ( status , STATUS_MORE_ENTRIES ) ) ;
}
return ret ;
}
/*
try a netlogon DatabaseDeltas
*/
static BOOL test_DatabaseDeltas ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx )
{
NTSTATUS status ;
struct netr_DatabaseDeltas r ;
struct netr_CredentialState creds ;
const uint32 database_ids [ ] = { 0 , 1 , 2 } ;
int i ;
BOOL ret = True ;
if ( ! test_SetupCredentials ( p , mem_ctx , & creds ) ) {
return False ;
}
r . in . logonserver = talloc_asprintf ( mem_ctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
r . in . computername = lp_netbios_name ( ) ;
r . in . preferredmaximumlength = ( uint32 ) - 1 ;
ZERO_STRUCT ( r . in . return_authenticator ) ;
for ( i = 0 ; i < ARRAY_SIZE ( database_ids ) ; i + + ) {
r . in . database_id = database_ids [ i ] ;
r . in . sequence_num = sequence_nums [ r . in . database_id ] ;
r . in . sequence_num . low - = 1 ;
printf ( " Testing DatabaseDeltas of id %d at %d \n " ,
r . in . database_id , r . in . sequence_num . low ) ;
do {
creds_client_authenticator ( & creds , & r . in . credential ) ;
status = dcerpc_netr_DatabaseDeltas ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) & &
! NT_STATUS_EQUAL ( status , STATUS_MORE_ENTRIES ) ) {
printf ( " DatabaseDeltas - %s \n " , nt_errstr ( status ) ) ;
ret = False ;
break ;
}
if ( ! creds_client_check ( & creds , & r . out . return_authenticator . cred ) ) {
printf ( " Credential chaining failed \n " ) ;
}
r . in . sequence_num . low + + ;
r . in . sequence_num . high = 0 ;
0001-01-01 02:30:17 +02:30
} while ( NT_STATUS_EQUAL ( status , STATUS_MORE_ENTRIES ) ) ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
return ret ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
/*
try a netlogon AccountDeltas
*/
static BOOL test_AccountDeltas ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx )
{
NTSTATUS status ;
struct netr_AccountDeltas r ;
struct netr_CredentialState creds ;
BOOL ret = True ;
if ( ! test_SetupCredentials ( p , mem_ctx , & creds ) ) {
return False ;
}
r . in . logonserver = talloc_asprintf ( mem_ctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
r . in . computername = lp_netbios_name ( ) ;
ZERO_STRUCT ( r . in . return_authenticator ) ;
creds_client_authenticator ( & creds , & r . in . credential ) ;
ZERO_STRUCT ( r . in . uas ) ;
r . in . count = 10 ;
r . in . level = 0 ;
r . in . buffersize = 100 ;
printf ( " Testing AccountDeltas \n " ) ;
/* w2k3 returns "NOT IMPLEMENTED" for this call */
status = dcerpc_netr_AccountDeltas ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_NOT_IMPLEMENTED ) ) {
printf ( " AccountDeltas - %s \n " , nt_errstr ( status ) ) ;
ret = False ;
}
return ret ;
}
0001-01-01 02:30:17 +02:30
/*
try a netlogon AccountSync
*/
static BOOL test_AccountSync ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx )
{
NTSTATUS status ;
struct netr_AccountSync r ;
struct netr_CredentialState creds ;
BOOL ret = True ;
if ( ! test_SetupCredentials ( p , mem_ctx , & creds ) ) {
return False ;
}
r . in . logonserver = talloc_asprintf ( mem_ctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
r . in . computername = lp_netbios_name ( ) ;
ZERO_STRUCT ( r . in . return_authenticator ) ;
creds_client_authenticator ( & creds , & r . in . credential ) ;
ZERO_STRUCT ( r . in . recordid ) ;
r . in . reference = 0 ;
r . in . level = 0 ;
r . in . buffersize = 100 ;
printf ( " Testing AccountSync \n " ) ;
/* w2k3 returns "NOT IMPLEMENTED" for this call */
status = dcerpc_netr_AccountSync ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_NOT_IMPLEMENTED ) ) {
printf ( " AccountSync - %s \n " , nt_errstr ( status ) ) ;
ret = False ;
}
return ret ;
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
BOOL torture_rpc_netlogon ( int dummy )
{
NTSTATUS status ;
struct dcerpc_pipe * p ;
TALLOC_CTX * mem_ctx ;
BOOL ret = True ;
mem_ctx = talloc_init ( " torture_rpc_netlogon " ) ;
status = torture_rpc_connection ( & p ,
DCERPC_NETLOGON_NAME ,
DCERPC_NETLOGON_UUID ,
DCERPC_NETLOGON_VERSION ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return False ;
}
p - > flags | = DCERPC_DEBUG_PRINT_BOTH ;
0001-01-01 02:30:17 +02:30
if ( ! test_AccountSync ( p , mem_ctx ) ) {
0001-01-01 02:30:17 +02:30
ret = False ;
}
return ret ;
0001-01-01 02:30:17 +02:30
if ( ! test_LogonUasLogon ( p , mem_ctx ) ) {
ret = False ;
}
0001-01-01 02:30:17 +02:30
if ( ! test_LogonUasLogoff ( p , mem_ctx ) ) {
ret = False ;
}
0001-01-01 02:30:17 +02:30
if ( ! test_SetPassword ( p , mem_ctx ) ) {
ret = False ;
}
0001-01-01 02:30:17 +02:30
if ( ! test_SamLogon ( p , mem_ctx ) ) {
0001-01-01 02:30:17 +02:30
ret = False ;
}
0001-01-01 02:30:17 +02:30
if ( ! test_DatabaseSync ( p , mem_ctx ) ) {
ret = False ;
}
0001-01-01 02:30:17 +02:30
if ( ! test_DatabaseDeltas ( p , mem_ctx ) ) {
ret = False ;
}
0001-01-01 02:30:17 +02:30
if ( ! test_AccountDeltas ( p , mem_ctx ) ) {
ret = False ;
}
0001-01-01 02:30:17 +02:30
torture_rpc_close ( p ) ;
return ret ;
}