2021-07-26 11:18:05 +03:00
/*
Unix SMB / CIFS implementation .
test suite for netlogon rpc operations
Copyright ( C ) Andrew Tridgell 2003
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2003 - 2004
Copyright ( C ) Tim Potter 2003
Copyright ( C ) Matthias Dieter Wallnöfer 2009 - 2010
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 3 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 , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
# include "lib/replace/system/network.h"
# include "lib/cmdline/cmdline.h"
# include "torture/rpc/torture_rpc.h"
# include "libcli/auth/libcli_auth.h"
# include "librpc/gen_ndr/ndr_netlogon_c.h"
# include "param/param.h"
# include "lib/param/loadparm.h"
# include "libcli/security/security.h"
# undef strcasecmp
# define TEST_MACHINE_NAME "torturetest"
static bool test_ServerAuth3Crypto ( struct dcerpc_pipe * p ,
struct torture_context * tctx ,
uint32_t negotiate_flags ,
struct cli_credentials * machine_credentials ,
bool force_client_rc4 )
{
struct netr_ServerReqChallenge r ;
struct netr_ServerAuthenticate3 a ;
struct netr_Credential netr_creds1 = {
. data = { 0 } ,
} ;
struct netr_Credential netr_creds2 = {
. data = { 0 } ,
} ;
struct netr_Credential netr_creds3 = {
. data = { 0 } ,
} ;
struct netlogon_creds_CredentialState * creds_state = NULL ;
struct samr_Password machine_password = {
. hash = { 0 } ,
} ;
const char * machine_name = NULL ;
const char * plain_pass = NULL ;
struct dcerpc_binding_handle * b = NULL ;
uint32_t rid = 0 ;
NTSTATUS status ;
bool weak_crypto_allowed =
( lpcfg_weak_crypto ( tctx - > lp_ctx ) = =
SAMBA_WEAK_CRYPTO_ALLOWED ) ;
if ( p = = NULL ) {
return false ;
}
b = p - > binding_handle ;
ZERO_STRUCT ( r ) ;
ZERO_STRUCT ( a ) ;
torture_comment ( tctx , " client negotiate_flags=0x%08x \n " , negotiate_flags ) ;
machine_name = cli_credentials_get_workstation ( machine_credentials ) ;
torture_assert_not_null ( tctx , machine_name , " machine name is not set " ) ;
plain_pass = cli_credentials_get_password ( machine_credentials ) ;
torture_assert_not_null ( tctx , plain_pass , " plain_pass is not set " ) ;
torture_comment ( tctx , " Testing ServerReqChallenge \n " ) ;
r . in . server_name = NULL ;
r . in . computer_name = machine_name ;
r . in . credentials = & netr_creds1 ;
r . out . return_credentials = & netr_creds2 ;
netlogon_creds_random_challenge ( & netr_creds1 ) ;
status = dcerpc_netr_ServerReqChallenge_r ( b , tctx , & r ) ;
torture_assert_ntstatus_ok ( tctx ,
status ,
" ServerReqChallenge failed " ) ;
torture_assert_ntstatus_ok ( tctx ,
r . out . result ,
" ServerReqChallenge failed " ) ;
E_md4hash ( plain_pass , machine_password . hash ) ;
a . in . server_name = NULL ;
a . in . account_name = talloc_asprintf ( tctx , " %s$ " , machine_name ) ;
a . in . secure_channel_type =
cli_credentials_get_secure_channel_type ( machine_credentials ) ;
a . in . computer_name = machine_name ;
a . in . negotiate_flags = & negotiate_flags ;
a . in . credentials = & netr_creds3 ;
a . out . return_credentials = & netr_creds3 ;
a . out . negotiate_flags = & negotiate_flags ;
a . out . rid = & rid ;
if ( force_client_rc4 ) {
GNUTLS_FIPS140_SET_LAX_MODE ( ) ;
}
creds_state = netlogon_creds_client_init ( tctx ,
a . in . account_name ,
a . in . computer_name ,
a . in . secure_channel_type ,
& netr_creds1 ,
& netr_creds2 ,
& machine_password ,
& netr_creds3 ,
2024-10-02 20:06:59 +03:00
negotiate_flags ,
2021-07-26 11:18:05 +03:00
negotiate_flags ) ;
GNUTLS_FIPS140_SET_STRICT_MODE ( ) ;
/* Test that we fail to encrypt with RC4 */
if ( creds_state = = NULL & &
! weak_crypto_allowed & & ! force_client_rc4 & &
( negotiate_flags & NETLOGON_NEG_ARCFOUR ) ) {
return false ;
}
torture_assert_not_null ( tctx ,
creds_state ,
" Failed init netlogon client creds " ) ;
torture_comment ( tctx , " Testing ServerAuthenticate3 \n " ) ;
status = dcerpc_netr_ServerAuthenticate3_r ( b , tctx , & a ) ;
torture_assert_ntstatus_ok ( tctx ,
status ,
" ServerAuthenticate3 failed " ) ;
/* Check that the server denies RC4 */
if ( ! NT_STATUS_IS_OK ( a . out . result ) & &
! weak_crypto_allowed & &
force_client_rc4 ) {
torture_assert_ntstatus_equal ( tctx ,
a . out . result ,
2022-11-25 12:10:33 +03:00
NT_STATUS_DOWNGRADE_DETECTED ,
2021-07-26 11:18:05 +03:00
" Unexpected status code " ) ;
2024-10-10 16:08:01 +03:00
torture_assert_int_equal ( tctx , negotiate_flags , 0 ,
" NT_STATUS_DOWNGRADE_DETECTED... " ) ;
2021-07-26 11:18:05 +03:00
return false ;
}
torture_assert_ntstatus_ok ( tctx ,
a . out . result ,
" ServerAuthenticate3 failed " ) ;
torture_assert ( tctx ,
netlogon_creds_client_check ( creds_state , & netr_creds3 ) ,
" Credential chaining failed " ) ;
torture_comment ( tctx ,
" server negotiate_flags=0x%08x \n " ,
negotiate_flags ) ;
if ( ! weak_crypto_allowed ) {
torture_assert ( tctx ,
2024-10-10 16:02:16 +03:00
( negotiate_flags & NETLOGON_NEG_SUPPORTS_AES ) ,
" Server negotiate AES support " ) ;
2021-07-26 11:18:05 +03:00
}
/* Prove that requesting a challenge again won't break it */
torture_assert_ntstatus_ok ( tctx , dcerpc_netr_ServerReqChallenge_r ( b , tctx , & r ) ,
" ServerReqChallenge failed " ) ;
torture_assert_ntstatus_ok ( tctx , r . out . result , " ServerReqChallenge failed " ) ;
return true ;
}
/* Test that we can successfully authenticate using AES. */
static bool test_AES_Crypto ( struct torture_context * tctx ,
struct dcerpc_pipe * p ,
struct cli_credentials * machine_credentials )
{
uint32_t negotiate_flags =
NETLOGON_NEG_AUTH2_ADS_FLAGS |
NETLOGON_NEG_SUPPORTS_AES ;
bool ok ;
ok = test_ServerAuth3Crypto ( p ,
tctx ,
negotiate_flags ,
machine_credentials ,
false ) ;
if ( ! ok ) {
return false ;
}
return true ;
}
/* If we try to use RC4, the client code should fail to encrypt. */
static bool test_RC4_Crypto_Fail ( struct torture_context * tctx ,
struct dcerpc_pipe * p ,
struct cli_credentials * machine_credentials )
{
uint32_t negotiate_flags =
NETLOGON_NEG_AUTH2_ADS_FLAGS |
NETLOGON_NEG_ARCFOUR ;
bool ok ;
ok = test_ServerAuth3Crypto ( p ,
tctx ,
negotiate_flags ,
machine_credentials ,
false ) ;
if ( ! ok ) {
return true ;
}
return false ;
}
/*
* Enforce the use of RC4 and try to authenticate . The server should fail
* in this case as it doesn ' t allow RC4
*/
static bool test_RC4_Crypto_Force ( struct torture_context * tctx ,
struct dcerpc_pipe * p ,
struct cli_credentials * machine_credentials )
{
uint32_t negotiate_flags =
NETLOGON_NEG_AUTH2_ADS_FLAGS |
NETLOGON_NEG_ARCFOUR ;
bool ok ;
ok = test_ServerAuth3Crypto ( p ,
tctx ,
negotiate_flags ,
machine_credentials ,
true ) ;
if ( ! ok ) {
return true ;
}
return false ;
}
struct torture_suite * torture_rpc_netlogon_crypto_fips ( TALLOC_CTX * mem_ctx )
{
struct torture_suite * suite = torture_suite_create ( mem_ctx ,
" fips.netlogon.crypto " ) ;
struct torture_rpc_tcase * tcase = NULL ;
tcase = torture_suite_add_machine_bdc_rpc_iface_tcase ( suite ,
" netlogon " ,
& ndr_table_netlogon ,
TEST_MACHINE_NAME ) ;
torture_rpc_tcase_add_test_creds ( tcase ,
" test_AES_Crytpo " ,
test_AES_Crypto ) ;
torture_rpc_tcase_add_test_creds ( tcase ,
" test_RC4_Crytpo_Fail " ,
test_RC4_Crypto_Fail ) ;
torture_rpc_tcase_add_test_creds ( tcase ,
" test_RC4_Crytpo_Force " ,
test_RC4_Crypto_Force ) ;
return suite ;
}