2003-12-01 04:41:38 +03:00
/*
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 ( ) ;
2003-12-01 12:28:10 +03:00
printf ( " Testing LogonUasLogon \n " ) ;
2003-12-01 06:19:43 +03:00
2003-12-01 04:41:38 +03:00
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 ;
}
2003-12-01 06:19:43 +03:00
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 ( ) ;
2003-12-01 12:28:10 +03:00
printf ( " Testing LogonUasLogoff \n " ) ;
2003-12-01 06:19:43 +03:00
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 ;
}
2003-12-02 03:31:54 +03:00
static BOOL test_SetupCredentials ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx ,
struct netr_CredentialState * creds )
2003-12-01 06:19:43 +03:00
{
NTSTATUS status ;
struct netr_ServerReqChallenge r ;
2003-12-01 07:13:43 +03:00
struct netr_ServerAuthenticate a ;
const char * plain_pass ;
uint8 mach_pwd [ 16 ] ;
2003-12-01 06:19:43 +03:00
2003-12-01 12:28:10 +03:00
printf ( " Testing ServerReqChallenge \n " ) ;
2003-12-01 06:19:43 +03:00
r . in . server_name = NULL ;
r . in . computer_name = lp_netbios_name ( ) ;
2003-12-02 01:13:11 +03:00
generate_random_buffer ( r . in . credentials . data , sizeof ( r . in . credentials . data ) , False ) ;
2003-12-01 06:19:43 +03:00
status = dcerpc_netr_ServerReqChallenge ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " ServerReqChallenge - %s \n " , nt_errstr ( status ) ) ;
return False ;
}
2003-12-01 07:13:43 +03:00
plain_pass = secrets_fetch_machine_password ( ) ;
if ( ! plain_pass ) {
printf ( " Unable to fetch machine password! \n " ) ;
return False ;
}
E_md4hash ( plain_pass , mach_pwd ) ;
2003-12-02 05:15:33 +03:00
creds_client_init ( creds , & r . in . credentials , & r . out . credentials , mach_pwd ,
& a . in . credentials ) ;
2003-12-01 07:13:43 +03:00
a . in . server_name = NULL ;
a . in . username = talloc_asprintf ( mem_ctx , " %s$ " , lp_netbios_name ( ) ) ;
2003-12-02 07:05:05 +03:00
a . in . secure_challenge_type = SEC_CHAN_BDC ;
2003-12-01 07:13:43 +03:00
a . in . computer_name = lp_netbios_name ( ) ;
2003-12-01 12:28:10 +03:00
printf ( " Testing ServerAuthenticate \n " ) ;
2003-12-01 07:13:43 +03:00
status = dcerpc_netr_ServerAuthenticate ( p , mem_ctx , & a ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " ServerAuthenticate - %s \n " , nt_errstr ( status ) ) ;
return False ;
}
2003-12-02 05:15:33 +03:00
if ( ! creds_client_check ( creds , & a . out . credentials ) ) {
2003-12-01 15:41:54 +03:00
printf ( " Credential chaining failed \n " ) ;
2003-12-02 01:13:11 +03:00
return False ;
2003-12-01 12:28:10 +03:00
}
2003-12-02 03:31:54 +03:00
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 ;
}
2003-12-01 12:28:10 +03:00
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 ( ) ;
2003-12-01 15:41:54 +03:00
generate_random_buffer ( ninfo . challenge ,
sizeof ( ninfo . challenge ) , False ) ;
2003-12-01 12:28:10 +03:00
ninfo . nt . length = 24 ;
ninfo . nt . data = talloc ( mem_ctx , 24 ) ;
2003-12-01 15:41:54 +03:00
SMBNTencrypt ( password , ninfo . challenge , ninfo . nt . data ) ;
2003-12-01 12:28:10 +03:00
ninfo . lm . length = 24 ;
ninfo . lm . data = talloc ( mem_ctx , 24 ) ;
2003-12-01 15:41:54 +03:00
SMBencrypt ( password , ninfo . challenge , ninfo . lm . data ) ;
2003-12-01 12:28:10 +03:00
ZERO_STRUCT ( auth2 ) ;
2003-12-02 05:15:33 +03:00
creds_client_authenticator ( & creds , & auth ) ;
2003-12-02 01:13:11 +03:00
2003-12-02 03:31:54 +03:00
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 ;
2003-12-01 12:28:10 +03:00
printf ( " Testing SamLogon \n " ) ;
2003-12-02 03:31:54 +03:00
status = dcerpc_netr_LogonSamLogon ( p , mem_ctx , & r ) ;
2003-12-01 12:28:10 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " LogonSamLogon - %s \n " , nt_errstr ( status ) ) ;
return False ;
}
2003-12-02 05:15:33 +03:00
if ( ! creds_client_check ( & creds , & r . out . authenticator - > cred ) ) {
2003-12-02 03:31:54 +03:00
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 ( ) ) ;
2003-12-02 07:05:05 +03:00
r . in . secure_challenge_type = SEC_CHAN_BDC ;
2003-12-02 03:31:54 +03:00
r . in . computer_name = lp_netbios_name ( ) ;
password = generate_random_str ( 8 ) ;
E_md4hash ( password , r . in . new_password . data ) ;
2003-12-02 05:15:33 +03:00
creds_client_encrypt ( & creds , & r . in . new_password ) ;
2003-12-02 03:31:54 +03:00
printf ( " Testing ServerPasswordSet on machine account \n " ) ;
2003-12-02 05:15:33 +03:00
creds_client_authenticator ( & creds , & r . in . credential ) ;
2003-12-02 03:31:54 +03:00
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 " ) ;
}
2003-12-02 05:15:33 +03:00
if ( ! creds_client_check ( & creds , & r . out . return_authenticator . cred ) ) {
printf ( " Credential chaining failed \n " ) ;
}
2003-12-02 06:06:21 +03:00
/* by changing the machine password twice we test the credentials
chaining fully */
2003-12-02 05:15:33 +03:00
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 ) ) {
2003-12-01 15:41:54 +03:00
printf ( " Credential chaining failed \n " ) ;
}
2003-12-01 06:19:43 +03:00
return True ;
}
2003-12-01 04:41:38 +03:00
2003-12-02 11:04:37 +03:00
/* we remember the sequence numbers so we can easily do a DatabaseDelta */
static struct ULONG8 sequence_nums [ 3 ] ;
2003-12-02 06:06:21 +03:00
/*
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 ;
2003-12-02 07:33:57 +03:00
const uint32 database_ids [ ] = { 0 , 1 , 2 } ;
int i ;
BOOL ret = True ;
2003-12-02 06:06:21 +03:00
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 ;
2003-12-02 07:33:57 +03:00
ZERO_STRUCT ( r . in . return_authenticator ) ;
2003-12-02 06:06:21 +03:00
2003-12-02 07:33:57 +03:00
for ( i = 0 ; i < ARRAY_SIZE ( database_ids ) ; i + + ) {
2003-12-02 07:59:18 +03:00
r . in . sync_context = 0 ;
2003-12-02 07:33:57 +03:00
r . in . database_id = database_ids [ i ] ;
2003-12-02 06:06:21 +03:00
2003-12-02 07:33:57 +03:00
printf ( " Testing DatabaseSync of id %d \n " , r . in . database_id ) ;
2003-12-02 06:06:21 +03:00
2003-12-02 07:33:57 +03:00
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 ;
2003-12-02 11:04:37 +03:00
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 ;
2003-12-02 07:33:57 +03:00
} while ( NT_STATUS_EQUAL ( status , STATUS_MORE_ENTRIES ) ) ;
2003-12-02 06:06:21 +03:00
}
2003-12-02 07:33:57 +03:00
return ret ;
2003-12-02 06:06:21 +03:00
}
2003-12-02 12:52:15 +03:00
/*
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 ;
}
2003-12-02 13:04:10 +03:00
/*
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 ;
}
2003-12-02 13:08:26 +03:00
/*
try a netlogon GetDcName
*/
static BOOL test_GetDcName ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx )
{
NTSTATUS status ;
struct netr_GetDcName r ;
r . in . logon_server = talloc_asprintf ( mem_ctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
r . in . domainname = lp_workgroup ( ) ;
printf ( " Testing GetDcName \n " ) ;
status = dcerpc_netr_GetDcName ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " GetDcName - %s \n " , nt_errstr ( status ) ) ;
return False ;
}
return True ;
}
2003-12-02 12:52:15 +03:00
2003-12-01 04:41:38 +03:00
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 ;
if ( ! test_LogonUasLogon ( p , mem_ctx ) ) {
ret = False ;
}
2003-12-01 06:19:43 +03:00
if ( ! test_LogonUasLogoff ( p , mem_ctx ) ) {
ret = False ;
}
2003-12-02 03:31:54 +03:00
if ( ! test_SetPassword ( p , mem_ctx ) ) {
ret = False ;
}
2003-12-01 12:28:10 +03:00
if ( ! test_SamLogon ( p , mem_ctx ) ) {
2003-12-01 06:19:43 +03:00
ret = False ;
}
2003-12-02 06:06:21 +03:00
if ( ! test_DatabaseSync ( p , mem_ctx ) ) {
ret = False ;
}
2003-12-02 11:04:37 +03:00
if ( ! test_DatabaseDeltas ( p , mem_ctx ) ) {
ret = False ;
}
2003-12-02 13:04:10 +03:00
if ( ! test_AccountDeltas ( p , mem_ctx ) ) {
ret = False ;
}
2003-12-02 13:08:26 +03:00
if ( ! test_AccountSync ( p , mem_ctx ) ) {
ret = False ;
}
if ( ! test_GetDcName ( p , mem_ctx ) ) {
ret = False ;
}
2003-12-01 04:41:38 +03:00
torture_rpc_close ( p ) ;
return ret ;
}