2018-07-27 08:44:24 +12:00
/*
* Unit tests for the ntlm_check password hash check library .
*
* Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2018
*
* 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/>.
*
*/
/*
* from cmocka . c :
* These headers or their equivalents should be included prior to
* including
* this header file .
*
* # include < stdarg . h >
* # include < stddef . h >
* # include < setjmp . h >
*
* This allows test applications to use custom definitions of C standard
* library functions and types .
*
*/
/*
* Note that the messaging routines ( audit_message_send and get_event_server )
* are not tested by these unit tests . Currently they are for integration
* test support , and as such are exercised by the integration tests .
*/
# include <stdarg.h>
# include <stddef.h>
2018-08-18 09:43:00 +02:00
# include <stdint.h>
2018-07-27 08:44:24 +12:00
# include <setjmp.h>
# include <cmocka.h>
# include "includes.h"
# include "librpc/gen_ndr/netlogon.h"
# include "libcli/auth/libcli_auth.h"
# include "auth/credentials/credentials.h"
struct ntlm_state {
const char * username ;
const char * domain ;
DATA_BLOB challenge ;
DATA_BLOB ntlm ;
DATA_BLOB lm ;
DATA_BLOB ntlm_key ;
DATA_BLOB lm_key ;
const struct samr_Password * nt_hash ;
} ;
static int test_ntlm_setup_with_options ( void * * state ,
int flags , bool upn )
{
NTSTATUS status ;
DATA_BLOB challenge = {
. data = discard_const_p ( uint8_t , " I am a teapot " ) ,
. length = 8
} ;
struct ntlm_state * ntlm_state = talloc ( NULL , struct ntlm_state ) ;
DATA_BLOB target_info = NTLMv2_generate_names_blob ( ntlm_state ,
NULL ,
" serverdom " ) ;
struct cli_credentials * creds = cli_credentials_init ( ntlm_state ) ;
cli_credentials_set_username ( creds ,
" testuser " ,
CRED_SPECIFIED ) ;
cli_credentials_set_domain ( creds ,
" testdom " ,
CRED_SPECIFIED ) ;
cli_credentials_set_workstation ( creds ,
" testwksta " ,
CRED_SPECIFIED ) ;
cli_credentials_set_password ( creds ,
" testpass " ,
CRED_SPECIFIED ) ;
if ( upn ) {
cli_credentials_set_principal ( creds ,
" testuser@samba.org " ,
CRED_SPECIFIED ) ;
}
cli_credentials_get_ntlm_username_domain ( creds ,
ntlm_state ,
& ntlm_state - > username ,
& ntlm_state - > domain ) ;
status = cli_credentials_get_ntlm_response ( creds ,
ntlm_state ,
& flags ,
challenge ,
NULL ,
target_info ,
& ntlm_state - > lm ,
& ntlm_state - > ntlm ,
& ntlm_state - > lm_key ,
& ntlm_state - > ntlm_key ) ;
ntlm_state - > challenge = challenge ;
ntlm_state - > nt_hash = cli_credentials_get_nt_hash ( creds ,
ntlm_state ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return - 1 ;
}
* state = ntlm_state ;
return 0 ;
}
static int test_ntlm_setup ( void * * state ) {
return test_ntlm_setup_with_options ( state , 0 , false ) ;
}
static int test_ntlm_and_lm_setup ( void * * state ) {
return test_ntlm_setup_with_options ( state ,
CLI_CRED_LANMAN_AUTH ,
false ) ;
}
static int test_ntlm2_setup ( void * * state ) {
return test_ntlm_setup_with_options ( state ,
CLI_CRED_NTLM2 ,
false ) ;
}
static int test_ntlmv2_setup ( void * * state ) {
return test_ntlm_setup_with_options ( state ,
CLI_CRED_NTLMv2_AUTH ,
false ) ;
}
static int test_ntlm_teardown ( void * * state )
{
struct ntlm_state * ntlm_state
= talloc_get_type_abort ( * state ,
struct ntlm_state ) ;
TALLOC_FREE ( ntlm_state ) ;
* state = NULL ;
return 0 ;
}
static void test_ntlm_allowed ( void * * state )
{
DATA_BLOB user_sess_key , lm_sess_key ;
struct ntlm_state * ntlm_state
= talloc_get_type_abort ( * state ,
struct ntlm_state ) ;
NTSTATUS status ;
status = ntlm_password_check ( ntlm_state ,
false ,
NTLM_AUTH_ON ,
0 ,
& ntlm_state - > challenge ,
& ntlm_state - > lm ,
& ntlm_state - > ntlm ,
ntlm_state - > username ,
ntlm_state - > username ,
ntlm_state - > domain ,
NULL ,
ntlm_state - > nt_hash ,
& user_sess_key ,
& lm_sess_key ) ;
assert_int_equal ( NT_STATUS_V ( status ) , NT_STATUS_V ( NT_STATUS_OK ) ) ;
}
static void test_ntlm_allowed_lm_supplied ( void * * state )
{
2019-01-24 10:38:41 +01:00
test_ntlm_allowed ( state ) ;
2018-07-27 08:44:24 +12:00
}
static void test_ntlm_disabled ( void * * state )
{
DATA_BLOB user_sess_key , lm_sess_key ;
struct ntlm_state * ntlm_state
= talloc_get_type_abort ( * state ,
struct ntlm_state ) ;
NTSTATUS status ;
status = ntlm_password_check ( ntlm_state ,
false ,
NTLM_AUTH_DISABLED ,
0 ,
& ntlm_state - > challenge ,
& ntlm_state - > lm ,
& ntlm_state - > ntlm ,
ntlm_state - > username ,
ntlm_state - > username ,
ntlm_state - > domain ,
NULL ,
ntlm_state - > nt_hash ,
& user_sess_key ,
& lm_sess_key ) ;
assert_int_equal ( NT_STATUS_V ( status ) , NT_STATUS_V ( NT_STATUS_NTLM_BLOCKED ) ) ;
}
static void test_ntlm2 ( void * * state )
{
DATA_BLOB user_sess_key , lm_sess_key ;
struct ntlm_state * ntlm_state
= talloc_get_type_abort ( * state ,
struct ntlm_state ) ;
NTSTATUS status ;
status = ntlm_password_check ( ntlm_state ,
false ,
NTLM_AUTH_ON ,
0 ,
& ntlm_state - > challenge ,
& ntlm_state - > lm ,
& ntlm_state - > ntlm ,
ntlm_state - > username ,
ntlm_state - > username ,
ntlm_state - > domain ,
NULL ,
ntlm_state - > nt_hash ,
& user_sess_key ,
& lm_sess_key ) ;
/*
* NTLM2 session security ( where the real challenge is the
* MD5 ( challenge , client - challenge ) ( in the first 8 bytes of
* the lm ) isn ' t decoded by ntlm_password_check ( ) , it must
* first be converted back into normal NTLM by the NTLMSSP
* layer
*/
assert_int_equal ( NT_STATUS_V ( status ) ,
NT_STATUS_V ( NT_STATUS_WRONG_PASSWORD ) ) ;
}
static void test_ntlm_mschapv2_only_allowed ( void * * state )
{
DATA_BLOB user_sess_key , lm_sess_key ;
struct ntlm_state * ntlm_state
= talloc_get_type_abort ( * state ,
struct ntlm_state ) ;
NTSTATUS status ;
status = ntlm_password_check ( ntlm_state ,
false ,
NTLM_AUTH_MSCHAPv2_NTLMV2_ONLY ,
MSV1_0_ALLOW_MSVCHAPV2 ,
& ntlm_state - > challenge ,
& ntlm_state - > lm ,
& ntlm_state - > ntlm ,
ntlm_state - > username ,
ntlm_state - > username ,
ntlm_state - > domain ,
NULL ,
ntlm_state - > nt_hash ,
& user_sess_key ,
& lm_sess_key ) ;
assert_int_equal ( NT_STATUS_V ( status ) , NT_STATUS_V ( NT_STATUS_OK ) ) ;
}
static void test_ntlm_mschapv2_only_denied ( void * * state )
{
DATA_BLOB user_sess_key , lm_sess_key ;
struct ntlm_state * ntlm_state
= talloc_get_type_abort ( * state ,
struct ntlm_state ) ;
NTSTATUS status ;
status = ntlm_password_check ( ntlm_state ,
false ,
NTLM_AUTH_MSCHAPv2_NTLMV2_ONLY ,
0 ,
& ntlm_state - > challenge ,
& ntlm_state - > lm ,
& ntlm_state - > ntlm ,
ntlm_state - > username ,
ntlm_state - > username ,
ntlm_state - > domain ,
NULL ,
ntlm_state - > nt_hash ,
& user_sess_key ,
& lm_sess_key ) ;
assert_int_equal ( NT_STATUS_V ( status ) ,
NT_STATUS_V ( NT_STATUS_WRONG_PASSWORD ) ) ;
}
static void test_ntlmv2_only_ntlmv2 ( void * * state )
{
DATA_BLOB user_sess_key , lm_sess_key ;
struct ntlm_state * ntlm_state
= talloc_get_type_abort ( * state ,
struct ntlm_state ) ;
NTSTATUS status ;
status = ntlm_password_check ( ntlm_state ,
false ,
NTLM_AUTH_NTLMV2_ONLY ,
0 ,
& ntlm_state - > challenge ,
& ntlm_state - > lm ,
& ntlm_state - > ntlm ,
ntlm_state - > username ,
ntlm_state - > username ,
ntlm_state - > domain ,
NULL ,
ntlm_state - > nt_hash ,
& user_sess_key ,
& lm_sess_key ) ;
assert_int_equal ( NT_STATUS_V ( status ) , NT_STATUS_V ( NT_STATUS_OK ) ) ;
}
static void test_ntlmv2_only_ntlm ( void * * state )
{
DATA_BLOB user_sess_key , lm_sess_key ;
struct ntlm_state * ntlm_state
= talloc_get_type_abort ( * state ,
struct ntlm_state ) ;
NTSTATUS status ;
status = ntlm_password_check ( ntlm_state ,
false ,
NTLM_AUTH_NTLMV2_ONLY ,
0 ,
& ntlm_state - > challenge ,
& ntlm_state - > lm ,
& ntlm_state - > ntlm ,
ntlm_state - > username ,
ntlm_state - > username ,
ntlm_state - > domain ,
NULL ,
ntlm_state - > nt_hash ,
& user_sess_key ,
& lm_sess_key ) ;
assert_int_equal ( NT_STATUS_V ( status ) ,
NT_STATUS_V ( NT_STATUS_WRONG_PASSWORD ) ) ;
}
static void test_ntlmv2_only_ntlm_and_lanman ( void * * state )
{
2019-01-24 10:38:41 +01:00
test_ntlmv2_only_ntlm ( state ) ;
2018-07-27 08:44:24 +12:00
}
static void test_ntlmv2_only_ntlm_once ( void * * state )
{
DATA_BLOB user_sess_key , lm_sess_key ;
struct ntlm_state * ntlm_state
= talloc_get_type_abort ( * state ,
struct ntlm_state ) ;
NTSTATUS status ;
status = ntlm_password_check ( ntlm_state ,
false ,
NTLM_AUTH_NTLMV2_ONLY ,
0 ,
& ntlm_state - > challenge ,
& data_blob_null ,
& ntlm_state - > ntlm ,
ntlm_state - > username ,
ntlm_state - > username ,
ntlm_state - > domain ,
NULL ,
ntlm_state - > nt_hash ,
& user_sess_key ,
& lm_sess_key ) ;
assert_int_equal ( NT_STATUS_V ( status ) ,
NT_STATUS_V ( NT_STATUS_WRONG_PASSWORD ) ) ;
}
int main ( int argc , const char * * argv )
{
const struct CMUnitTest tests [ ] = {
cmocka_unit_test_setup_teardown ( test_ntlm_allowed ,
test_ntlm_setup ,
test_ntlm_teardown ) ,
cmocka_unit_test_setup_teardown ( test_ntlm_allowed_lm_supplied ,
test_ntlm_and_lm_setup ,
test_ntlm_teardown ) ,
cmocka_unit_test_setup_teardown ( test_ntlm_disabled ,
test_ntlm_setup ,
test_ntlm_teardown ) ,
cmocka_unit_test_setup_teardown ( test_ntlm2 ,
test_ntlm2_setup ,
test_ntlm_teardown ) ,
cmocka_unit_test_setup_teardown ( test_ntlm_mschapv2_only_allowed ,
test_ntlm_setup ,
test_ntlm_teardown ) ,
cmocka_unit_test_setup_teardown ( test_ntlm_mschapv2_only_denied ,
test_ntlm_setup ,
test_ntlm_teardown ) ,
cmocka_unit_test_setup_teardown ( test_ntlmv2_only_ntlm ,
test_ntlm_setup ,
test_ntlm_teardown ) ,
cmocka_unit_test_setup_teardown ( test_ntlmv2_only_ntlm_and_lanman ,
test_ntlm_and_lm_setup ,
test_ntlm_teardown ) ,
cmocka_unit_test_setup_teardown ( test_ntlmv2_only_ntlm_once ,
test_ntlm_setup ,
test_ntlm_teardown ) ,
cmocka_unit_test_setup_teardown ( test_ntlmv2_only_ntlmv2 ,
test_ntlmv2_setup ,
test_ntlm_teardown )
} ;
cmocka_set_message_output ( CM_OUTPUT_SUBUNIT ) ;
return cmocka_run_group_tests ( tests , NULL , NULL ) ;
}