2003-12-01 04:41:38 +03:00
/*
Unix SMB / CIFS implementation .
test suite for netlogon rpc operations
Copyright ( C ) Andrew Tridgell 2003
2004-05-09 16:42:18 +04:00
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2003 - 2004
Copyright ( C ) Tim Potter 2003
2003-12-01 04:41:38 +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
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"
2004-06-06 11:14:10 +04:00
static const char * machine_password ;
2004-05-15 11:51:38 +04:00
2004-06-06 11:14:10 +04:00
# define TEST_MACHINE_NAME "torturetest"
2004-04-27 10:36:39 +04:00
2003-12-01 04:41:38 +03:00
static BOOL test_LogonUasLogon ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx )
{
NTSTATUS status ;
struct netr_LogonUasLogon r ;
r . in . server_name = NULL ;
2004-06-05 07:22:10 +04:00
r . in . account_name = lp_parm_string ( - 1 , " torture " , " username " ) ;
2004-04-27 10:36:39 +04:00
r . in . workstation = TEST_MACHINE_NAME ;
2003-12-01 04:41:38 +03:00
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 ;
2004-06-05 07:22:10 +04:00
r . in . account_name = lp_parm_string ( - 1 , " torture " , " username " ) ;
2004-04-27 10:36:39 +04:00
r . in . workstation = TEST_MACHINE_NAME ;
2003-12-01 06:19:43 +03:00
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 ,
2004-05-09 16:42:18 +04:00
struct creds_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 ;
2004-05-30 17:15:15 +04:00
struct netr_Credential credentials1 , credentials2 , credentials3 ;
2003-12-01 07:13:43 +03:00
const char * plain_pass ;
2004-06-05 07:22:10 +04:00
struct samr_Password mach_password ;
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 ;
2004-04-27 10:36:39 +04:00
r . in . computer_name = TEST_MACHINE_NAME ;
2004-05-30 17:15:15 +04:00
r . in . credentials = & credentials1 ;
r . out . credentials = & credentials2 ;
2004-07-14 16:14:07 +04:00
generate_random_buffer ( credentials1 . data , sizeof ( credentials1 . data ) ) ;
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 ;
}
2004-06-06 11:14:10 +04:00
plain_pass = machine_password ;
2003-12-01 07:13:43 +03:00
if ( ! plain_pass ) {
printf ( " Unable to fetch machine password! \n " ) ;
return False ;
}
2004-06-05 07:22:10 +04:00
E_md4hash ( plain_pass , mach_password . hash ) ;
2003-12-01 07:13:43 +03:00
a . in . server_name = NULL ;
2004-06-05 07:22:10 +04:00
a . in . account_name = talloc_asprintf ( mem_ctx , " %s$ " , TEST_MACHINE_NAME ) ;
2003-12-02 14:43:09 +03:00
a . in . secure_channel_type = SEC_CHAN_BDC ;
2004-04-27 10:36:39 +04:00
a . in . computer_name = TEST_MACHINE_NAME ;
2004-05-30 17:15:15 +04:00
a . in . credentials = & credentials3 ;
a . out . credentials = & credentials3 ;
2004-06-05 07:22:10 +04:00
creds_client_init ( creds , & credentials1 , & credentials2 , & mach_password , & credentials3 ,
2004-06-04 03:15:16 +04:00
NETLOGON_NEG_AUTH2_FLAGS ) ;
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 ;
}
2004-05-30 17:15:15 +04:00
if ( ! creds_client_check ( creds , & credentials3 ) ) {
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 ;
}
2003-12-02 14:43:09 +03:00
static BOOL test_SetupCredentials2 ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx ,
2004-05-25 20:24:13 +04:00
uint32_t negotiate_flags ,
2004-05-09 16:42:18 +04:00
struct creds_CredentialState * creds )
2003-12-02 14:43:09 +03:00
{
NTSTATUS status ;
struct netr_ServerReqChallenge r ;
struct netr_ServerAuthenticate2 a ;
2004-05-30 17:15:15 +04:00
struct netr_Credential credentials1 , credentials2 , credentials3 ;
2003-12-02 14:43:09 +03:00
const char * plain_pass ;
2004-06-05 07:22:10 +04:00
struct samr_Password mach_password ;
2003-12-02 14:43:09 +03:00
printf ( " Testing ServerReqChallenge \n " ) ;
r . in . server_name = NULL ;
2004-04-27 10:36:39 +04:00
r . in . computer_name = TEST_MACHINE_NAME ;
2004-05-30 17:15:15 +04:00
r . in . credentials = & credentials1 ;
r . out . credentials = & credentials2 ;
2004-07-14 16:14:07 +04:00
generate_random_buffer ( credentials1 . data , sizeof ( credentials1 . data ) ) ;
2003-12-02 14:43:09 +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 ;
}
2004-06-06 11:14:10 +04:00
plain_pass = machine_password ;
2003-12-02 14:43:09 +03:00
if ( ! plain_pass ) {
printf ( " Unable to fetch machine password! \n " ) ;
return False ;
}
2004-06-05 07:22:10 +04:00
E_md4hash ( plain_pass , mach_password . hash ) ;
2003-12-02 14:43:09 +03:00
a . in . server_name = NULL ;
2004-06-05 07:22:10 +04:00
a . in . account_name = talloc_asprintf ( mem_ctx , " %s$ " , TEST_MACHINE_NAME ) ;
2003-12-02 14:43:09 +03:00
a . in . secure_channel_type = SEC_CHAN_BDC ;
2004-04-27 10:36:39 +04:00
a . in . computer_name = TEST_MACHINE_NAME ;
2003-12-02 14:43:09 +03:00
a . in . negotiate_flags = & negotiate_flags ;
a . out . negotiate_flags = & negotiate_flags ;
2004-05-30 17:15:15 +04:00
a . in . credentials = & credentials3 ;
a . out . credentials = & credentials3 ;
2004-06-05 07:22:10 +04:00
creds_client_init ( creds , & credentials1 , & credentials2 , & mach_password , & credentials3 ,
2004-06-04 03:15:16 +04:00
negotiate_flags ) ;
2003-12-02 14:43:09 +03:00
printf ( " Testing ServerAuthenticate2 \n " ) ;
status = dcerpc_netr_ServerAuthenticate2 ( p , mem_ctx , & a ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " ServerAuthenticate2 - %s \n " , nt_errstr ( status ) ) ;
return False ;
}
2004-05-30 17:15:15 +04:00
if ( ! creds_client_check ( creds , & credentials3 ) ) {
printf ( " Credential chaining failed \n " ) ;
return False ;
}
printf ( " negotiate_flags=0x%08x \n " , negotiate_flags ) ;
return True ;
}
static BOOL test_SetupCredentials3 ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx ,
uint32_t negotiate_flags ,
struct creds_CredentialState * creds )
{
NTSTATUS status ;
struct netr_ServerReqChallenge r ;
struct netr_ServerAuthenticate3 a ;
struct netr_Credential credentials1 , credentials2 , credentials3 ;
const char * plain_pass ;
2004-06-05 07:22:10 +04:00
struct samr_Password mach_password ;
2004-05-30 17:15:15 +04:00
uint32 rid ;
printf ( " Testing ServerReqChallenge \n " ) ;
r . in . server_name = NULL ;
r . in . computer_name = TEST_MACHINE_NAME ;
r . in . credentials = & credentials1 ;
r . out . credentials = & credentials2 ;
2004-06-04 03:15:16 +04:00
2004-07-14 16:14:07 +04:00
generate_random_buffer ( credentials1 . data , sizeof ( credentials1 . data ) ) ;
2004-05-30 17:15:15 +04:00
status = dcerpc_netr_ServerReqChallenge ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " ServerReqChallenge - %s \n " , nt_errstr ( status ) ) ;
return False ;
}
2004-06-06 11:14:10 +04:00
plain_pass = machine_password ;
2004-05-30 17:15:15 +04:00
if ( ! plain_pass ) {
printf ( " Unable to fetch machine password! \n " ) ;
return False ;
}
2004-06-05 07:22:10 +04:00
E_md4hash ( plain_pass , mach_password . hash ) ;
2004-05-30 17:15:15 +04:00
a . in . server_name = NULL ;
2004-06-05 07:22:10 +04:00
a . in . account_name = talloc_asprintf ( mem_ctx , " %s$ " , TEST_MACHINE_NAME ) ;
2004-05-30 17:15:15 +04:00
a . in . secure_channel_type = SEC_CHAN_BDC ;
a . in . computer_name = TEST_MACHINE_NAME ;
a . in . negotiate_flags = & negotiate_flags ;
a . in . credentials = & credentials3 ;
a . out . credentials = & credentials3 ;
a . out . negotiate_flags = & negotiate_flags ;
a . out . rid = & rid ;
2004-06-05 07:22:10 +04:00
creds_client_init ( creds , & credentials1 , & credentials2 , & mach_password , & credentials3 ,
2004-06-04 03:15:16 +04:00
negotiate_flags ) ;
2004-05-30 17:15:15 +04:00
printf ( " Testing ServerAuthenticate3 \n " ) ;
status = dcerpc_netr_ServerAuthenticate3 ( p , mem_ctx , & a ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " ServerAuthenticate3 - %s \n " , nt_errstr ( status ) ) ;
return False ;
}
if ( ! creds_client_check ( creds , & credentials3 ) ) {
2003-12-02 14:43:09 +03:00
printf ( " Credential chaining failed \n " ) ;
return False ;
}
printf ( " negotiate_flags=0x%08x \n " , negotiate_flags ) ;
return True ;
}
2004-05-09 16:42:18 +04:00
enum ntlm_break {
BREAK_NONE ,
BREAK_LM ,
BREAK_NT ,
NO_LM ,
NO_NT
} ;
struct samlogon_state {
TALLOC_CTX * mem_ctx ;
2004-06-05 07:22:10 +04:00
const char * account_name ;
2004-08-25 18:31:59 +04:00
const char * account_domain ;
2004-05-09 16:42:18 +04:00
const char * password ;
struct dcerpc_pipe * p ;
2003-12-02 03:31:54 +03:00
struct netr_LogonSamLogon r ;
struct netr_Authenticator auth , auth2 ;
2004-05-09 16:42:18 +04:00
struct creds_CredentialState creds ;
DATA_BLOB chall ;
} ;
2003-12-02 03:31:54 +03:00
2004-05-09 16:42:18 +04:00
/*
Authenticate a user with a challenge / response , checking session key
and valid authentication types
*/
static NTSTATUS check_samlogon ( struct samlogon_state * samlogon_state ,
enum ntlm_break break_which ,
DATA_BLOB * chall ,
DATA_BLOB * lm_response ,
DATA_BLOB * nt_response ,
2004-05-25 21:50:17 +04:00
uint8_t lm_key [ 8 ] ,
uint8_t user_session_key [ 16 ] ,
2004-05-09 16:42:18 +04:00
char * * error_string )
{
NTSTATUS status ;
struct netr_LogonSamLogon * r = & samlogon_state - > r ;
struct netr_NetworkInfo ninfo ;
2003-12-01 12:28:10 +03:00
2004-09-04 04:02:43 +04:00
struct netr_SamBaseInfo * base ;
printf ( " testing netr_LogonSamLogon \n " ) ;
samlogon_state - > r . in . logon . network = & ninfo ;
2004-05-09 16:42:18 +04:00
2004-09-04 04:02:43 +04:00
ninfo . identity_info . domain_name . string = samlogon_state - > account_domain ;
ninfo . identity_info . parameter_control = 0 ;
ninfo . identity_info . logon_id_low = 0 ;
ninfo . identity_info . logon_id_high = 0 ;
ninfo . identity_info . account_name . string = samlogon_state - > account_name ;
ninfo . identity_info . workstation . string = TEST_MACHINE_NAME ;
2004-05-19 18:43:58 +04:00
2004-09-04 04:02:43 +04:00
memcpy ( ninfo . challenge , chall - > data , 8 ) ;
2004-05-19 18:43:58 +04:00
2004-09-04 04:02:43 +04:00
switch ( break_which ) {
case BREAK_NONE :
break ;
case BREAK_LM :
if ( lm_response & & lm_response - > data ) {
lm_response - > data [ 0 ] + + ;
2004-05-09 16:42:18 +04:00
}
2004-09-04 04:02:43 +04:00
break ;
case BREAK_NT :
if ( nt_response & & nt_response - > data ) {
nt_response - > data [ 0 ] + + ;
2004-05-09 16:42:18 +04:00
}
2004-09-04 04:02:43 +04:00
break ;
case NO_LM :
data_blob_free ( lm_response ) ;
break ;
case NO_NT :
data_blob_free ( nt_response ) ;
break ;
}
2004-05-19 18:43:58 +04:00
2004-09-04 04:02:43 +04:00
if ( nt_response ) {
ninfo . nt . data = nt_response - > data ;
ninfo . nt . length = nt_response - > length ;
} else {
ninfo . nt . data = NULL ;
ninfo . nt . length = 0 ;
}
2004-05-19 18:43:58 +04:00
2004-09-04 04:02:43 +04:00
if ( lm_response ) {
ninfo . lm . data = lm_response - > data ;
ninfo . lm . length = lm_response - > length ;
} else {
ninfo . lm . data = NULL ;
ninfo . lm . length = 0 ;
}
2004-05-19 18:43:58 +04:00
2004-09-04 04:02:43 +04:00
ZERO_STRUCT ( samlogon_state - > auth2 ) ;
creds_client_authenticator ( & samlogon_state - > creds , & samlogon_state - > auth ) ;
2004-05-19 18:43:58 +04:00
2004-09-04 04:02:43 +04:00
r - > out . return_authenticator = NULL ;
status = dcerpc_netr_LogonSamLogon ( samlogon_state - > p , samlogon_state - > mem_ctx , r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( error_string ) {
* error_string = strdup ( nt_errstr ( status ) ) ;
2004-05-09 16:42:18 +04:00
}
2004-09-04 04:02:43 +04:00
}
2004-05-19 18:43:58 +04:00
2004-09-04 04:02:43 +04:00
if ( ! r - > out . return_authenticator | |
! creds_client_check ( & samlogon_state - > creds , & r - > out . return_authenticator - > cred ) ) {
printf ( " Credential chaining failed \n " ) ;
}
2004-06-18 17:27:37 +04:00
2004-09-04 04:02:43 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
/* we cannot check the session key, if the logon failed... */
return status ;
}
/* find and decyrpt the session keys, return in parameters above */
if ( r - > in . validation_level = = 2 ) {
base = & r - > out . validation . sam2 - > base ;
} else if ( r - > in . validation_level = = 3 ) {
base = & r - > out . validation . sam3 - > base ;
} else if ( r - > in . validation_level = = 6 ) {
base = & r - > out . validation . sam6 - > base ;
} else {
base = NULL ;
}
if ( r - > in . validation_level ! = 6 ) {
static const char zeros [ 16 ] ;
2004-05-19 18:43:58 +04:00
2004-09-04 04:02:43 +04:00
if ( memcmp ( base - > key . key , zeros ,
sizeof ( base - > key . key ) ) ! = 0 ) {
creds_arcfour_crypt ( & samlogon_state - > creds ,
base - > key . key ,
sizeof ( base - > key . key ) ) ;
}
2004-05-19 18:43:58 +04:00
2004-09-04 04:02:43 +04:00
if ( user_session_key ) {
memcpy ( user_session_key , base - > key . key , 16 ) ;
}
2004-05-19 18:43:58 +04:00
2004-09-04 04:02:43 +04:00
if ( memcmp ( base - > LMSessKey . key , zeros ,
sizeof ( base - > LMSessKey . key ) ) ! = 0 ) {
creds_arcfour_crypt ( & samlogon_state - > creds ,
base - > LMSessKey . key ,
sizeof ( base - > LMSessKey . key ) ) ;
}
2004-05-19 18:43:58 +04:00
2004-09-04 04:02:43 +04:00
if ( lm_key ) {
memcpy ( lm_key , base - > LMSessKey . key , 8 ) ;
}
} else {
/* they aren't encrypted! */
if ( user_session_key ) {
memcpy ( user_session_key , base - > key . key , 16 ) ;
}
if ( lm_key ) {
memcpy ( lm_key , base - > LMSessKey . key , 8 ) ;
2004-05-09 16:42:18 +04:00
}
}
2004-09-04 04:02:43 +04:00
2004-05-09 16:42:18 +04:00
return status ;
}
2004-06-14 15:33:28 +04:00
2004-05-09 16:42:18 +04:00
/*
* Test the normal ' LM and NTLM ' combination
*/
static BOOL test_lm_ntlm_broken ( struct samlogon_state * samlogon_state , enum ntlm_break break_which , char * * error_string )
{
BOOL pass = True ;
2004-09-04 04:02:43 +04:00
BOOL lm_good ;
2004-05-09 16:42:18 +04:00
NTSTATUS nt_status ;
DATA_BLOB lm_response = data_blob_talloc ( samlogon_state - > mem_ctx , NULL , 24 ) ;
DATA_BLOB nt_response = data_blob_talloc ( samlogon_state - > mem_ctx , NULL , 24 ) ;
DATA_BLOB session_key = data_blob_talloc ( samlogon_state - > mem_ctx , NULL , 16 ) ;
2004-06-01 12:30:34 +04:00
uint8_t lm_key [ 8 ] ;
uint8_t user_session_key [ 16 ] ;
uint8_t lm_hash [ 16 ] ;
uint8_t nt_hash [ 16 ] ;
2004-05-09 16:42:18 +04:00
ZERO_STRUCT ( lm_key ) ;
ZERO_STRUCT ( user_session_key ) ;
2004-09-04 04:02:43 +04:00
lm_good = SMBencrypt ( samlogon_state - > password , samlogon_state - > chall . data , lm_response . data ) ;
2004-10-21 05:55:46 +04:00
if ( ! lm_good ) {
2004-09-04 04:02:43 +04:00
ZERO_STRUCT ( lm_hash ) ;
} else {
E_deshash ( samlogon_state - > password , lm_hash ) ;
}
2004-05-09 16:42:18 +04:00
SMBNTencrypt ( samlogon_state - > password , samlogon_state - > chall . data , nt_response . data ) ;
E_md4hash ( samlogon_state - > password , nt_hash ) ;
SMBsesskeygen_ntv1 ( nt_hash , session_key . data ) ;
nt_status = check_samlogon ( samlogon_state ,
break_which ,
& samlogon_state - > chall ,
& lm_response ,
& nt_response ,
lm_key ,
user_session_key ,
error_string ) ;
data_blob_free ( & lm_response ) ;
2004-09-04 04:02:43 +04:00
if ( NT_STATUS_EQUAL ( NT_STATUS_WRONG_PASSWORD , nt_status ) ) {
/* for 'long' passwords, the LM password is invalid */
if ( break_which = = NO_NT & & ! lm_good ) {
return True ;
}
2004-05-09 16:42:18 +04:00
return break_which = = BREAK_NT ;
}
2004-09-04 04:02:43 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
return False ;
}
if ( break_which = = NO_NT & & ! lm_good ) {
printf ( " LM password is 'long' (> 14 chars and therefore invalid) but login did not fail! " ) ;
return False ;
}
2004-05-09 16:42:18 +04:00
if ( memcmp ( lm_hash , lm_key ,
sizeof ( lm_key ) ) ! = 0 ) {
printf ( " LM Key does not match expectations! \n " ) ;
2004-09-04 04:02:43 +04:00
printf ( " lm_key: \n " ) ;
2004-05-09 16:42:18 +04:00
dump_data ( 1 , ( const char * ) lm_key , 8 ) ;
printf ( " expected: \n " ) ;
dump_data ( 1 , ( const char * ) lm_hash , 8 ) ;
pass = False ;
}
if ( break_which = = NO_NT ) {
char lm_key_expected [ 16 ] ;
memcpy ( lm_key_expected , lm_hash , 8 ) ;
memset ( lm_key_expected + 8 , ' \0 ' , 8 ) ;
if ( memcmp ( lm_key_expected , user_session_key ,
16 ) ! = 0 ) {
printf ( " NT Session Key does not match expectations (should be first-8 LM hash)! \n " ) ;
printf ( " user_session_key: \n " ) ;
dump_data ( 1 , ( const char * ) user_session_key , sizeof ( user_session_key ) ) ;
printf ( " expected: \n " ) ;
dump_data ( 1 , ( const char * ) lm_key_expected , sizeof ( lm_key_expected ) ) ;
pass = False ;
}
} else {
if ( memcmp ( session_key . data , user_session_key ,
sizeof ( user_session_key ) ) ! = 0 ) {
printf ( " NT Session Key does not match expectations! \n " ) ;
printf ( " user_session_key: \n " ) ;
dump_data ( 1 , ( const char * ) user_session_key , 16 ) ;
printf ( " expected: \n " ) ;
dump_data ( 1 , ( const char * ) session_key . data , session_key . length ) ;
pass = False ;
}
}
return pass ;
}
/*
* Test LM authentication , no NT response supplied
*/
static BOOL test_lm ( struct samlogon_state * samlogon_state , char * * error_string )
{
return test_lm_ntlm_broken ( samlogon_state , NO_NT , error_string ) ;
}
/*
* Test the NTLM response only , no LM .
*/
static BOOL test_ntlm ( struct samlogon_state * samlogon_state , char * * error_string )
{
return test_lm_ntlm_broken ( samlogon_state , NO_LM , error_string ) ;
}
/*
* Test the NTLM response only , but in the LM field .
*/
static BOOL test_ntlm_in_lm ( struct samlogon_state * samlogon_state , char * * error_string )
{
BOOL pass = True ;
NTSTATUS nt_status ;
DATA_BLOB nt_response = data_blob_talloc ( samlogon_state - > mem_ctx , NULL , 24 ) ;
2004-06-01 12:30:34 +04:00
uint8_t lm_key [ 8 ] ;
uint8_t lm_hash [ 16 ] ;
uint8_t user_session_key [ 16 ] ;
2004-05-09 16:42:18 +04:00
ZERO_STRUCT ( user_session_key ) ;
SMBNTencrypt ( samlogon_state - > password , samlogon_state - > chall . data , nt_response . data ) ;
E_deshash ( samlogon_state - > password , lm_hash ) ;
nt_status = check_samlogon ( samlogon_state ,
BREAK_NONE ,
& samlogon_state - > chall ,
& nt_response ,
NULL ,
lm_key ,
user_session_key ,
error_string ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
return False ;
}
if ( memcmp ( lm_hash , lm_key ,
sizeof ( lm_key ) ) ! = 0 ) {
printf ( " LM Key does not match expectations! \n " ) ;
printf ( " lm_key: \n " ) ;
dump_data ( 1 , ( const char * ) lm_key , 8 ) ;
printf ( " expected: \n " ) ;
dump_data ( 1 , ( const char * ) lm_hash , 8 ) ;
pass = False ;
}
if ( memcmp ( lm_hash , user_session_key , 8 ) ! = 0 ) {
char lm_key_expected [ 16 ] ;
memcpy ( lm_key_expected , lm_hash , 8 ) ;
memset ( lm_key_expected + 8 , ' \0 ' , 8 ) ;
if ( memcmp ( lm_key_expected , user_session_key ,
16 ) ! = 0 ) {
printf ( " NT Session Key does not match expectations (should be first-8 LM hash)! \n " ) ;
printf ( " user_session_key: \n " ) ;
dump_data ( 1 , ( const char * ) user_session_key , sizeof ( user_session_key ) ) ;
printf ( " expected: \n " ) ;
dump_data ( 1 , ( const char * ) lm_key_expected , sizeof ( lm_key_expected ) ) ;
pass = False ;
2004-05-08 06:48:24 +04:00
}
2004-05-09 16:42:18 +04:00
}
return pass ;
}
/*
* Test the NTLM response only , but in the both the NT and LM fields .
*/
2004-05-08 06:48:24 +04:00
2004-05-09 16:42:18 +04:00
static BOOL test_ntlm_in_both ( struct samlogon_state * samlogon_state , char * * error_string )
{
BOOL pass = True ;
2004-09-04 04:02:43 +04:00
BOOL lm_good ;
2004-05-09 16:42:18 +04:00
NTSTATUS nt_status ;
DATA_BLOB nt_response = data_blob_talloc ( samlogon_state - > mem_ctx , NULL , 24 ) ;
DATA_BLOB session_key = data_blob_talloc ( samlogon_state - > mem_ctx , NULL , 16 ) ;
char lm_key [ 8 ] ;
char lm_hash [ 16 ] ;
char user_session_key [ 16 ] ;
char nt_hash [ 16 ] ;
ZERO_STRUCT ( lm_key ) ;
ZERO_STRUCT ( user_session_key ) ;
SMBNTencrypt ( samlogon_state - > password , samlogon_state - > chall . data ,
nt_response . data ) ;
2004-05-29 12:11:46 +04:00
E_md4hash ( samlogon_state - > password , ( uint8_t * ) nt_hash ) ;
SMBsesskeygen_ntv1 ( ( const uint8_t * ) nt_hash ,
2004-05-09 16:42:18 +04:00
session_key . data ) ;
2004-09-04 04:02:43 +04:00
lm_good = E_deshash ( samlogon_state - > password , ( uint8_t * ) lm_hash ) ;
if ( ! lm_good ) {
ZERO_STRUCT ( lm_hash ) ;
}
2004-05-09 16:42:18 +04:00
nt_status = check_samlogon ( samlogon_state ,
BREAK_NONE ,
& samlogon_state - > chall ,
NULL ,
& nt_response ,
lm_key ,
user_session_key ,
error_string ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
return False ;
}
if ( memcmp ( lm_hash , lm_key ,
sizeof ( lm_key ) ) ! = 0 ) {
printf ( " LM Key does not match expectations! \n " ) ;
printf ( " lm_key: \n " ) ;
dump_data ( 1 , lm_key , 8 ) ;
printf ( " expected: \n " ) ;
dump_data ( 1 , lm_hash , 8 ) ;
pass = False ;
}
if ( memcmp ( session_key . data , user_session_key ,
sizeof ( user_session_key ) ) ! = 0 ) {
printf ( " NT Session Key does not match expectations! \n " ) ;
printf ( " user_session_key: \n " ) ;
dump_data ( 1 , user_session_key , 16 ) ;
printf ( " expected: \n " ) ;
dump_data ( 1 , ( const char * ) session_key . data , session_key . length ) ;
pass = False ;
}
return pass ;
}
/*
* Test the NTLMv2 and LMv2 responses
*/
static BOOL test_lmv2_ntlmv2_broken ( struct samlogon_state * samlogon_state , enum ntlm_break break_which , char * * error_string )
{
BOOL pass = True ;
NTSTATUS nt_status ;
DATA_BLOB ntlmv2_response = data_blob ( NULL , 0 ) ;
DATA_BLOB lmv2_response = data_blob ( NULL , 0 ) ;
DATA_BLOB ntlmv2_session_key = data_blob ( NULL , 0 ) ;
2004-05-25 18:06:28 +04:00
DATA_BLOB names_blob = NTLMv2_generate_names_blob ( samlogon_state - > mem_ctx , lp_netbios_name ( ) , lp_workgroup ( ) ) ;
2004-05-09 16:42:18 +04:00
2004-06-01 12:30:34 +04:00
uint8_t user_session_key [ 16 ] ;
2004-05-09 16:42:18 +04:00
ZERO_STRUCT ( user_session_key ) ;
2004-05-13 19:31:21 +04:00
/* TODO - test with various domain cases, and without domain */
2004-08-25 18:31:59 +04:00
if ( ! SMBNTLMv2encrypt ( samlogon_state - > account_name , samlogon_state - > account_domain ,
2004-05-25 18:06:28 +04:00
samlogon_state - > password , & samlogon_state - > chall ,
2004-05-09 16:42:18 +04:00
& names_blob ,
& lmv2_response , & ntlmv2_response ,
& ntlmv2_session_key ) ) {
data_blob_free ( & names_blob ) ;
return False ;
}
data_blob_free ( & names_blob ) ;
nt_status = check_samlogon ( samlogon_state ,
break_which ,
& samlogon_state - > chall ,
& lmv2_response ,
& ntlmv2_response ,
NULL ,
user_session_key ,
error_string ) ;
data_blob_free ( & lmv2_response ) ;
data_blob_free ( & ntlmv2_response ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
return break_which = = BREAK_NT ;
}
if ( break_which ! = NO_NT & & break_which ! = BREAK_NT & & memcmp ( ntlmv2_session_key . data , user_session_key ,
sizeof ( user_session_key ) ) ! = 0 ) {
printf ( " USER (NTLMv2) Session Key does not match expectations! \n " ) ;
printf ( " user_session_key: \n " ) ;
dump_data ( 1 , ( const char * ) user_session_key , 16 ) ;
printf ( " expected: \n " ) ;
dump_data ( 1 , ( const char * ) ntlmv2_session_key . data , ntlmv2_session_key . length ) ;
pass = False ;
}
return pass ;
}
/*
* Test the NTLMv2 and LMv2 responses
*/
static BOOL test_lmv2_ntlmv2 ( struct samlogon_state * samlogon_state , char * * error_string )
{
return test_lmv2_ntlmv2_broken ( samlogon_state , BREAK_NONE , error_string ) ;
}
/*
* Test the LMv2 response only
*/
static BOOL test_lmv2 ( struct samlogon_state * samlogon_state , char * * error_string )
{
return test_lmv2_ntlmv2_broken ( samlogon_state , NO_NT , error_string ) ;
}
/*
* Test the NTLMv2 response only
*/
static BOOL test_ntlmv2 ( struct samlogon_state * samlogon_state , char * * error_string )
{
return test_lmv2_ntlmv2_broken ( samlogon_state , NO_LM , error_string ) ;
}
static BOOL test_lm_ntlm ( struct samlogon_state * samlogon_state , char * * error_string )
{
return test_lm_ntlm_broken ( samlogon_state , BREAK_NONE , error_string ) ;
}
static BOOL test_ntlm_lm_broken ( struct samlogon_state * samlogon_state , char * * error_string )
{
return test_lm_ntlm_broken ( samlogon_state , BREAK_LM , error_string ) ;
}
static BOOL test_ntlm_ntlm_broken ( struct samlogon_state * samlogon_state , char * * error_string )
{
return test_lm_ntlm_broken ( samlogon_state , BREAK_NT , error_string ) ;
}
static BOOL test_ntlmv2_lmv2_broken ( struct samlogon_state * samlogon_state , char * * error_string )
{
return test_lmv2_ntlmv2_broken ( samlogon_state , BREAK_LM , error_string ) ;
}
static BOOL test_ntlmv2_ntlmv2_broken ( struct samlogon_state * samlogon_state , char * * error_string )
{
return test_lmv2_ntlmv2_broken ( samlogon_state , BREAK_NT , error_string ) ;
}
static BOOL test_plaintext ( struct samlogon_state * samlogon_state , enum ntlm_break break_which , char * * error_string )
{
NTSTATUS nt_status ;
DATA_BLOB nt_response = data_blob ( NULL , 0 ) ;
DATA_BLOB lm_response = data_blob ( NULL , 0 ) ;
char * password ;
char * dospw ;
2004-10-08 12:13:00 +04:00
void * unicodepw ;
2004-05-09 16:42:18 +04:00
2004-06-01 12:30:34 +04:00
uint8_t user_session_key [ 16 ] ;
uint8_t lm_key [ 16 ] ;
static const uint8_t zeros [ 8 ] ;
2004-05-09 16:42:18 +04:00
DATA_BLOB chall = data_blob_talloc ( samlogon_state - > mem_ctx , zeros , sizeof ( zeros ) ) ;
ZERO_STRUCT ( user_session_key ) ;
2004-10-08 12:13:00 +04:00
if ( ( push_ucs2_talloc ( samlogon_state - > mem_ctx , & unicodepw ,
2004-05-09 16:42:18 +04:00
samlogon_state - > password ) ) = = - 1 ) {
DEBUG ( 0 , ( " push_ucs2_allocate failed! \n " ) ) ;
exit ( 1 ) ;
}
2004-10-08 12:13:00 +04:00
nt_response = data_blob_talloc ( samlogon_state - > mem_ctx , unicodepw , utf16_len ( unicodepw ) ) ;
2004-05-09 16:42:18 +04:00
r2552: Character set conversion and string handling updates.
The intial motivation for this commit was to merge in some of the
bugfixes present in Samba3's chrcnv and string handling code into
Samba4. However, along the way I found a lot of unused functions, and
decided to do a bit more...
The strlen_m code now does not use a fixed buffer, but more work is
needed to finish off other functions in str_util.c. These fixed
length buffers hav caused very nasty, hard to chase down bugs at some
sites.
The strupper_m() function has a strupper_talloc() to replace it (we
need to go around and fix more uses, but it's a start). Use of these
new functions will avoid bugs where the upper or lowercase version of
a string is a different length.
I have removed the push_*_allocate functions, which are replaced by
calls to push_*_talloc. Likewise, pstring and other 'fixed length'
wrappers are removed, where possible.
I have removed the first ('base pointer') argument, used by push_ucs2,
as the Samba4 way of doing things ensures that this is always on an
even boundary anyway. (It was used in only one place, in any case).
(This used to be commit dfecb0150627b500cb026b8a4932fe87902ca392)
2004-09-23 04:51:45 +04:00
password = strupper_talloc ( samlogon_state - > mem_ctx , samlogon_state - > password ) ;
2004-05-09 16:42:18 +04:00
if ( ( convert_string_talloc ( samlogon_state - > mem_ctx , CH_UNIX ,
CH_DOS , password ,
strlen ( password ) + 1 ,
r2552: Character set conversion and string handling updates.
The intial motivation for this commit was to merge in some of the
bugfixes present in Samba3's chrcnv and string handling code into
Samba4. However, along the way I found a lot of unused functions, and
decided to do a bit more...
The strlen_m code now does not use a fixed buffer, but more work is
needed to finish off other functions in str_util.c. These fixed
length buffers hav caused very nasty, hard to chase down bugs at some
sites.
The strupper_m() function has a strupper_talloc() to replace it (we
need to go around and fix more uses, but it's a start). Use of these
new functions will avoid bugs where the upper or lowercase version of
a string is a different length.
I have removed the push_*_allocate functions, which are replaced by
calls to push_*_talloc. Likewise, pstring and other 'fixed length'
wrappers are removed, where possible.
I have removed the first ('base pointer') argument, used by push_ucs2,
as the Samba4 way of doing things ensures that this is always on an
even boundary anyway. (It was used in only one place, in any case).
(This used to be commit dfecb0150627b500cb026b8a4932fe87902ca392)
2004-09-23 04:51:45 +04:00
( void * * ) & dospw ) ) = = - 1 ) {
DEBUG ( 0 , ( " convert_string_talloc failed! \n " ) ) ;
2004-05-09 16:42:18 +04:00
exit ( 1 ) ;
}
lm_response = data_blob_talloc ( samlogon_state - > mem_ctx , dospw , strlen ( dospw ) ) ;
nt_status = check_samlogon ( samlogon_state ,
break_which ,
& chall ,
& lm_response ,
& nt_response ,
lm_key ,
user_session_key ,
error_string ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
return break_which = = BREAK_NT ;
}
return True ;
}
static BOOL test_plaintext_none_broken ( struct samlogon_state * samlogon_state ,
char * * error_string ) {
return test_plaintext ( samlogon_state , BREAK_NONE , error_string ) ;
}
static BOOL test_plaintext_lm_broken ( struct samlogon_state * samlogon_state ,
char * * error_string ) {
return test_plaintext ( samlogon_state , BREAK_LM , error_string ) ;
}
static BOOL test_plaintext_nt_broken ( struct samlogon_state * samlogon_state ,
char * * error_string ) {
return test_plaintext ( samlogon_state , BREAK_NT , error_string ) ;
}
static BOOL test_plaintext_nt_only ( struct samlogon_state * samlogon_state ,
char * * error_string ) {
return test_plaintext ( samlogon_state , NO_LM , error_string ) ;
}
static BOOL test_plaintext_lm_only ( struct samlogon_state * samlogon_state ,
char * * error_string ) {
return test_plaintext ( samlogon_state , NO_NT , error_string ) ;
}
/*
Tests :
- LM only
- NT and LM
- NT
- NT in LM field
- NT in both fields
- NTLMv2
- NTLMv2 and LMv2
- LMv2
2004-06-05 07:37:27 +04:00
- plaintext tests ( in challenge - response fields )
2004-05-09 16:42:18 +04:00
check we get the correct session key in each case
check what values we get for the LM session key
*/
static const struct ntlm_tests {
BOOL ( * fn ) ( struct samlogon_state * , char * * ) ;
const char * name ;
BOOL expect_fail ;
} test_table [ ] = {
{ test_lm , " LM " , False } ,
{ test_lm_ntlm , " LM and NTLM " , False } ,
{ test_ntlm , " NTLM " , False } ,
{ test_ntlm_in_lm , " NTLM in LM " , False } ,
{ test_ntlm_in_both , " NTLM in both " , False } ,
{ test_ntlmv2 , " NTLMv2 " , False } ,
{ test_lmv2_ntlmv2 , " NTLMv2 and LMv2 " , False } ,
{ test_lmv2 , " LMv2 " , False } ,
{ test_ntlmv2_lmv2_broken , " NTLMv2 and LMv2, LMv2 broken " , False } ,
{ test_ntlmv2_ntlmv2_broken , " NTLMv2 and LMv2, NTLMv2 broken " , False } ,
{ test_ntlm_lm_broken , " NTLM and LM, LM broken " , False } ,
{ test_ntlm_ntlm_broken , " NTLM and LM, NTLM broken " , False } ,
{ test_plaintext_none_broken , " Plaintext " , True } ,
{ test_plaintext_lm_broken , " Plaintext LM broken " , True } ,
{ test_plaintext_nt_broken , " Plaintext NT broken " , True } ,
{ test_plaintext_nt_only , " Plaintext NT only " , True } ,
{ test_plaintext_lm_only , " Plaintext LM only " , True } ,
{ NULL , NULL }
} ;
/*
try a netlogon SamLogon
*/
static BOOL test_SamLogon ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx )
{
2004-09-04 04:02:43 +04:00
int i , v , l ;
2004-05-09 16:42:18 +04:00
BOOL ret = True ;
2004-06-14 15:33:28 +04:00
int validation_levels [ ] = { 2 , 3 , 6 } ;
2004-09-04 04:02:43 +04:00
int logon_levels [ ] = { 2 , 6 } ;
2004-05-09 16:42:18 +04:00
struct samlogon_state samlogon_state ;
samlogon_state . mem_ctx = mem_ctx ;
2004-06-05 07:22:10 +04:00
samlogon_state . account_name = lp_parm_string ( - 1 , " torture " , " username " ) ;
2004-08-25 18:31:59 +04:00
samlogon_state . account_domain = lp_parm_string ( - 1 , " torture " , " userdomain " ) ;
2004-05-09 16:42:18 +04:00
samlogon_state . password = lp_parm_string ( - 1 , " torture " , " password " ) ;
samlogon_state . p = p ;
samlogon_state . chall = data_blob_talloc ( mem_ctx , NULL , 8 ) ;
2004-07-14 16:14:07 +04:00
generate_random_buffer ( samlogon_state . chall . data , 8 ) ;
2004-05-09 16:42:18 +04:00
if ( ! test_SetupCredentials2 ( p , mem_ctx , NETLOGON_NEG_AUTH2_FLAGS , & samlogon_state . creds ) ) {
return False ;
}
2004-05-30 17:15:15 +04:00
if ( ! test_SetupCredentials3 ( p , mem_ctx , NETLOGON_NEG_AUTH2_FLAGS , & samlogon_state . creds ) ) {
return False ;
}
if ( ! test_SetupCredentials3 ( p , mem_ctx , NETLOGON_NEG_AUTH2_ADS_FLAGS , & samlogon_state . creds ) ) {
return False ;
}
2004-05-09 16:42:18 +04:00
samlogon_state . r . in . server_name = talloc_asprintf ( mem_ctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
samlogon_state . r . in . workstation = TEST_MACHINE_NAME ;
samlogon_state . r . in . credential = & samlogon_state . auth ;
2004-06-07 12:54:49 +04:00
samlogon_state . r . in . return_authenticator = & samlogon_state . auth2 ;
2004-05-09 16:42:18 +04:00
2004-09-04 04:02:43 +04:00
for ( i = 0 ; test_table [ i ] . fn ; i + + ) {
for ( v = 0 ; v < ARRAY_SIZE ( validation_levels ) ; v + + ) {
for ( l = 0 ; l < ARRAY_SIZE ( logon_levels ) ; l + + ) {
char * error_string = NULL ;
samlogon_state . r . in . validation_level = validation_levels [ v ] ;
samlogon_state . r . in . logon_level = logon_levels [ l ] ;
printf ( " Testing SamLogon with '%s' at validation level %d, logon level %d \n " ,
test_table [ i ] . name , validation_levels [ v ] , logon_levels [ l ] ) ;
2004-05-09 16:42:18 +04:00
2004-09-04 04:02:43 +04:00
if ( ! test_table [ i ] . fn ( & samlogon_state , & error_string ) ) {
if ( test_table [ i ] . expect_fail ) {
printf ( " Test %s failed (expected, test incomplete): %s \n " , test_table [ i ] . name , error_string ) ;
} else {
printf ( " Test %s failed: %s \n " , test_table [ i ] . name , error_string ) ;
ret = False ;
}
SAFE_FREE ( error_string ) ;
2004-05-09 16:42:18 +04:00
}
}
2004-05-08 06:48:24 +04:00
}
2003-12-02 03:31:54 +03:00
}
2004-05-08 06:48:24 +04:00
return ret ;
2003-12-02 03:31:54 +03:00
}
/*
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 ;
2004-05-09 16:42:18 +04:00
struct creds_CredentialState creds ;
2003-12-02 03:31:54 +03:00
if ( ! test_SetupCredentials ( p , mem_ctx , & creds ) ) {
return False ;
}
r . in . server_name = talloc_asprintf ( mem_ctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
2004-06-05 07:22:10 +04:00
r . in . account_name = talloc_asprintf ( mem_ctx , " %s$ " , TEST_MACHINE_NAME ) ;
2003-12-02 14:43:09 +03:00
r . in . secure_channel_type = SEC_CHAN_BDC ;
2004-04-27 10:36:39 +04:00
r . in . computer_name = TEST_MACHINE_NAME ;
2003-12-02 03:31:54 +03:00
2004-05-15 11:51:38 +04:00
password = generate_random_str ( mem_ctx , 8 ) ;
2004-06-04 15:58:46 +04:00
E_md4hash ( password , r . in . new_password . hash ) ;
2003-12-02 03:31:54 +03:00
2004-05-09 16:42:18 +04:00
creds_des_encrypt ( & creds , & r . in . new_password ) ;
2003-12-02 03:31:54 +03:00
printf ( " Testing ServerPasswordSet on machine account \n " ) ;
2004-05-15 11:51:38 +04:00
printf ( " Changing machine account password to '%s' \n " , password ) ;
2003-12-02 03:31:54 +03:00
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 ;
}
2003-12-02 05:15:33 +03:00
if ( ! creds_client_check ( & creds , & r . out . return_authenticator . cred ) ) {
printf ( " Credential chaining failed \n " ) ;
}
2004-05-22 11:55:48 +04:00
/* by changing the machine password twice we test the
credentials chaining fully , and we verify that the server
allows the password to be set to the same value twice in a
row ( match win2k3 ) */
2003-12-02 05:15:33 +03:00
printf ( " Testing a second ServerPasswordSet on machine account \n " ) ;
2004-08-25 05:58:08 +04:00
printf ( " Changing machine account password to '%s' (same as previous run) \n " , password ) ;
2003-12-02 05:15:33 +03:00
creds_client_authenticator ( & creds , & r . in . credential ) ;
status = dcerpc_netr_ServerPasswordSet ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-05-15 11:51:38 +04:00
printf ( " ServerPasswordSet (2) - %s \n " , nt_errstr ( status ) ) ;
2003-12-02 05:15:33 +03:00
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 " ) ;
}
2004-06-06 11:14:10 +04:00
machine_password = password ;
2004-05-15 11:51:38 +04:00
2004-05-16 13:43:19 +04:00
if ( ! test_SetupCredentials ( p , mem_ctx , & creds ) ) {
printf ( " ServerPasswordSet failed to actually change the password \n " ) ;
return False ;
}
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 */
2004-05-25 17:57:39 +04:00
static uint64_t sequence_nums [ 3 ] ;
2003-12-02 11:04:37 +03:00
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 ;
2004-05-09 16:42:18 +04:00
struct creds_CredentialState creds ;
2004-05-25 20:24:13 +04:00
const uint32_t database_ids [ ] = { 0 , 1 , 2 } ;
2003-12-02 07:33:57 +03:00
int i ;
BOOL ret = True ;
2003-12-02 06:06:21 +03:00
if ( ! test_SetupCredentials ( p , mem_ctx , & creds ) ) {
return False ;
}
2003-12-02 13:34:06 +03:00
r . in . logon_server = talloc_asprintf ( mem_ctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
2004-04-27 10:36:39 +04:00
r . in . computername = TEST_MACHINE_NAME ;
2004-05-25 20:24:13 +04:00
r . in . preferredmaximumlength = ( uint32_t ) - 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 ;
2004-05-25 17:57:39 +04:00
printf ( " \t sequence_nums[%d]=%llu \n " ,
2003-12-02 11:04:37 +03:00
r . in . database_id ,
2004-05-25 17:57:39 +04:00
sequence_nums [ r . in . database_id ] ) ;
2003-12-02 11:04:37 +03:00
}
} 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 ;
2004-05-09 16:42:18 +04:00
struct creds_CredentialState creds ;
2004-05-25 20:24:13 +04:00
const uint32_t database_ids [ ] = { 0 , 1 , 2 } ;
2003-12-02 11:04:37 +03:00
int i ;
BOOL ret = True ;
if ( ! test_SetupCredentials ( p , mem_ctx , & creds ) ) {
return False ;
}
2003-12-02 13:34:06 +03:00
r . in . logon_server = talloc_asprintf ( mem_ctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
2004-04-27 10:36:39 +04:00
r . in . computername = TEST_MACHINE_NAME ;
2004-05-25 20:24:13 +04:00
r . in . preferredmaximumlength = ( uint32_t ) - 1 ;
2003-12-02 11:04:37 +03:00
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 ] ;
2004-04-09 11:51:03 +04:00
2004-05-25 17:57:39 +04:00
if ( r . in . sequence_num = = 0 ) continue ;
2004-04-09 11:51:03 +04:00
2004-05-25 17:57:39 +04:00
r . in . sequence_num - = 1 ;
2003-12-02 11:04:37 +03:00
2004-04-09 11:51:03 +04:00
2004-05-25 17:57:39 +04:00
printf ( " Testing DatabaseDeltas of id %d at %llu \n " ,
r . in . database_id , r . in . sequence_num ) ;
2003-12-02 11:04:37 +03:00
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 " ) ;
}
2004-05-25 17:57:39 +04:00
r . in . sequence_num + + ;
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 ;
2004-05-09 16:42:18 +04:00
struct creds_CredentialState creds ;
2003-12-02 12:52:15 +03:00
BOOL ret = True ;
if ( ! test_SetupCredentials ( p , mem_ctx , & creds ) ) {
return False ;
}
2003-12-02 13:34:06 +03:00
r . in . logon_server = talloc_asprintf ( mem_ctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
2004-04-27 10:36:39 +04:00
r . in . computername = TEST_MACHINE_NAME ;
2003-12-02 12:52:15 +03:00
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 ;
2004-05-09 16:42:18 +04:00
struct creds_CredentialState creds ;
2003-12-02 13:04:10 +03:00
BOOL ret = True ;
if ( ! test_SetupCredentials ( p , mem_ctx , & creds ) ) {
return False ;
}
2003-12-02 13:34:06 +03:00
r . in . logon_server = talloc_asprintf ( mem_ctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
2004-04-27 10:36:39 +04:00
r . in . computername = TEST_MACHINE_NAME ;
2003-12-02 13:04:10 +03:00
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 ;
}
2003-12-02 13:34:06 +03:00
printf ( " \t DC is at '%s' \n " , r . out . dcname ) ;
return True ;
}
/*
try a netlogon LogonControl
*/
static BOOL test_LogonControl ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx )
{
NTSTATUS status ;
struct netr_LogonControl r ;
BOOL ret = True ;
int i ;
r . in . logon_server = talloc_asprintf ( mem_ctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
r . in . function_code = 1 ;
for ( i = 1 ; i < 4 ; i + + ) {
r . in . level = i ;
printf ( " Testing LogonControl level %d \n " , i ) ;
status = dcerpc_netr_LogonControl ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " LogonControl - %s \n " , nt_errstr ( status ) ) ;
ret = False ;
}
}
return ret ;
}
/*
try a netlogon GetAnyDCName
*/
static BOOL test_GetAnyDCName ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx )
{
NTSTATUS status ;
struct netr_GetAnyDCName r ;
r . in . logon_server = talloc_asprintf ( mem_ctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
r . in . domainname = lp_workgroup ( ) ;
printf ( " Testing GetAnyDCName \n " ) ;
status = dcerpc_netr_GetAnyDCName ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " GetAnyDCName - %s \n " , nt_errstr ( status ) ) ;
return False ;
}
if ( r . out . dcname ) {
printf ( " \t DC is at '%s' \n " , r . out . dcname ) ;
}
2003-12-02 13:08:26 +03:00
return True ;
}
2003-12-02 12:52:15 +03:00
2003-12-02 14:43:09 +03:00
/*
try a netlogon LogonControl2
*/
static BOOL test_LogonControl2 ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx )
{
NTSTATUS status ;
struct netr_LogonControl2 r ;
BOOL ret = True ;
int i ;
r . in . logon_server = talloc_asprintf ( mem_ctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
r . in . function_code = NETLOGON_CONTROL_REDISCOVER ;
r . in . data . domain = lp_workgroup ( ) ;
for ( i = 1 ; i < 4 ; i + + ) {
r . in . level = i ;
printf ( " Testing LogonControl2 level %d function %d \n " ,
i , r . in . function_code ) ;
status = dcerpc_netr_LogonControl2 ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " LogonControl - %s \n " , nt_errstr ( status ) ) ;
ret = False ;
}
}
r . in . function_code = NETLOGON_CONTROL_TC_QUERY ;
r . in . data . domain = lp_workgroup ( ) ;
for ( i = 1 ; i < 4 ; i + + ) {
r . in . level = i ;
printf ( " Testing LogonControl2 level %d function %d \n " ,
i , r . in . function_code ) ;
status = dcerpc_netr_LogonControl2 ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " LogonControl - %s \n " , nt_errstr ( status ) ) ;
ret = False ;
}
}
r . in . function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY ;
r . in . data . domain = lp_workgroup ( ) ;
for ( i = 1 ; i < 4 ; i + + ) {
r . in . level = i ;
printf ( " Testing LogonControl2 level %d function %d \n " ,
i , r . in . function_code ) ;
status = dcerpc_netr_LogonControl2 ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " LogonControl - %s \n " , nt_errstr ( status ) ) ;
ret = False ;
}
}
r . in . function_code = NETLOGON_CONTROL_SET_DBFLAG ;
r . in . data . debug_level = ~ 0 ;
for ( i = 1 ; i < 4 ; i + + ) {
r . in . level = i ;
printf ( " Testing LogonControl2 level %d function %d \n " ,
i , r . in . function_code ) ;
status = dcerpc_netr_LogonControl2 ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " LogonControl - %s \n " , nt_errstr ( status ) ) ;
ret = False ;
}
}
return ret ;
}
2003-12-02 15:01:10 +03:00
/*
try a netlogon DatabaseSync2
*/
static BOOL test_DatabaseSync2 ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx )
{
NTSTATUS status ;
struct netr_DatabaseSync2 r ;
2004-05-09 16:42:18 +04:00
struct creds_CredentialState creds ;
2004-05-25 20:24:13 +04:00
const uint32_t database_ids [ ] = { 0 , 1 , 2 } ;
2003-12-02 15:01:10 +03:00
int i ;
BOOL ret = True ;
2004-05-09 16:42:18 +04:00
if ( ! test_SetupCredentials2 ( p , mem_ctx , NETLOGON_NEG_AUTH2_FLAGS , & creds ) ) {
2003-12-02 15:01:10 +03:00
return False ;
}
r . in . logon_server = talloc_asprintf ( mem_ctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
2004-04-27 10:36:39 +04:00
r . in . computername = TEST_MACHINE_NAME ;
2004-05-25 20:24:13 +04:00
r . in . preferredmaximumlength = ( uint32_t ) - 1 ;
2003-12-02 15:01:10 +03:00
ZERO_STRUCT ( r . in . return_authenticator ) ;
for ( i = 0 ; i < ARRAY_SIZE ( database_ids ) ; i + + ) {
r . in . sync_context = 0 ;
r . in . database_id = database_ids [ i ] ;
r . in . restart_state = 0 ;
printf ( " Testing DatabaseSync2 of id %d \n " , r . in . database_id ) ;
do {
creds_client_authenticator ( & creds , & r . in . credential ) ;
status = dcerpc_netr_DatabaseSync2 ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) & &
! NT_STATUS_EQUAL ( status , STATUS_MORE_ENTRIES ) ) {
printf ( " DatabaseSync2 - %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 ;
} while ( NT_STATUS_EQUAL ( status , STATUS_MORE_ENTRIES ) ) ;
}
return ret ;
}
2003-12-02 15:16:08 +03:00
/*
try a netlogon LogonControl2Ex
*/
static BOOL test_LogonControl2Ex ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx )
{
NTSTATUS status ;
struct netr_LogonControl2Ex r ;
BOOL ret = True ;
int i ;
r . in . logon_server = talloc_asprintf ( mem_ctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
r . in . function_code = NETLOGON_CONTROL_REDISCOVER ;
r . in . data . domain = lp_workgroup ( ) ;
for ( i = 1 ; i < 4 ; i + + ) {
r . in . level = i ;
printf ( " Testing LogonControl2Ex level %d function %d \n " ,
i , r . in . function_code ) ;
status = dcerpc_netr_LogonControl2Ex ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " LogonControl - %s \n " , nt_errstr ( status ) ) ;
ret = False ;
}
}
r . in . function_code = NETLOGON_CONTROL_TC_QUERY ;
r . in . data . domain = lp_workgroup ( ) ;
for ( i = 1 ; i < 4 ; i + + ) {
r . in . level = i ;
printf ( " Testing LogonControl2Ex level %d function %d \n " ,
i , r . in . function_code ) ;
status = dcerpc_netr_LogonControl2Ex ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " LogonControl - %s \n " , nt_errstr ( status ) ) ;
ret = False ;
}
}
r . in . function_code = NETLOGON_CONTROL_TRANSPORT_NOTIFY ;
r . in . data . domain = lp_workgroup ( ) ;
for ( i = 1 ; i < 4 ; i + + ) {
r . in . level = i ;
printf ( " Testing LogonControl2Ex level %d function %d \n " ,
i , r . in . function_code ) ;
status = dcerpc_netr_LogonControl2Ex ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " LogonControl - %s \n " , nt_errstr ( status ) ) ;
ret = False ;
}
}
r . in . function_code = NETLOGON_CONTROL_SET_DBFLAG ;
r . in . data . debug_level = ~ 0 ;
for ( i = 1 ; i < 4 ; i + + ) {
r . in . level = i ;
printf ( " Testing LogonControl2Ex level %d function %d \n " ,
i , r . in . function_code ) ;
status = dcerpc_netr_LogonControl2Ex ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " LogonControl - %s \n " , nt_errstr ( status ) ) ;
ret = False ;
}
}
return ret ;
}
2004-05-28 17:23:30 +04:00
/*
try a netlogon netr_DsrEnumerateDomainTrusts
*/
static BOOL test_DsrEnumerateDomainTrusts ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx )
{
NTSTATUS status ;
struct netr_DsrEnumerateDomainTrusts r ;
r . in . server_name = talloc_asprintf ( mem_ctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
r . in . trust_flags = 0x3f ;
printf ( " Testing netr_DsrEnumerateDomainTrusts \n " ) ;
status = dcerpc_netr_DsrEnumerateDomainTrusts ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) | | ! W_ERROR_IS_OK ( r . out . result ) ) {
printf ( " netr_DsrEnumerateDomainTrusts - %s/%s \n " ,
nt_errstr ( status ) , win_errstr ( r . out . result ) ) ;
return False ;
}
return True ;
}
2004-06-15 07:53:21 +04:00
/*
test an ADS style interactive domain login
*/
static BOOL test_InteractiveLogin ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx ,
struct creds_CredentialState * creds )
{
NTSTATUS status ;
struct netr_LogonSamLogonWithFlags r ;
struct netr_Authenticator a , ra ;
struct netr_PasswordInfo pinfo ;
const char * plain_pass ;
ZERO_STRUCT ( r ) ;
ZERO_STRUCT ( ra ) ;
creds_client_authenticator ( creds , & a ) ;
r . in . server_name = talloc_asprintf ( mem_ctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
r . in . workstation = TEST_MACHINE_NAME ;
r . in . credential = & a ;
r . in . return_authenticator = & ra ;
r . in . logon_level = 5 ;
r . in . logon . password = & pinfo ;
r . in . validation_level = 6 ;
r . in . flags = 0 ;
2004-08-25 18:31:59 +04:00
pinfo . identity_info . domain_name . string = lp_parm_string ( - 1 , " torture " , " userdomain " ) ;
2004-06-15 07:53:21 +04:00
pinfo . identity_info . parameter_control = 0 ;
pinfo . identity_info . logon_id_low = 0 ;
pinfo . identity_info . logon_id_high = 0 ;
pinfo . identity_info . account_name . string = lp_parm_string ( - 1 , " torture " , " username " ) ;
pinfo . identity_info . workstation . string = TEST_MACHINE_NAME ;
plain_pass = lp_parm_string ( - 1 , " torture " , " password " ) ;
E_deshash ( plain_pass , pinfo . lmpassword . hash ) ;
E_md4hash ( plain_pass , pinfo . ntpassword . hash ) ;
creds_arcfour_crypt ( creds , pinfo . lmpassword . hash , 16 ) ;
creds_arcfour_crypt ( creds , pinfo . ntpassword . hash , 16 ) ;
printf ( " Testing netr_LogonSamLogonWithFlags \n " ) ;
status = dcerpc_netr_LogonSamLogonWithFlags ( p , mem_ctx , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " netr_LogonSamLogonWithFlags - %s \n " , nt_errstr ( status ) ) ;
exit ( 1 ) ;
return False ;
}
if ( ! creds_client_check ( creds , & r . out . return_authenticator - > cred ) ) {
printf ( " Credential chaining failed \n " ) ;
return False ;
}
return True ;
}
2004-06-14 12:15:31 +04:00
static BOOL test_GetDomainInfo ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx )
{
NTSTATUS status ;
struct netr_LogonGetDomainInfo r ;
struct netr_DomainQuery1 q1 ;
struct netr_Authenticator a ;
struct creds_CredentialState creds ;
2004-06-15 07:53:21 +04:00
if ( ! test_SetupCredentials3 ( p , mem_ctx , NETLOGON_NEG_AUTH2_ADS_FLAGS , & creds ) ) {
2004-06-14 12:15:31 +04:00
return False ;
}
ZERO_STRUCT ( r ) ;
creds_client_authenticator ( & creds , & a ) ;
r . in . server_name = talloc_asprintf ( mem_ctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
r . in . computer_name = TEST_MACHINE_NAME ;
r . in . unknown1 = 512 ;
r . in . level = 1 ;
r . in . credential = & a ;
r . out . credential = & a ;
2004-08-23 11:12:13 +04:00
r . in . i1 [ 0 ] = 0 ;
r . in . i1 [ 1 ] = 0 ;
2004-06-14 12:15:31 +04:00
r . in . query . query1 = & q1 ;
ZERO_STRUCT ( q1 ) ;
/* this should really be the fully qualified name */
q1 . workstation_domain = TEST_MACHINE_NAME ;
q1 . workstation_site = " Default-First-Site-Name " ;
q1 . blob2 . length = 0 ;
q1 . blob2 . size = 0 ;
q1 . blob2 . data = NULL ;
q1 . product . string = " product string " ;
printf ( " Testing netr_LogonGetDomainInfo \n " ) ;
status = dcerpc_netr_LogonGetDomainInfo ( p , mem_ctx , & r ) ;
2004-06-15 07:53:21 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " netr_LogonGetDomainInfo - %s \n " , nt_errstr ( status ) ) ;
return False ;
}
2004-06-14 12:15:31 +04:00
if ( ! creds_client_check ( & creds , & a . cred ) ) {
printf ( " Credential chaining failed \n " ) ;
2004-06-15 07:53:21 +04:00
return False ;
2004-06-14 12:15:31 +04:00
}
2004-06-15 07:53:21 +04:00
test_InteractiveLogin ( p , mem_ctx , & creds ) ;
2004-06-14 12:15:31 +04:00
return True ;
}
2004-09-02 16:03:16 +04:00
static void async_callback ( struct rpc_request * req )
{
int * counter = req - > async . private ;
if ( NT_STATUS_IS_OK ( req - > status ) ) {
( * counter ) + + ;
}
}
2004-09-02 15:06:23 +04:00
static BOOL test_GetDomainInfo_async ( struct dcerpc_pipe * p , TALLOC_CTX * mem_ctx )
{
NTSTATUS status ;
struct netr_LogonGetDomainInfo r ;
struct netr_DomainQuery1 q1 ;
struct netr_Authenticator a ;
# define ASYNC_COUNT 100
struct creds_CredentialState creds ;
struct creds_CredentialState creds_async [ ASYNC_COUNT ] ;
struct rpc_request * req [ ASYNC_COUNT ] ;
int i ;
2004-09-02 16:03:16 +04:00
int async_counter = 0 ;
2004-09-02 15:06:23 +04:00
if ( ! test_SetupCredentials3 ( p , mem_ctx , NETLOGON_NEG_AUTH2_ADS_FLAGS , & creds ) ) {
return False ;
}
ZERO_STRUCT ( r ) ;
r . in . server_name = talloc_asprintf ( mem_ctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
r . in . computer_name = TEST_MACHINE_NAME ;
r . in . unknown1 = 512 ;
r . in . level = 1 ;
r . in . credential = & a ;
r . out . credential = & a ;
r . in . i1 [ 0 ] = 0 ;
r . in . i1 [ 1 ] = 0 ;
r . in . query . query1 = & q1 ;
ZERO_STRUCT ( q1 ) ;
/* this should really be the fully qualified name */
q1 . workstation_domain = TEST_MACHINE_NAME ;
q1 . workstation_site = " Default-First-Site-Name " ;
q1 . blob2 . length = 0 ;
q1 . blob2 . size = 0 ;
q1 . blob2 . data = NULL ;
q1 . product . string = " product string " ;
printf ( " Testing netr_LogonGetDomainInfo - async count %d \n " , ASYNC_COUNT ) ;
for ( i = 0 ; i < ASYNC_COUNT ; i + + ) {
creds_client_authenticator ( & creds , & a ) ;
creds_async [ i ] = creds ;
req [ i ] = dcerpc_netr_LogonGetDomainInfo_send ( p , mem_ctx , & r ) ;
2004-09-02 16:03:16 +04:00
req [ i ] - > async . callback = async_callback ;
req [ i ] - > async . private = & async_counter ;
/* even with this flush per request a w2k3 server seems to
clag with multiple outstanding requests . bleergh . */
2004-09-20 14:40:11 +04:00
if ( event_loop_once ( dcerpc_event_context ( p ) ) ! = 0 ) {
return False ;
}
2004-09-02 15:06:23 +04:00
}
for ( i = 0 ; i < ASYNC_COUNT ; i + + ) {
status = dcerpc_ndr_request_recv ( req [ i ] ) ;
if ( ! NT_STATUS_IS_OK ( status ) | | ! NT_STATUS_IS_OK ( r . out . result ) ) {
printf ( " netr_LogonGetDomainInfo_async(%d) - %s/%s \n " ,
i , nt_errstr ( status ) , nt_errstr ( r . out . result ) ) ;
2004-09-02 16:03:16 +04:00
break ;
2004-09-02 15:06:23 +04:00
}
if ( ! creds_client_check ( & creds_async [ i ] , & a . cred ) ) {
printf ( " Credential chaining failed at async %d \n " , i ) ;
2004-09-02 16:03:16 +04:00
break ;
2004-09-02 15:06:23 +04:00
}
}
2004-09-02 16:03:16 +04:00
printf ( " Testing netr_LogonGetDomainInfo - async count %d OK \n " , async_counter ) ;
2004-09-02 15:06:23 +04:00
2004-09-02 16:03:16 +04:00
return async_counter = = ASYNC_COUNT ;
2004-09-02 15:06:23 +04: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 ;
2004-06-06 11:14:10 +04:00
void * join_ctx ;
2003-12-01 04:41:38 +03:00
mem_ctx = talloc_init ( " torture_rpc_netlogon " ) ;
2004-06-06 11:14:10 +04:00
join_ctx = torture_join_domain ( TEST_MACHINE_NAME , lp_workgroup ( ) , ACB_SVRTRUST ,
& machine_password ) ;
if ( ! join_ctx ) {
2004-04-27 10:36:39 +04:00
printf ( " Failed to join as BDC \n " ) ;
return False ;
}
2003-12-01 04:41:38 +03:00
status = torture_rpc_connection ( & p ,
DCERPC_NETLOGON_NAME ,
DCERPC_NETLOGON_UUID ,
DCERPC_NETLOGON_VERSION ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return False ;
}
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 ;
}
2004-06-15 07:53:21 +04:00
if ( ! test_GetDomainInfo ( p , mem_ctx ) ) {
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-02 13:34:06 +03:00
if ( ! test_LogonControl ( p , mem_ctx ) ) {
ret = False ;
}
if ( ! test_GetAnyDCName ( p , mem_ctx ) ) {
ret = False ;
}
2003-12-02 14:43:09 +03:00
if ( ! test_LogonControl2 ( p , mem_ctx ) ) {
ret = False ;
}
2003-12-02 15:01:10 +03:00
if ( ! test_DatabaseSync2 ( p , mem_ctx ) ) {
ret = False ;
}
2003-12-02 15:16:08 +03:00
if ( ! test_LogonControl2Ex ( p , mem_ctx ) ) {
ret = False ;
}
2004-05-28 17:23:30 +04:00
if ( ! test_DsrEnumerateDomainTrusts ( p , mem_ctx ) ) {
ret = False ;
}
2004-09-02 15:06:23 +04:00
if ( ! test_GetDomainInfo_async ( p , mem_ctx ) ) {
ret = False ;
}
2004-08-04 11:44:14 +04:00
talloc_destroy ( mem_ctx ) ;
torture_rpc_close ( p ) ;
2003-12-01 04:41:38 +03:00
2004-06-06 11:14:10 +04:00
torture_leave_domain ( join_ctx ) ;
2004-04-27 10:36:39 +04:00
2003-12-01 04:41:38 +03:00
return ret ;
}