2008-08-27 15:36:27 +04:00
/*
Unix SMB / CIFS implementation .
test suite for netlogon PAC operations
2012-08-24 04:01:42 +04:00
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2012
2008-08-27 15:36:27 +04: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 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 "auth/auth.h"
2010-03-04 12:07:12 +03:00
# include "auth/auth_sam_reply.h"
2008-08-27 15:36:27 +04:00
# include "auth/gensec/gensec.h"
2010-11-02 09:14:55 +03:00
# include "system/kerberos.h"
# include "auth/kerberos/kerberos.h"
# include "auth/credentials/credentials.h"
# include "auth/credentials/credentials_krb5.h"
2008-08-27 15:36:27 +04:00
# include "lib/cmdline/popt_common.h"
2010-04-14 00:06:51 +04:00
# include "torture/rpc/torture_rpc.h"
2008-08-27 15:36:27 +04:00
# include "libcli/auth/libcli_auth.h"
2010-09-20 11:42:13 +04:00
# include "libcli/security/security.h"
2008-08-27 15:36:27 +04:00
# include "librpc/gen_ndr/ndr_netlogon_c.h"
2011-02-08 08:53:13 +03:00
# include "librpc/gen_ndr/ndr_krb5pac.h"
2010-11-02 09:14:55 +03:00
# include "librpc/gen_ndr/ndr_samr_c.h"
2008-08-27 15:36:27 +04:00
# include "param/param.h"
2010-03-04 12:07:12 +03:00
# define TEST_MACHINE_NAME_BDC "torturepacbdc"
# define TEST_MACHINE_NAME_WKSTA "torturepacwksta"
2010-11-02 09:14:55 +03:00
# define TEST_MACHINE_NAME_WKSTA_DES "torturepacwkdes"
2010-03-04 12:07:12 +03:00
# define TEST_MACHINE_NAME_S2U4SELF_BDC "tests2u4selfbdc"
# define TEST_MACHINE_NAME_S2U4SELF_WKSTA "tests2u4selfwk"
2008-08-27 15:36:27 +04:00
2012-01-30 01:00:28 +04:00
struct pac_data {
struct PAC_SIGNATURE_DATA * pac_srv_sig ;
struct PAC_SIGNATURE_DATA * pac_kdc_sig ;
} ;
2011-12-29 04:46:41 +04:00
/* A helper function which avoids touching the local databases to
* generate the session info , as we just want to verify the PAC
* details , not the full local token */
static NTSTATUS test_generate_session_info_pac ( struct auth4_context * auth_ctx ,
2011-12-29 15:36:14 +04:00
TALLOC_CTX * mem_ctx ,
2011-12-29 04:46:41 +04:00
struct smb_krb5_context * smb_krb5_context ,
DATA_BLOB * pac_blob ,
const char * principal_name ,
const struct tsocket_address * remote_address ,
uint32_t session_info_flags ,
struct auth_session_info * * session_info )
{
NTSTATUS nt_status ;
struct auth_user_info_dc * user_info_dc ;
2011-12-29 15:36:14 +04:00
TALLOC_CTX * tmp_ctx ;
2012-01-30 01:00:28 +04:00
struct pac_data * pac_data ;
2011-12-29 15:36:14 +04:00
tmp_ctx = talloc_named ( mem_ctx , 0 , " gensec_gssapi_session_info context " ) ;
NT_STATUS_HAVE_NO_MEMORY ( tmp_ctx ) ;
2011-12-29 04:46:41 +04:00
2012-01-30 01:00:28 +04:00
auth_ctx - > private_data = pac_data = talloc_zero ( auth_ctx , struct pac_data ) ;
pac_data - > pac_srv_sig = talloc ( tmp_ctx , struct PAC_SIGNATURE_DATA ) ;
if ( ! pac_data - > pac_srv_sig ) {
2011-12-29 15:36:14 +04:00
talloc_free ( tmp_ctx ) ;
2011-12-29 04:46:41 +04:00
return NT_STATUS_NO_MEMORY ;
}
2012-01-30 01:00:28 +04:00
pac_data - > pac_kdc_sig = talloc ( tmp_ctx , struct PAC_SIGNATURE_DATA ) ;
if ( ! pac_data - > pac_kdc_sig ) {
2011-12-29 15:36:14 +04:00
talloc_free ( tmp_ctx ) ;
2011-12-29 04:46:41 +04:00
return NT_STATUS_NO_MEMORY ;
}
2011-12-29 15:36:14 +04:00
nt_status = kerberos_pac_blob_to_user_info_dc ( tmp_ctx ,
2011-12-29 04:46:41 +04:00
* pac_blob ,
smb_krb5_context - > krb5_context ,
& user_info_dc ,
2012-01-30 01:00:28 +04:00
pac_data - > pac_srv_sig ,
pac_data - > pac_kdc_sig ) ;
2011-12-29 04:46:41 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
2011-12-29 15:36:14 +04:00
talloc_free ( tmp_ctx ) ;
2011-12-29 04:46:41 +04:00
return nt_status ;
}
2012-01-30 01:00:28 +04:00
talloc_steal ( pac_data , pac_data - > pac_srv_sig ) ;
talloc_steal ( pac_data , pac_data - > pac_kdc_sig ) ;
2012-01-25 03:01:10 +04:00
if ( user_info_dc - > info - > authenticated ) {
session_info_flags | = AUTH_SESSION_INFO_AUTHENTICATED ;
}
2011-12-29 04:46:41 +04:00
session_info_flags | = AUTH_SESSION_INFO_SIMPLE_PRIVILEGES ;
2011-12-29 15:36:14 +04:00
nt_status = auth_generate_session_info ( mem_ctx ,
2011-12-29 04:46:41 +04:00
NULL ,
NULL ,
user_info_dc , session_info_flags ,
session_info ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
2011-12-29 15:36:14 +04:00
talloc_free ( tmp_ctx ) ;
2011-12-29 04:46:41 +04:00
return nt_status ;
}
2011-12-29 15:36:14 +04:00
talloc_free ( tmp_ctx ) ;
2011-12-29 04:46:41 +04:00
return nt_status ;
}
2008-08-27 15:36:27 +04:00
/* Check to see if we can pass the PAC across to the NETLOGON server for validation */
/* Also happens to be a really good one-step verfication of our Kerberos stack */
static bool test_PACVerify ( struct torture_context * tctx ,
struct dcerpc_pipe * p ,
2010-03-04 12:07:12 +03:00
struct cli_credentials * credentials ,
enum netr_SchannelType secure_channel_type ,
const char * test_machine_name )
2008-08-27 15:36:27 +04:00
{
NTSTATUS status ;
struct netr_LogonSamLogon r ;
2008-10-28 21:03:50 +03:00
union netr_LogonLevel logon ;
union netr_Validation validation ;
uint8_t authoritative ;
struct netr_Authenticator return_authenticator ;
2008-08-27 15:36:27 +04:00
struct netr_GenericInfo generic ;
struct netr_Authenticator auth , auth2 ;
2009-04-06 16:54:44 +04:00
struct netlogon_creds_CredentialState * creds ;
2008-08-27 15:36:27 +04:00
struct gensec_security * gensec_client_context ;
struct gensec_security * gensec_server_context ;
2008-08-28 10:30:17 +04:00
DATA_BLOB client_to_server , server_to_client , pac_wrapped , payload ;
2008-08-27 15:36:27 +04:00
struct PAC_Validate pac_wrapped_struct ;
enum ndr_err_code ndr_err ;
2011-12-29 04:46:41 +04:00
struct auth4_context * auth_context ;
2008-08-27 15:36:27 +04:00
struct auth_session_info * session_info ;
2012-01-30 01:00:28 +04:00
struct pac_data * pac_data ;
2008-08-27 15:36:27 +04:00
2010-03-16 13:24:25 +03:00
struct dcerpc_binding_handle * b = p - > binding_handle ;
2008-08-27 15:36:27 +04:00
TALLOC_CTX * tmp_ctx = talloc_new ( tctx ) ;
torture_assert ( tctx , tmp_ctx ! = NULL , " talloc_new() failed " ) ;
if ( ! test_SetupCredentials2 ( p , tctx , NETLOGON_NEG_AUTH2_ADS_FLAGS ,
2010-03-04 12:07:12 +03:00
credentials , secure_channel_type ,
2008-08-27 15:36:27 +04:00
& creds ) ) {
return false ;
}
2011-12-29 04:46:41 +04:00
auth_context = talloc_zero ( tmp_ctx , struct auth4_context ) ;
torture_assert ( tctx , auth_context ! = NULL , " talloc_new() failed " ) ;
auth_context - > generate_session_info_pac = test_generate_session_info_pac ;
2011-10-17 11:22:33 +04:00
status = gensec_client_start ( tctx , & gensec_client_context ,
2010-07-16 08:32:42 +04:00
lpcfg_gensec_settings ( tctx , tctx - > lp_ctx ) ) ;
2008-08-27 15:36:27 +04:00
torture_assert_ntstatus_ok ( tctx , status , " gensec_client_start (client) failed " ) ;
2010-03-04 12:07:12 +03:00
status = gensec_set_target_hostname ( gensec_client_context , test_machine_name ) ;
2008-08-27 15:36:27 +04:00
status = gensec_set_credentials ( gensec_client_context , cmdline_credentials ) ;
torture_assert_ntstatus_ok ( tctx , status , " gensec_set_credentials (client) failed " ) ;
status = gensec_start_mech_by_sasl_name ( gensec_client_context , " GSSAPI " ) ;
torture_assert_ntstatus_ok ( tctx , status , " gensec_start_mech_by_sasl_name (client) failed " ) ;
2011-10-17 11:22:33 +04:00
status = gensec_server_start ( tctx ,
2010-07-16 08:32:42 +04:00
lpcfg_gensec_settings ( tctx , tctx - > lp_ctx ) ,
2011-12-29 04:46:41 +04:00
auth_context , & gensec_server_context ) ;
2008-08-27 15:36:27 +04:00
torture_assert_ntstatus_ok ( tctx , status , " gensec_server_start (server) failed " ) ;
status = gensec_set_credentials ( gensec_server_context , credentials ) ;
torture_assert_ntstatus_ok ( tctx , status , " gensec_set_credentials (server) failed " ) ;
status = gensec_start_mech_by_sasl_name ( gensec_server_context , " GSSAPI " ) ;
torture_assert_ntstatus_ok ( tctx , status , " gensec_start_mech_by_sasl_name (server) failed " ) ;
server_to_client = data_blob ( NULL , 0 ) ;
do {
/* Do a client-server update dance */
2011-10-17 11:22:33 +04:00
status = gensec_update ( gensec_client_context , tmp_ctx , tctx - > ev , server_to_client , & client_to_server ) ;
2008-08-27 15:36:27 +04:00
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) { ;
torture_assert_ntstatus_ok ( tctx , status , " gensec_update (client) failed " ) ;
}
2011-10-17 11:22:33 +04:00
status = gensec_update ( gensec_server_context , tmp_ctx , tctx - > ev , client_to_server , & server_to_client ) ;
2008-08-27 15:36:27 +04:00
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) { ;
torture_assert_ntstatus_ok ( tctx , status , " gensec_update (server) failed " ) ;
}
2008-09-23 04:14:26 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
2008-08-27 15:36:27 +04:00
break ;
}
} while ( 1 ) ;
/* Extract the PAC using Samba's code */
2011-08-01 09:39:01 +04:00
status = gensec_session_info ( gensec_server_context , gensec_server_context , & session_info ) ;
2008-08-28 10:30:17 +04:00
torture_assert_ntstatus_ok ( tctx , status , " gensec_session_info failed " ) ;
2011-02-08 08:53:13 +03:00
2012-01-30 01:00:28 +04:00
pac_data = talloc_get_type ( auth_context - > private_data , struct pac_data ) ;
torture_assert ( tctx , pac_data ! = NULL , " gensec_update failed to fill in pac_data in auth_context " ) ;
torture_assert ( tctx , pac_data - > pac_srv_sig ! = NULL , " pac_srv_sig not present " ) ;
torture_assert ( tctx , pac_data - > pac_kdc_sig ! = NULL , " pac_kdc_sig not present " ) ;
pac_wrapped_struct . ChecksumLength = pac_data - > pac_srv_sig - > signature . length ;
pac_wrapped_struct . SignatureType = pac_data - > pac_kdc_sig - > type ;
pac_wrapped_struct . SignatureLength = pac_data - > pac_kdc_sig - > signature . length ;
2008-08-28 10:30:17 +04:00
pac_wrapped_struct . ChecksumAndSignature = payload
= data_blob_talloc ( tmp_ctx , NULL ,
pac_wrapped_struct . ChecksumLength
+ pac_wrapped_struct . SignatureLength ) ;
memcpy ( & payload . data [ 0 ] ,
2012-01-30 01:00:28 +04:00
pac_data - > pac_srv_sig - > signature . data ,
2008-08-28 10:30:17 +04:00
pac_wrapped_struct . ChecksumLength ) ;
memcpy ( & payload . data [ pac_wrapped_struct . ChecksumLength ] ,
2012-01-30 01:00:28 +04:00
pac_data - > pac_kdc_sig - > signature . data ,
2008-08-28 10:30:17 +04:00
pac_wrapped_struct . SignatureLength ) ;
2008-08-27 15:36:27 +04:00
2010-05-09 19:20:01 +04:00
ndr_err = ndr_push_struct_blob ( & pac_wrapped , tmp_ctx , & pac_wrapped_struct ,
2008-08-27 15:36:27 +04:00
( ndr_push_flags_fn_t ) ndr_push_PAC_Validate ) ;
torture_assert ( tctx , NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) , " ndr_push_struct_blob of PACValidate structure failed " ) ;
2008-08-29 09:06:30 +04:00
torture_assert ( tctx , ( creds - > negotiate_flags & NETLOGON_NEG_ARCFOUR ) , " not willing to even try a PACValidate without RC4 encryption " ) ;
2009-04-06 16:54:44 +04:00
netlogon_creds_arcfour_crypt ( creds , pac_wrapped . data , pac_wrapped . length ) ;
2008-08-29 09:06:30 +04:00
2008-09-03 08:19:16 +04:00
generic . length = pac_wrapped . length ;
generic . data = pac_wrapped . data ;
2008-08-27 15:36:27 +04:00
/* Validate it over the netlogon pipe */
generic . identity_info . parameter_control = 0 ;
generic . identity_info . logon_id_high = 0 ;
generic . identity_info . logon_id_low = 0 ;
2011-02-08 08:53:13 +03:00
generic . identity_info . domain_name . string = session_info - > info - > domain_name ;
generic . identity_info . account_name . string = session_info - > info - > account_name ;
2010-03-04 12:07:12 +03:00
generic . identity_info . workstation . string = test_machine_name ;
2008-08-27 15:36:27 +04:00
generic . package_name . string = " Kerberos " ;
2008-10-28 21:03:50 +03:00
logon . generic = & generic ;
2008-08-27 15:36:27 +04:00
ZERO_STRUCT ( auth2 ) ;
2009-04-06 16:54:44 +04:00
netlogon_creds_client_authenticator ( creds , & auth ) ;
2008-08-27 15:36:27 +04:00
r . in . credential = & auth ;
r . in . return_authenticator = & auth2 ;
2008-10-28 21:03:50 +03:00
r . in . logon = & logon ;
2008-08-27 15:36:27 +04:00
r . in . logon_level = NetlogonGenericInformation ;
r . in . server_name = talloc_asprintf ( tctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
r . in . computer_name = cli_credentials_get_workstation ( credentials ) ;
r . in . validation_level = NetlogonValidationGenericInfo2 ;
2008-10-28 21:03:50 +03:00
r . out . validation = & validation ;
r . out . authoritative = & authoritative ;
r . out . return_authenticator = & return_authenticator ;
2008-08-27 15:36:27 +04:00
2010-03-19 16:48:36 +03:00
torture_assert_ntstatus_ok ( tctx , dcerpc_netr_LogonSamLogon_r ( b , tctx , & r ) ,
" LogonSamLogon failed " ) ;
2008-08-27 15:36:27 +04:00
2010-03-19 16:48:36 +03:00
torture_assert_ntstatus_ok ( tctx , r . out . result , " LogonSamLogon failed " ) ;
2008-08-27 15:36:27 +04:00
2008-09-03 08:19:16 +04:00
/* This will break the signature nicely (even in the crypto wrapping), check we get a logon failure */
generic . data [ generic . length - 1 ] + + ;
2008-10-28 21:03:50 +03:00
logon . generic = & generic ;
2008-09-03 08:19:16 +04:00
ZERO_STRUCT ( auth2 ) ;
2009-04-06 16:54:44 +04:00
netlogon_creds_client_authenticator ( creds , & auth ) ;
2008-09-03 08:19:16 +04:00
r . in . credential = & auth ;
r . in . return_authenticator = & auth2 ;
r . in . logon_level = NetlogonGenericInformation ;
2008-10-28 21:03:50 +03:00
r . in . logon = & logon ;
2008-09-03 08:19:16 +04:00
r . in . server_name = talloc_asprintf ( tctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
r . in . computer_name = cli_credentials_get_workstation ( credentials ) ;
r . in . validation_level = NetlogonValidationGenericInfo2 ;
2010-03-19 16:48:36 +03:00
torture_assert_ntstatus_ok ( tctx , dcerpc_netr_LogonSamLogon_r ( b , tctx , & r ) ,
" LogonSamLogon failed " ) ;
2008-09-03 08:19:16 +04:00
2010-03-19 16:48:36 +03:00
torture_assert_ntstatus_equal ( tctx , r . out . result , NT_STATUS_LOGON_FAILURE , " LogonSamLogon failed " ) ;
2008-09-03 08:19:16 +04:00
2009-04-06 16:54:44 +04:00
torture_assert ( tctx , netlogon_creds_client_check ( creds , & r . out . return_authenticator - > cred ) ,
2008-09-03 08:19:16 +04:00
" Credential chaining failed " ) ;
/* This will break the parsing nicely (even in the crypto wrapping), check we get INVALID_PARAMETER */
generic . length - - ;
2008-10-28 21:03:50 +03:00
logon . generic = & generic ;
2008-09-03 08:19:16 +04:00
ZERO_STRUCT ( auth2 ) ;
2009-04-06 16:54:44 +04:00
netlogon_creds_client_authenticator ( creds , & auth ) ;
2008-09-03 08:19:16 +04:00
r . in . credential = & auth ;
r . in . return_authenticator = & auth2 ;
r . in . logon_level = NetlogonGenericInformation ;
2008-10-28 21:03:50 +03:00
r . in . logon = & logon ;
2008-09-03 08:19:16 +04:00
r . in . server_name = talloc_asprintf ( tctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
r . in . computer_name = cli_credentials_get_workstation ( credentials ) ;
r . in . validation_level = NetlogonValidationGenericInfo2 ;
2010-03-19 16:48:36 +03:00
torture_assert_ntstatus_ok ( tctx , dcerpc_netr_LogonSamLogon_r ( b , tctx , & r ) ,
" LogonSamLogon failed " ) ;
2008-09-03 08:19:16 +04:00
2010-03-19 16:48:36 +03:00
torture_assert_ntstatus_equal ( tctx , r . out . result , NT_STATUS_INVALID_PARAMETER , " LogonSamLogon failed " ) ;
2008-09-03 08:19:16 +04:00
2009-04-06 16:54:44 +04:00
torture_assert ( tctx , netlogon_creds_client_check ( creds ,
& r . out . return_authenticator - > cred ) ,
2008-09-03 08:19:16 +04:00
" Credential chaining failed " ) ;
2012-01-30 01:00:28 +04:00
pac_wrapped_struct . ChecksumLength = pac_data - > pac_srv_sig - > signature . length ;
pac_wrapped_struct . SignatureType = pac_data - > pac_kdc_sig - > type ;
2008-09-03 08:19:16 +04:00
/* Break the SignatureType */
pac_wrapped_struct . SignatureType + + ;
2012-01-30 01:00:28 +04:00
pac_wrapped_struct . SignatureLength = pac_data - > pac_kdc_sig - > signature . length ;
2008-09-03 08:19:16 +04:00
pac_wrapped_struct . ChecksumAndSignature = payload
= data_blob_talloc ( tmp_ctx , NULL ,
pac_wrapped_struct . ChecksumLength
+ pac_wrapped_struct . SignatureLength ) ;
memcpy ( & payload . data [ 0 ] ,
2012-01-30 01:00:28 +04:00
pac_data - > pac_srv_sig - > signature . data ,
2008-09-03 08:19:16 +04:00
pac_wrapped_struct . ChecksumLength ) ;
memcpy ( & payload . data [ pac_wrapped_struct . ChecksumLength ] ,
2012-01-30 01:00:28 +04:00
pac_data - > pac_kdc_sig - > signature . data ,
2008-09-03 08:19:16 +04:00
pac_wrapped_struct . SignatureLength ) ;
2010-05-09 19:20:01 +04:00
ndr_err = ndr_push_struct_blob ( & pac_wrapped , tmp_ctx , & pac_wrapped_struct ,
2008-09-03 08:19:16 +04:00
( ndr_push_flags_fn_t ) ndr_push_PAC_Validate ) ;
torture_assert ( tctx , NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) , " ndr_push_struct_blob of PACValidate structure failed " ) ;
torture_assert ( tctx , ( creds - > negotiate_flags & NETLOGON_NEG_ARCFOUR ) , " not willing to even try a PACValidate without RC4 encryption " ) ;
2009-04-06 16:54:44 +04:00
netlogon_creds_arcfour_crypt ( creds , pac_wrapped . data , pac_wrapped . length ) ;
2008-09-03 08:19:16 +04:00
generic . length = pac_wrapped . length ;
generic . data = pac_wrapped . data ;
2008-10-28 21:03:50 +03:00
logon . generic = & generic ;
2008-09-03 08:19:16 +04:00
ZERO_STRUCT ( auth2 ) ;
2009-04-06 16:54:44 +04:00
netlogon_creds_client_authenticator ( creds , & auth ) ;
2008-09-03 08:19:16 +04:00
r . in . credential = & auth ;
r . in . return_authenticator = & auth2 ;
r . in . logon_level = NetlogonGenericInformation ;
2008-10-28 21:03:50 +03:00
r . in . logon = & logon ;
2008-09-03 08:19:16 +04:00
r . in . server_name = talloc_asprintf ( tctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
r . in . computer_name = cli_credentials_get_workstation ( credentials ) ;
r . in . validation_level = NetlogonValidationGenericInfo2 ;
2010-03-19 16:48:36 +03:00
torture_assert_ntstatus_ok ( tctx , dcerpc_netr_LogonSamLogon_r ( b , tctx , & r ) ,
" LogonSamLogon failed " ) ;
2008-09-03 08:19:16 +04:00
2010-03-19 16:48:36 +03:00
torture_assert_ntstatus_equal ( tctx , r . out . result , NT_STATUS_LOGON_FAILURE , " LogonSamLogon failed " ) ;
2008-09-03 08:19:16 +04:00
2009-04-06 16:54:44 +04:00
torture_assert ( tctx , netlogon_creds_client_check ( creds , & r . out . return_authenticator - > cred ) ,
2008-08-27 15:36:27 +04:00
" Credential chaining failed " ) ;
2012-01-30 01:00:28 +04:00
pac_wrapped_struct . ChecksumLength = pac_data - > pac_srv_sig - > signature . length ;
pac_wrapped_struct . SignatureType = pac_data - > pac_kdc_sig - > type ;
pac_wrapped_struct . SignatureLength = pac_data - > pac_kdc_sig - > signature . length ;
2008-09-03 08:19:16 +04:00
pac_wrapped_struct . ChecksumAndSignature = payload
= data_blob_talloc ( tmp_ctx , NULL ,
pac_wrapped_struct . ChecksumLength
+ pac_wrapped_struct . SignatureLength ) ;
memcpy ( & payload . data [ 0 ] ,
2012-01-30 01:00:28 +04:00
pac_data - > pac_srv_sig - > signature . data ,
2008-09-03 08:19:16 +04:00
pac_wrapped_struct . ChecksumLength ) ;
memcpy ( & payload . data [ pac_wrapped_struct . ChecksumLength ] ,
2012-01-30 01:00:28 +04:00
pac_data - > pac_kdc_sig - > signature . data ,
2008-09-03 08:19:16 +04:00
pac_wrapped_struct . SignatureLength ) ;
/* Break the signature length */
pac_wrapped_struct . SignatureLength + + ;
2010-05-09 19:20:01 +04:00
ndr_err = ndr_push_struct_blob ( & pac_wrapped , tmp_ctx , & pac_wrapped_struct ,
2008-09-03 08:19:16 +04:00
( ndr_push_flags_fn_t ) ndr_push_PAC_Validate ) ;
torture_assert ( tctx , NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) , " ndr_push_struct_blob of PACValidate structure failed " ) ;
torture_assert ( tctx , ( creds - > negotiate_flags & NETLOGON_NEG_ARCFOUR ) , " not willing to even try a PACValidate without RC4 encryption " ) ;
2009-04-06 16:54:44 +04:00
netlogon_creds_arcfour_crypt ( creds , pac_wrapped . data , pac_wrapped . length ) ;
2008-09-03 08:19:16 +04:00
generic . length = pac_wrapped . length ;
generic . data = pac_wrapped . data ;
2008-10-28 21:03:50 +03:00
logon . generic = & generic ;
2008-09-03 08:19:16 +04:00
ZERO_STRUCT ( auth2 ) ;
2009-04-06 16:54:44 +04:00
netlogon_creds_client_authenticator ( creds , & auth ) ;
2008-09-03 08:19:16 +04:00
r . in . credential = & auth ;
r . in . return_authenticator = & auth2 ;
r . in . logon_level = NetlogonGenericInformation ;
2008-10-28 21:03:50 +03:00
r . in . logon = & logon ;
2008-09-03 08:19:16 +04:00
r . in . server_name = talloc_asprintf ( tctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
r . in . computer_name = cli_credentials_get_workstation ( credentials ) ;
r . in . validation_level = NetlogonValidationGenericInfo2 ;
2010-03-19 16:48:36 +03:00
torture_assert_ntstatus_ok ( tctx , dcerpc_netr_LogonSamLogon_r ( b , tctx , & r ) ,
" LogonSamLogon failed " ) ;
2008-09-03 08:19:16 +04:00
2010-03-19 16:48:36 +03:00
torture_assert_ntstatus_equal ( tctx , r . out . result , NT_STATUS_INVALID_PARAMETER , " LogonSamLogon failed " ) ;
2008-09-03 08:19:16 +04:00
2009-04-06 16:54:44 +04:00
torture_assert ( tctx , netlogon_creds_client_check ( creds , & r . out . return_authenticator - > cred ) ,
2008-09-03 08:19:16 +04:00
" Credential chaining failed " ) ;
2010-03-04 12:07:12 +03:00
return true ;
}
static bool test_PACVerify_bdc ( struct torture_context * tctx ,
struct dcerpc_pipe * p ,
struct cli_credentials * credentials )
{
return test_PACVerify ( tctx , p , credentials , SEC_CHAN_BDC , TEST_MACHINE_NAME_BDC ) ;
}
static bool test_PACVerify_workstation ( struct torture_context * tctx ,
struct dcerpc_pipe * p ,
struct cli_credentials * credentials )
{
return test_PACVerify ( tctx , p , credentials , SEC_CHAN_WKSTA , TEST_MACHINE_NAME_WKSTA ) ;
}
2010-11-02 09:14:55 +03:00
static bool test_PACVerify_workstation_des ( struct torture_context * tctx ,
struct dcerpc_pipe * p , struct cli_credentials * credentials , struct test_join * join_ctx )
{
struct samr_SetUserInfo r ;
union samr_UserInfo user_info ;
struct dcerpc_pipe * samr_pipe = torture_join_samr_pipe ( join_ctx ) ;
2012-05-21 13:45:12 +04:00
# ifdef AD_DC_BUILD_IS_ENABLED
2010-11-02 09:14:55 +03:00
struct smb_krb5_context * smb_krb5_context ;
krb5_error_code ret ;
ret = cli_credentials_get_krb5_context ( cmdline_credentials , tctx - > lp_ctx , & smb_krb5_context ) ;
torture_assert_int_equal ( tctx , ret , 0 , " cli_credentials_get_krb5_context() failed " ) ;
if ( krb5_config_get_bool_default ( smb_krb5_context - > krb5_context , NULL , FALSE ,
" libdefaults " ,
" allow_weak_crypto " , NULL ) = = FALSE ) {
torture_skip ( tctx , " Cannot test DES without [libdefaults] allow_weak_crypto = yes " ) ;
}
2012-05-21 13:45:12 +04:00
# else
torture_skip ( tctx , " Skipping DES test in non-AD DC build " ) ;
# endif
2010-11-02 09:14:55 +03:00
/* Mark this workstation with DES-only */
user_info . info16 . acct_flags = ACB_USE_DES_KEY_ONLY | ACB_WSTRUST ;
r . in . user_handle = torture_join_samr_user_policy ( join_ctx ) ;
r . in . level = 16 ;
r . in . info = & user_info ;
torture_assert_ntstatus_ok ( tctx , dcerpc_samr_SetUserInfo_r ( samr_pipe - > binding_handle , tctx , & r ) ,
" failed to set DES info account flags " ) ;
torture_assert_ntstatus_ok ( tctx , r . out . result ,
" failed to set DES into account flags " ) ;
return test_PACVerify ( tctx , p , credentials , SEC_CHAN_WKSTA , TEST_MACHINE_NAME_WKSTA_DES ) ;
}
2010-03-04 12:07:12 +03:00
/* Check various ways to get the PAC, in particular check the group membership and other details between the PAC from a normal kinit, S2U4Self and a SamLogon */
static bool test_S2U4Self ( struct torture_context * tctx ,
struct dcerpc_pipe * p ,
struct cli_credentials * credentials ,
enum netr_SchannelType secure_channel_type ,
const char * test_machine_name )
{
NTSTATUS status ;
2010-06-17 01:11:05 +04:00
struct dcerpc_binding_handle * b = p - > binding_handle ;
2010-03-04 12:07:12 +03:00
struct netr_LogonSamLogon r ;
union netr_LogonLevel logon ;
union netr_Validation validation ;
uint8_t authoritative ;
struct netr_Authenticator auth , auth2 ;
DATA_BLOB client_to_server , server_to_client ;
struct netlogon_creds_CredentialState * creds ;
struct gensec_security * gensec_client_context ;
struct gensec_security * gensec_server_context ;
2011-12-29 04:46:41 +04:00
struct auth4_context * auth_context ;
2010-03-04 12:07:12 +03:00
struct auth_session_info * kinit_session_info ;
struct auth_session_info * s2u4self_session_info ;
2011-02-08 08:53:13 +03:00
struct auth_user_info_dc * netlogon_user_info_dc ;
2010-03-04 12:07:12 +03:00
struct netr_NetworkInfo ninfo ;
DATA_BLOB names_blob , chal , lm_resp , nt_resp ;
size_t i ;
int flags = CLI_CRED_NTLMv2_AUTH ;
struct dom_sid * builtin_domain ;
TALLOC_CTX * tmp_ctx = talloc_new ( tctx ) ;
torture_assert ( tctx , tmp_ctx ! = NULL , " talloc_new() failed " ) ;
2011-12-29 04:46:41 +04:00
auth_context = talloc_zero ( tmp_ctx , struct auth4_context ) ;
torture_assert ( tctx , auth_context ! = NULL , " talloc_new() failed " ) ;
auth_context - > generate_session_info_pac = test_generate_session_info_pac ;
2010-03-04 12:07:12 +03:00
/* First, do a normal Kerberos connection */
2011-10-17 11:22:33 +04:00
status = gensec_client_start ( tctx , & gensec_client_context ,
2010-07-16 08:32:42 +04:00
lpcfg_gensec_settings ( tctx , tctx - > lp_ctx ) ) ;
2010-03-04 12:07:12 +03:00
torture_assert_ntstatus_ok ( tctx , status , " gensec_client_start (client) failed " ) ;
status = gensec_set_target_hostname ( gensec_client_context , test_machine_name ) ;
status = gensec_set_credentials ( gensec_client_context , cmdline_credentials ) ;
torture_assert_ntstatus_ok ( tctx , status , " gensec_set_credentials (client) failed " ) ;
status = gensec_start_mech_by_sasl_name ( gensec_client_context , " GSSAPI " ) ;
torture_assert_ntstatus_ok ( tctx , status , " gensec_start_mech_by_sasl_name (client) failed " ) ;
2011-10-17 11:22:33 +04:00
status = gensec_server_start ( tctx ,
2010-07-16 08:32:42 +04:00
lpcfg_gensec_settings ( tctx , tctx - > lp_ctx ) ,
2011-12-29 04:46:41 +04:00
auth_context , & gensec_server_context ) ;
2010-03-04 12:07:12 +03:00
torture_assert_ntstatus_ok ( tctx , status , " gensec_server_start (server) failed " ) ;
status = gensec_set_credentials ( gensec_server_context , credentials ) ;
torture_assert_ntstatus_ok ( tctx , status , " gensec_set_credentials (server) failed " ) ;
status = gensec_start_mech_by_sasl_name ( gensec_server_context , " GSSAPI " ) ;
torture_assert_ntstatus_ok ( tctx , status , " gensec_start_mech_by_sasl_name (server) failed " ) ;
server_to_client = data_blob ( NULL , 0 ) ;
do {
/* Do a client-server update dance */
2011-10-17 11:22:33 +04:00
status = gensec_update ( gensec_client_context , tmp_ctx , tctx - > ev , server_to_client , & client_to_server ) ;
2010-03-04 12:07:12 +03:00
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) { ;
torture_assert_ntstatus_ok ( tctx , status , " gensec_update (client) failed " ) ;
}
2011-10-17 11:22:33 +04:00
status = gensec_update ( gensec_server_context , tmp_ctx , tctx - > ev , client_to_server , & server_to_client ) ;
2010-03-04 12:07:12 +03:00
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) { ;
torture_assert_ntstatus_ok ( tctx , status , " gensec_update (server) failed " ) ;
}
if ( NT_STATUS_IS_OK ( status ) ) {
break ;
}
} while ( 1 ) ;
/* Extract the PAC using Samba's code */
2011-08-01 09:39:01 +04:00
status = gensec_session_info ( gensec_server_context , gensec_server_context , & kinit_session_info ) ;
2010-03-04 12:07:12 +03:00
torture_assert_ntstatus_ok ( tctx , status , " gensec_session_info failed " ) ;
/* Now do the dance with S2U4Self */
/* Wipe out any existing ccache */
cli_credentials_invalidate_ccache ( credentials , CRED_SPECIFIED ) ;
2011-04-22 13:22:50 +04:00
cli_credentials_set_impersonate_principal ( credentials ,
cli_credentials_get_principal ( cmdline_credentials , tmp_ctx ) ,
talloc_asprintf ( tmp_ctx , " host/%s " , test_machine_name ) ) ;
2010-03-04 12:07:12 +03:00
2011-10-17 11:22:33 +04:00
status = gensec_client_start ( tctx , & gensec_client_context ,
2010-07-16 08:32:42 +04:00
lpcfg_gensec_settings ( tctx , tctx - > lp_ctx ) ) ;
2010-03-04 12:07:12 +03:00
torture_assert_ntstatus_ok ( tctx , status , " gensec_client_start (client) failed " ) ;
status = gensec_set_target_hostname ( gensec_client_context , test_machine_name ) ;
/* We now set the same credentials on both client and server contexts */
status = gensec_set_credentials ( gensec_client_context , credentials ) ;
torture_assert_ntstatus_ok ( tctx , status , " gensec_set_credentials (client) failed " ) ;
status = gensec_start_mech_by_sasl_name ( gensec_client_context , " GSSAPI " ) ;
torture_assert_ntstatus_ok ( tctx , status , " gensec_start_mech_by_sasl_name (client) failed " ) ;
2011-10-17 11:22:33 +04:00
status = gensec_server_start ( tctx ,
2010-07-16 08:32:42 +04:00
lpcfg_gensec_settings ( tctx , tctx - > lp_ctx ) ,
2011-12-29 04:46:41 +04:00
auth_context , & gensec_server_context ) ;
2010-03-04 12:07:12 +03:00
torture_assert_ntstatus_ok ( tctx , status , " gensec_server_start (server) failed " ) ;
status = gensec_set_credentials ( gensec_server_context , credentials ) ;
torture_assert_ntstatus_ok ( tctx , status , " gensec_set_credentials (server) failed " ) ;
status = gensec_start_mech_by_sasl_name ( gensec_server_context , " GSSAPI " ) ;
torture_assert_ntstatus_ok ( tctx , status , " gensec_start_mech_by_sasl_name (server) failed " ) ;
server_to_client = data_blob ( NULL , 0 ) ;
do {
/* Do a client-server update dance */
2011-10-17 11:22:33 +04:00
status = gensec_update ( gensec_client_context , tmp_ctx , tctx - > ev , server_to_client , & client_to_server ) ;
2010-03-04 12:07:12 +03:00
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) { ;
torture_assert_ntstatus_ok ( tctx , status , " gensec_update (client) failed " ) ;
}
2011-10-17 11:22:33 +04:00
status = gensec_update ( gensec_server_context , tmp_ctx , tctx - > ev , client_to_server , & server_to_client ) ;
2010-03-04 12:07:12 +03:00
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) { ;
torture_assert_ntstatus_ok ( tctx , status , " gensec_update (server) failed " ) ;
}
if ( NT_STATUS_IS_OK ( status ) ) {
break ;
}
} while ( 1 ) ;
/* Don't pollute the remaining tests with the changed credentials */
cli_credentials_invalidate_ccache ( credentials , CRED_SPECIFIED ) ;
cli_credentials_set_target_service ( credentials , NULL ) ;
2011-04-22 13:22:50 +04:00
cli_credentials_set_impersonate_principal ( credentials , NULL , NULL ) ;
2010-03-04 12:07:12 +03:00
/* Extract the PAC using Samba's code */
2011-08-01 09:39:01 +04:00
status = gensec_session_info ( gensec_server_context , gensec_server_context , & s2u4self_session_info ) ;
2010-03-04 12:07:12 +03:00
torture_assert_ntstatus_ok ( tctx , status , " gensec_session_info failed " ) ;
cli_credentials_get_ntlm_username_domain ( cmdline_credentials , tctx ,
& ninfo . identity_info . account_name . string ,
& ninfo . identity_info . domain_name . string ) ;
/* Now try with SamLogon */
generate_random_buffer ( ninfo . challenge ,
sizeof ( ninfo . challenge ) ) ;
chal = data_blob_const ( ninfo . challenge ,
sizeof ( ninfo . challenge ) ) ;
names_blob = NTLMv2_generate_names_blob ( tctx , cli_credentials_get_workstation ( credentials ) ,
cli_credentials_get_domain ( credentials ) ) ;
status = cli_credentials_get_ntlm_response ( cmdline_credentials , tctx ,
& flags ,
chal ,
names_blob ,
& lm_resp , & nt_resp ,
NULL , NULL ) ;
torture_assert_ntstatus_ok ( tctx , status , " cli_credentials_get_ntlm_response failed " ) ;
ninfo . lm . data = lm_resp . data ;
ninfo . lm . length = lm_resp . length ;
ninfo . nt . data = nt_resp . data ;
ninfo . nt . length = nt_resp . length ;
ninfo . identity_info . parameter_control = 0 ;
ninfo . identity_info . logon_id_low = 0 ;
ninfo . identity_info . logon_id_high = 0 ;
ninfo . identity_info . workstation . string = cli_credentials_get_workstation ( credentials ) ;
logon . network = & ninfo ;
r . in . server_name = talloc_asprintf ( tctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
r . in . computer_name = cli_credentials_get_workstation ( credentials ) ;
r . in . credential = & auth ;
r . in . return_authenticator = & auth2 ;
r . in . logon_level = 2 ;
r . in . logon = & logon ;
r . out . validation = & validation ;
r . out . authoritative = & authoritative ;
if ( ! test_SetupCredentials2 ( p , tctx , NETLOGON_NEG_AUTH2_ADS_FLAGS ,
credentials , secure_channel_type ,
& creds ) ) {
return false ;
}
ZERO_STRUCT ( auth2 ) ;
netlogon_creds_client_authenticator ( creds , & auth ) ;
r . in . validation_level = 3 ;
2010-06-17 01:11:05 +04:00
status = dcerpc_netr_LogonSamLogon_r ( b , tctx , & r ) ;
2010-03-04 12:07:12 +03:00
torture_assert_ntstatus_ok ( tctx , status , " LogonSamLogon failed " ) ;
torture_assert ( tctx , netlogon_creds_client_check ( creds ,
& r . out . return_authenticator - > cred ) ,
" Credential chaining failed " ) ;
2011-02-08 08:53:13 +03:00
status = make_user_info_dc_netlogon_validation ( tmp_ctx ,
2010-03-04 12:07:12 +03:00
ninfo . identity_info . account_name . string ,
r . in . validation_level ,
r . out . validation ,
2011-07-18 07:55:20 +04:00
true , /* This user was authenticated */
2011-02-08 08:53:13 +03:00
& netlogon_user_info_dc ) ;
2010-03-04 12:07:12 +03:00
2011-02-08 08:53:13 +03:00
torture_assert_ntstatus_ok ( tctx , status , " make_user_info_dc_netlogon_validation failed " ) ;
2010-03-04 12:07:12 +03:00
2011-02-08 08:53:13 +03:00
torture_assert_str_equal ( tctx , netlogon_user_info_dc - > info - > account_name = = NULL ? " " : netlogon_user_info_dc - > info - > account_name ,
kinit_session_info - > info - > account_name , " Account name differs for kinit-based PAC " ) ;
torture_assert_str_equal ( tctx , netlogon_user_info_dc - > info - > account_name = = NULL ? " " : netlogon_user_info_dc - > info - > account_name ,
s2u4self_session_info - > info - > account_name , " Account name differs for S2U4Self " ) ;
torture_assert_str_equal ( tctx , netlogon_user_info_dc - > info - > full_name = = NULL ? " " : netlogon_user_info_dc - > info - > full_name , kinit_session_info - > info - > full_name , " Full name differs for kinit-based PAC " ) ;
torture_assert_str_equal ( tctx , netlogon_user_info_dc - > info - > full_name = = NULL ? " " : netlogon_user_info_dc - > info - > full_name , s2u4self_session_info - > info - > full_name , " Full name differs for S2U4Self " ) ;
torture_assert_int_equal ( tctx , netlogon_user_info_dc - > num_sids , kinit_session_info - > torture - > num_dc_sids , " Different numbers of domain groups for kinit-based PAC " ) ;
torture_assert_int_equal ( tctx , netlogon_user_info_dc - > num_sids , s2u4self_session_info - > torture - > num_dc_sids , " Different numbers of domain groups for S2U4Self " ) ;
2010-03-04 12:07:12 +03:00
builtin_domain = dom_sid_parse_talloc ( tmp_ctx , SID_BUILTIN ) ;
2011-02-08 08:53:13 +03:00
for ( i = 0 ; i < kinit_session_info - > torture - > num_dc_sids ; i + + ) {
torture_assert ( tctx , dom_sid_equal ( & netlogon_user_info_dc - > sids [ i ] , & kinit_session_info - > torture - > dc_sids [ i ] ) , " Different domain groups for kinit-based PAC " ) ;
torture_assert ( tctx , dom_sid_equal ( & netlogon_user_info_dc - > sids [ i ] , & s2u4self_session_info - > torture - > dc_sids [ i ] ) , " Different domain groups for S2U4Self " ) ;
torture_assert ( tctx , ! dom_sid_in_domain ( builtin_domain , & s2u4self_session_info - > torture - > dc_sids [ i ] ) , " Returned BUILTIN domain in groups for S2U4Self " ) ;
torture_assert ( tctx , ! dom_sid_in_domain ( builtin_domain , & kinit_session_info - > torture - > dc_sids [ i ] ) , " Returned BUILTIN domain in groups kinit-based PAC " ) ;
torture_assert ( tctx , ! dom_sid_in_domain ( builtin_domain , & netlogon_user_info_dc - > sids [ i ] ) , " Returned BUILTIN domian in groups from NETLOGON SamLogon reply " ) ;
2010-03-04 12:07:12 +03:00
}
2008-08-27 15:36:27 +04:00
return true ;
}
2010-03-04 12:07:12 +03:00
static bool test_S2U4Self_bdc ( struct torture_context * tctx ,
struct dcerpc_pipe * p ,
struct cli_credentials * credentials )
{
return test_S2U4Self ( tctx , p , credentials , SEC_CHAN_BDC , TEST_MACHINE_NAME_S2U4SELF_BDC ) ;
}
static bool test_S2U4Self_workstation ( struct torture_context * tctx ,
struct dcerpc_pipe * p ,
struct cli_credentials * credentials )
{
return test_S2U4Self ( tctx , p , credentials , SEC_CHAN_WKSTA , TEST_MACHINE_NAME_S2U4SELF_WKSTA ) ;
}
2008-08-27 15:36:27 +04:00
struct torture_suite * torture_rpc_remote_pac ( TALLOC_CTX * mem_ctx )
{
2010-12-11 05:26:31 +03:00
struct torture_suite * suite = torture_suite_create ( mem_ctx , " pac " ) ;
2008-08-27 15:36:27 +04:00
struct torture_rpc_tcase * tcase ;
2010-03-04 12:07:12 +03:00
/* It is important to use different names, so that old entries in our credential cache are not used */
tcase = torture_suite_add_machine_bdc_rpc_iface_tcase ( suite , " netlogon-bdc " ,
& ndr_table_netlogon , TEST_MACHINE_NAME_BDC ) ;
torture_rpc_tcase_add_test_creds ( tcase , " verify-sig " , test_PACVerify_bdc ) ;
tcase = torture_suite_add_machine_workstation_rpc_iface_tcase ( suite , " netlogon-member " ,
& ndr_table_netlogon , TEST_MACHINE_NAME_WKSTA ) ;
torture_rpc_tcase_add_test_creds ( tcase , " verify-sig " , test_PACVerify_workstation ) ;
2010-11-02 09:14:55 +03:00
tcase = torture_suite_add_machine_workstation_rpc_iface_tcase ( suite , " netlogon-member-des " ,
& ndr_table_netlogon , TEST_MACHINE_NAME_WKSTA_DES ) ;
torture_rpc_tcase_add_test_join ( tcase , " verify-sig " , test_PACVerify_workstation_des ) ;
2010-03-04 12:07:12 +03:00
tcase = torture_suite_add_machine_bdc_rpc_iface_tcase ( suite , " netlogon-bdc " ,
& ndr_table_netlogon , TEST_MACHINE_NAME_S2U4SELF_BDC ) ;
torture_rpc_tcase_add_test_creds ( tcase , " s2u4self " , test_S2U4Self_bdc ) ;
tcase = torture_suite_add_machine_workstation_rpc_iface_tcase ( suite , " netlogon-member " ,
& ndr_table_netlogon , TEST_MACHINE_NAME_S2U4SELF_WKSTA ) ;
2008-08-27 15:36:27 +04:00
2010-03-04 12:07:12 +03:00
torture_rpc_tcase_add_test_creds ( tcase , " s2u4self " , test_S2U4Self_workstation ) ;
2008-08-27 15:36:27 +04:00
return suite ;
}