2012-01-30 15:42:39 +04:00
/*
2005-04-25 09:03:50 +04:00
Unix SMB / Netbios implementation .
Version 3.0
handle NLTMSSP , client server side parsing
Copyright ( C ) Andrew Tridgell 2001
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2001 - 2005
Copyright ( C ) Stefan Metzmacher 2005
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
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2005-04-25 09:03:50 +04:00
( at your option ) any later version .
2012-01-30 15:42:39 +04:00
2005-04-25 09:03:50 +04:00
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 .
2012-01-30 15:42:39 +04:00
2005-04-25 09:03:50 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-04-25 09:03:50 +04:00
*/
2011-07-25 10:04:38 +04:00
struct auth_session_info ;
2005-04-25 09:03:50 +04:00
# include "includes.h"
# include "auth/ntlmssp/ntlmssp.h"
2009-04-16 04:17:17 +04:00
# include "../libcli/auth/libcli_auth.h"
2006-11-07 03:48:36 +03:00
# include "auth/credentials/credentials.h"
# include "auth/gensec/gensec.h"
2013-08-05 09:12:01 +04:00
# include "auth/gensec/gensec_internal.h"
2007-09-08 16:42:09 +04:00
# include "param/param.h"
2011-07-25 10:04:38 +04:00
# include "auth/ntlmssp/ntlmssp_private.h"
2011-12-27 12:16:14 +04:00
# include "../librpc/gen_ndr/ndr_ntlmssp.h"
# include "../auth/ntlmssp/ntlmssp_ndr.h"
2015-11-27 17:35:40 +03:00
# include "../nsswitch/libwbclient/wbclient.h"
2005-04-25 09:03:50 +04:00
2019-06-26 07:41:05 +03:00
# include "lib/crypto/gnutls_helpers.h"
2018-10-30 11:31:19 +03:00
# include <gnutls/gnutls.h>
# include <gnutls/crypto.h>
2017-12-19 12:49:10 +03:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_AUTH
2005-04-25 09:03:50 +04:00
/*********************************************************************
Client side NTLMSSP
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* Next state function for the Initial packet
2012-01-30 15:42:39 +04:00
*
2005-04-25 09:03:50 +04:00
* @ param ntlmssp_state NTLMSSP State
* @ param out_mem_ctx The DATA_BLOB * out will be allocated on this context
2005-04-25 14:33:00 +04:00
* @ param in A NULL data blob ( input ignored )
* @ param out The initial negotiate request to the server , as an talloc ( ) ed DATA_BLOB , on out_mem_ctx
2012-01-30 15:42:39 +04:00
* @ return Errors or NT_STATUS_OK .
2005-04-25 09:03:50 +04:00
*/
2012-01-30 15:42:39 +04:00
NTSTATUS ntlmssp_client_initial ( struct gensec_security * gensec_security ,
TALLOC_CTX * out_mem_ctx ,
DATA_BLOB in , DATA_BLOB * out )
2005-04-25 09:03:50 +04:00
{
2009-12-30 10:23:13 +03:00
struct gensec_ntlmssp_context * gensec_ntlmssp =
talloc_get_type_abort ( gensec_security - > private_data ,
struct gensec_ntlmssp_context ) ;
2009-12-30 19:57:54 +03:00
struct ntlmssp_state * ntlmssp_state = gensec_ntlmssp - > ntlmssp_state ;
2011-03-29 00:26:27 +04:00
NTSTATUS status ;
2015-11-20 12:52:29 +03:00
const DATA_BLOB version_blob = ntlmssp_version_blob ( ) ;
2008-07-15 09:04:06 +04:00
2005-04-25 09:03:50 +04:00
/* generate the ntlmssp negotiate packet */
2011-12-27 12:16:14 +04:00
status = msrpc_gen ( out_mem_ctx ,
2015-11-20 12:52:29 +03:00
out , " CddAAb " ,
2005-04-25 09:03:50 +04:00
" NTLMSSP " ,
NTLMSSP_NEGOTIATE ,
2009-12-30 19:57:54 +03:00
ntlmssp_state - > neg_flags ,
2015-11-20 12:52:29 +03:00
" " , /* domain */
" " , /* workstation */
version_blob . data , version_blob . length ) ;
2011-03-29 00:26:27 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-12-27 12:16:14 +04:00
DEBUG ( 0 , ( " ntlmssp_client_initial: failed to generate "
" ntlmssp negotiate packet \n " ) ) ;
2011-03-29 00:26:27 +04:00
return status ;
}
2011-12-27 12:16:14 +04:00
if ( DEBUGLEVEL > = 10 ) {
struct NEGOTIATE_MESSAGE * negotiate = talloc (
2012-08-04 11:07:24 +04:00
ntlmssp_state , struct NEGOTIATE_MESSAGE ) ;
2011-12-27 12:16:14 +04:00
if ( negotiate ! = NULL ) {
status = ntlmssp_pull_NEGOTIATE_MESSAGE (
out , negotiate , negotiate ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
NDR_PRINT_DEBUG ( NEGOTIATE_MESSAGE ,
negotiate ) ;
}
TALLOC_FREE ( negotiate ) ;
}
}
2015-11-19 18:26:49 +03:00
ntlmssp_state - > negotiate_blob = data_blob_dup_talloc ( ntlmssp_state ,
* out ) ;
if ( ntlmssp_state - > negotiate_blob . length ! = out - > length ) {
return NT_STATUS_NO_MEMORY ;
}
2009-12-30 19:57:54 +03:00
ntlmssp_state - > expected_state = NTLMSSP_CHALLENGE ;
2005-04-25 09:03:50 +04:00
return NT_STATUS_MORE_PROCESSING_REQUIRED ;
}
2015-11-25 23:41:23 +03:00
NTSTATUS gensec_ntlmssp_resume_ccache ( struct gensec_security * gensec_security ,
TALLOC_CTX * out_mem_ctx ,
DATA_BLOB in , DATA_BLOB * out )
{
struct gensec_ntlmssp_context * gensec_ntlmssp =
talloc_get_type_abort ( gensec_security - > private_data ,
struct gensec_ntlmssp_context ) ;
struct ntlmssp_state * ntlmssp_state = gensec_ntlmssp - > ntlmssp_state ;
uint32_t neg_flags = 0 ;
uint32_t ntlmssp_command ;
NTSTATUS status ;
bool ok ;
* out = data_blob_null ;
if ( in . length = = 0 ) {
/*
* This is compat code for older callers
2015-11-19 18:26:49 +03:00
* which were missing the " initial_blob " / " negotiate_blob " .
*
* That means we can ' t calculate the NTLMSSP_MIC
* field correctly and need to force the
* old_spnego behaviour .
2015-11-25 23:41:23 +03:00
*/
2015-11-19 18:26:49 +03:00
DEBUG ( 10 , ( " %s: in.length==%u force_old_spnego! \n " ,
__func__ , ( unsigned int ) in . length ) ) ;
ntlmssp_state - > force_old_spnego = true ;
2015-12-01 16:54:13 +03:00
ntlmssp_state - > neg_flags | = ntlmssp_state - > required_flags ;
ntlmssp_state - > required_flags = 0 ;
2015-11-25 23:41:23 +03:00
ntlmssp_state - > expected_state = NTLMSSP_CHALLENGE ;
return NT_STATUS_MORE_PROCESSING_REQUIRED ;
}
/* parse the NTLMSSP packet */
if ( in . length > UINT16_MAX ) {
DEBUG ( 1 , ( " %s: reject large request of length %u \n " ,
__func__ , ( unsigned int ) in . length ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
ok = msrpc_parse ( ntlmssp_state , & in , " Cdd " ,
" NTLMSSP " ,
& ntlmssp_command ,
& neg_flags ) ;
if ( ! ok ) {
DEBUG ( 1 , ( " %s: failed to parse NTLMSSP Negotiate of length %u \n " ,
__func__ , ( unsigned int ) in . length ) ) ;
dump_data ( 2 , in . data , in . length ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
if ( ntlmssp_command ! = NTLMSSP_NEGOTIATE ) {
DEBUG ( 1 , ( " %s: no NTLMSSP Negotiate message (length %u) \n " ,
__func__ , ( unsigned int ) in . length ) ) ;
dump_data ( 2 , in . data , in . length ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
ntlmssp_state - > neg_flags = neg_flags ;
DEBUG ( 3 , ( " Imported Negotiate flags: \n " ) ) ;
debug_ntlmssp_flags ( neg_flags ) ;
if ( ntlmssp_state - > neg_flags & NTLMSSP_NEGOTIATE_UNICODE ) {
ntlmssp_state - > unicode = true ;
} else {
ntlmssp_state - > unicode = false ;
}
if ( ntlmssp_state - > neg_flags & NTLMSSP_NEGOTIATE_SIGN ) {
gensec_security - > want_features | = GENSEC_FEATURE_SIGN ;
}
if ( ntlmssp_state - > neg_flags & NTLMSSP_NEGOTIATE_SEAL ) {
gensec_security - > want_features | = GENSEC_FEATURE_SEAL ;
}
2015-12-01 13:01:24 +03:00
ntlmssp_state - > conf_flags = ntlmssp_state - > neg_flags ;
2016-04-20 19:44:21 +03:00
ntlmssp_state - > required_flags = 0 ;
2015-12-01 13:01:24 +03:00
2015-11-25 23:41:23 +03:00
if ( DEBUGLEVEL > = 10 ) {
struct NEGOTIATE_MESSAGE * negotiate = talloc (
ntlmssp_state , struct NEGOTIATE_MESSAGE ) ;
if ( negotiate ! = NULL ) {
status = ntlmssp_pull_NEGOTIATE_MESSAGE (
& in , negotiate , negotiate ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
NDR_PRINT_DEBUG ( NEGOTIATE_MESSAGE ,
negotiate ) ;
}
TALLOC_FREE ( negotiate ) ;
}
}
2015-11-19 18:26:49 +03:00
ntlmssp_state - > negotiate_blob = data_blob_dup_talloc ( ntlmssp_state ,
in ) ;
if ( ntlmssp_state - > negotiate_blob . length ! = in . length ) {
return NT_STATUS_NO_MEMORY ;
}
2015-11-25 23:41:23 +03:00
ntlmssp_state - > expected_state = NTLMSSP_CHALLENGE ;
return NT_STATUS_MORE_PROCESSING_REQUIRED ;
}
2005-04-25 09:03:50 +04:00
/**
* Next state function for the Challenge Packet . Generate an auth packet .
2012-01-30 15:42:39 +04:00
*
2005-04-25 14:33:00 +04:00
* @ param gensec_security GENSEC state
* @ param out_mem_ctx Memory context for * out
* @ param in The server challnege , as a DATA_BLOB . reply . data must be NULL
* @ param out The next request ( auth packet ) to the server , as an allocated DATA_BLOB , on the out_mem_ctx context
2012-01-30 15:42:39 +04:00
* @ return Errors or NT_STATUS_OK .
2005-04-25 09:03:50 +04:00
*/
2012-01-30 15:42:39 +04:00
NTSTATUS ntlmssp_client_challenge ( struct gensec_security * gensec_security ,
2005-04-25 09:03:50 +04:00
TALLOC_CTX * out_mem_ctx ,
2012-01-30 15:42:39 +04:00
const DATA_BLOB in , DATA_BLOB * out )
2005-04-25 09:03:50 +04:00
{
2009-12-30 10:23:13 +03:00
struct gensec_ntlmssp_context * gensec_ntlmssp =
talloc_get_type_abort ( gensec_security - > private_data ,
struct gensec_ntlmssp_context ) ;
2009-12-30 19:57:54 +03:00
struct ntlmssp_state * ntlmssp_state = gensec_ntlmssp - > ntlmssp_state ;
2015-03-10 00:21:22 +03:00
uint32_t chal_flags , ntlmssp_command , unkn1 = 0 , unkn2 = 0 ;
2005-04-25 09:03:50 +04:00
DATA_BLOB server_domain_blob ;
DATA_BLOB challenge_blob ;
2005-10-14 07:57:35 +04:00
DATA_BLOB target_info = data_blob ( NULL , 0 ) ;
2005-04-25 09:03:50 +04:00
char * server_domain ;
const char * chal_parse_string ;
2015-03-10 00:21:22 +03:00
const char * chal_parse_string_short = NULL ;
2005-04-25 09:03:50 +04:00
const char * auth_gen_string ;
DATA_BLOB lm_response = data_blob ( NULL , 0 ) ;
DATA_BLOB nt_response = data_blob ( NULL , 0 ) ;
DATA_BLOB session_key = data_blob ( NULL , 0 ) ;
DATA_BLOB lm_session_key = data_blob ( NULL , 0 ) ;
DATA_BLOB encrypted_session_key = data_blob ( NULL , 0 ) ;
NTSTATUS nt_status ;
2005-10-14 07:57:35 +04:00
int flags = 0 ;
2015-08-25 06:26:42 +03:00
const char * user = NULL , * domain = NULL , * workstation = NULL ;
2015-11-27 17:35:40 +03:00
bool is_anonymous = false ;
2015-11-20 12:52:29 +03:00
const DATA_BLOB version_blob = ntlmssp_version_blob ( ) ;
2015-11-20 11:29:11 +03:00
const NTTIME * server_timestamp = NULL ;
2015-11-19 18:26:49 +03:00
uint8_t mic_buffer [ NTLMSSP_MIC_SIZE ] = { 0 , } ;
DATA_BLOB mic_blob = data_blob_const ( mic_buffer , sizeof ( mic_buffer ) ) ;
2018-10-30 11:31:19 +03:00
gnutls_hmac_hd_t hmac_hnd = NULL ;
int rc ;
2005-04-25 09:03:50 +04:00
2005-10-14 07:57:35 +04:00
TALLOC_CTX * mem_ctx = talloc_new ( out_mem_ctx ) ;
if ( ! mem_ctx ) {
return NT_STATUS_NO_MEMORY ;
}
2005-04-25 10:33:20 +04:00
2005-10-14 07:57:35 +04:00
if ( ! msrpc_parse ( mem_ctx ,
2005-04-25 09:03:50 +04:00
& in , " CdBd " ,
" NTLMSSP " ,
2012-01-30 15:42:39 +04:00
& ntlmssp_command ,
2005-04-25 09:03:50 +04:00
& server_domain_blob ,
& chal_flags ) ) {
DEBUG ( 1 , ( " Failed to parse the NTLMSSP Challenge: (#1) \n " ) ) ;
dump_data ( 2 , in . data , in . length ) ;
2005-10-14 07:57:35 +04:00
talloc_free ( mem_ctx ) ;
2005-04-25 09:03:50 +04:00
return NT_STATUS_INVALID_PARAMETER ;
}
2012-01-30 15:42:39 +04:00
2005-04-25 09:03:50 +04:00
data_blob_free ( & server_domain_blob ) ;
DEBUG ( 3 , ( " Got challenge flags: \n " ) ) ;
debug_ntlmssp_flags ( chal_flags ) ;
2015-12-01 10:46:45 +03:00
nt_status = ntlmssp_handle_neg_flags ( ntlmssp_state ,
chal_flags , " challenge " ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
return nt_status ;
}
2005-04-25 09:03:50 +04:00
2009-12-30 19:57:54 +03:00
if ( ntlmssp_state - > unicode ) {
2009-08-25 14:12:59 +04:00
if ( chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO ) {
2005-04-25 09:03:50 +04:00
chal_parse_string = " CdUdbddB " ;
} else {
chal_parse_string = " CdUdbdd " ;
2015-03-10 00:21:22 +03:00
chal_parse_string_short = " CdUdb " ;
2005-04-25 09:03:50 +04:00
}
2015-11-19 18:26:49 +03:00
auth_gen_string = " CdBBUUUBdbb " ;
2005-04-25 09:03:50 +04:00
} else {
2009-08-25 14:12:59 +04:00
if ( chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO ) {
2005-04-25 09:03:50 +04:00
chal_parse_string = " CdAdbddB " ;
} else {
chal_parse_string = " CdAdbdd " ;
2015-03-10 00:21:22 +03:00
chal_parse_string_short = " CdAdb " ;
2005-04-25 09:03:50 +04:00
}
2015-11-19 18:26:49 +03:00
auth_gen_string = " CdBBAAABdbb " ;
2005-04-25 09:03:50 +04:00
}
2005-10-14 07:57:35 +04:00
if ( ! msrpc_parse ( mem_ctx ,
2005-04-25 09:03:50 +04:00
& in , chal_parse_string ,
" NTLMSSP " ,
2012-01-30 15:42:39 +04:00
& ntlmssp_command ,
2005-04-25 09:03:50 +04:00
& server_domain ,
& chal_flags ,
& challenge_blob , 8 ,
& unkn1 , & unkn2 ,
2005-10-14 07:57:35 +04:00
& target_info ) ) {
2015-03-10 00:21:22 +03:00
bool ok = false ;
2005-04-25 09:03:50 +04:00
DEBUG ( 1 , ( " Failed to parse the NTLMSSP Challenge: (#2) \n " ) ) ;
2015-03-10 00:21:22 +03:00
if ( chal_parse_string_short ! = NULL ) {
/*
* In the case where NTLMSSP_NEGOTIATE_TARGET_INFO
* is not used , some NTLMSSP servers don ' t return
* the unused unkn1 and unkn2 fields .
* See bug :
* https : //bugzilla.samba.org/show_bug.cgi?id=10016
* for packet traces .
* Try and parse again without them .
*/
ok = msrpc_parse ( mem_ctx ,
& in , chal_parse_string_short ,
" NTLMSSP " ,
& ntlmssp_command ,
& server_domain ,
& chal_flags ,
& challenge_blob , 8 ) ;
if ( ! ok ) {
DEBUG ( 1 , ( " Failed to short parse "
" the NTLMSSP Challenge: (#2) \n " ) ) ;
}
}
if ( ! ok ) {
dump_data ( 2 , in . data , in . length ) ;
talloc_free ( mem_ctx ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
2005-04-25 09:03:50 +04:00
}
2019-03-27 19:51:04 +03:00
if ( DEBUGLEVEL > = 10 ) {
struct CHALLENGE_MESSAGE * challenge =
talloc ( ntlmssp_state , struct CHALLENGE_MESSAGE ) ;
if ( challenge ! = NULL ) {
NTSTATUS status ;
challenge - > NegotiateFlags = chal_flags ;
status = ntlmssp_pull_CHALLENGE_MESSAGE (
& in , challenge , challenge ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
NDR_PRINT_DEBUG ( CHALLENGE_MESSAGE ,
challenge ) ;
}
TALLOC_FREE ( challenge ) ;
}
}
2009-12-30 17:00:02 +03:00
if ( chal_flags & NTLMSSP_TARGET_TYPE_SERVER ) {
2009-12-30 19:57:54 +03:00
ntlmssp_state - > server . is_standalone = true ;
2009-12-30 17:00:02 +03:00
} else {
2009-12-30 19:57:54 +03:00
ntlmssp_state - > server . is_standalone = false ;
2009-12-30 17:00:02 +03:00
}
/* TODO: parse struct_blob and fill in the rest */
2009-12-30 19:57:54 +03:00
ntlmssp_state - > server . netbios_name = " " ;
2016-03-03 00:15:50 +03:00
ntlmssp_state - > server . netbios_domain = talloc_move ( ntlmssp_state , & server_domain ) ;
2009-12-30 19:57:54 +03:00
ntlmssp_state - > server . dns_name = " " ;
ntlmssp_state - > server . dns_domain = " " ;
2005-04-25 09:03:50 +04:00
if ( challenge_blob . length ! = 8 ) {
2005-10-14 07:57:35 +04:00
talloc_free ( mem_ctx ) ;
2005-04-25 09:03:50 +04:00
return NT_STATUS_INVALID_PARAMETER ;
}
2015-11-27 17:35:40 +03:00
is_anonymous = cli_credentials_is_anonymous ( gensec_security - > credentials ) ;
2012-01-30 15:42:39 +04:00
cli_credentials_get_ntlm_username_domain ( gensec_security - > credentials , mem_ctx ,
2005-09-22 05:50:58 +04:00
& user , & domain ) ;
2005-04-25 10:33:20 +04:00
2015-08-25 06:26:42 +03:00
workstation = cli_credentials_get_workstation ( gensec_security - > credentials ) ;
if ( user = = NULL ) {
DEBUG ( 10 , ( " User is NULL, returning INVALID_PARAMETER \n " ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
if ( domain = = NULL ) {
DEBUG ( 10 , ( " Domain is NULL, returning INVALID_PARAMETER \n " ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
if ( workstation = = NULL ) {
DEBUG ( 10 , ( " Workstation is NULL, returning INVALID_PARAMETER \n " ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
2015-11-27 17:35:40 +03:00
if ( is_anonymous ) {
2015-12-08 15:59:42 +03:00
ntlmssp_state - > neg_flags | = NTLMSSP_ANONYMOUS ;
2015-11-27 17:35:40 +03:00
/*
* don ' t use the ccache for anonymous auth
*/
ntlmssp_state - > use_ccache = false ;
}
if ( ntlmssp_state - > use_ccache ) {
struct samr_Password * nt_hash = NULL ;
/*
* If we have a password given we don ' t
* use the ccache
*/
nt_hash = cli_credentials_get_nt_hash ( gensec_security - > credentials ,
mem_ctx ) ;
if ( nt_hash ! = NULL ) {
ZERO_STRUCTP ( nt_hash ) ;
TALLOC_FREE ( nt_hash ) ;
ntlmssp_state - > use_ccache = false ;
}
}
if ( ntlmssp_state - > use_ccache ) {
struct wbcCredentialCacheParams params ;
struct wbcCredentialCacheInfo * info = NULL ;
struct wbcAuthErrorInfo * error = NULL ;
2015-11-19 18:26:49 +03:00
struct wbcNamedBlob auth_blobs [ 2 ] ;
2015-11-27 17:35:40 +03:00
const struct wbcBlob * wbc_auth_blob = NULL ;
const struct wbcBlob * wbc_session_key = NULL ;
wbcErr wbc_status ;
int i ;
2015-11-19 18:26:49 +03:00
bool new_spnego = false ;
2015-11-27 17:35:40 +03:00
params . account_name = user ;
params . domain_name = domain ;
params . level = WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP ;
auth_blobs [ 0 ] . name = " challenge_blob " ;
auth_blobs [ 0 ] . flags = 0 ;
auth_blobs [ 0 ] . blob . data = in . data ;
auth_blobs [ 0 ] . blob . length = in . length ;
2015-11-19 18:26:49 +03:00
auth_blobs [ 1 ] . name = " negotiate_blob " ;
auth_blobs [ 1 ] . flags = 0 ;
auth_blobs [ 1 ] . blob . data = ntlmssp_state - > negotiate_blob . data ;
auth_blobs [ 1 ] . blob . length = ntlmssp_state - > negotiate_blob . length ;
2015-11-27 17:35:40 +03:00
params . num_blobs = ARRAY_SIZE ( auth_blobs ) ;
params . blobs = auth_blobs ;
wbc_status = wbcCredentialCache ( & params , & info , & error ) ;
wbcFreeMemory ( error ) ;
if ( ! WBC_ERROR_IS_OK ( wbc_status ) ) {
return NT_STATUS_WRONG_CREDENTIAL_HANDLE ;
}
for ( i = 0 ; i < info - > num_blobs ; i + + ) {
if ( strequal ( info - > blobs [ i ] . name , " auth_blob " ) ) {
wbc_auth_blob = & info - > blobs [ i ] . blob ;
}
if ( strequal ( info - > blobs [ i ] . name , " session_key " ) ) {
wbc_session_key = & info - > blobs [ i ] . blob ;
}
2015-11-19 18:26:49 +03:00
if ( strequal ( info - > blobs [ i ] . name , " new_spnego " ) ) {
new_spnego = true ;
}
2015-11-27 17:35:40 +03:00
}
if ( ( wbc_auth_blob = = NULL ) | | ( wbc_session_key = = NULL ) ) {
wbcFreeMemory ( info ) ;
return NT_STATUS_WRONG_CREDENTIAL_HANDLE ;
}
session_key = data_blob_talloc ( mem_ctx ,
wbc_session_key - > data ,
wbc_session_key - > length ) ;
if ( session_key . length ! = wbc_session_key - > length ) {
wbcFreeMemory ( info ) ;
return NT_STATUS_NO_MEMORY ;
}
* out = data_blob_talloc ( mem_ctx ,
wbc_auth_blob - > data ,
wbc_auth_blob - > length ) ;
if ( out - > length ! = wbc_auth_blob - > length ) {
wbcFreeMemory ( info ) ;
return NT_STATUS_NO_MEMORY ;
}
2015-11-19 18:26:49 +03:00
ntlmssp_state - > new_spnego = new_spnego ;
2015-11-27 17:35:40 +03:00
wbcFreeMemory ( info ) ;
goto done ;
}
2009-12-30 19:57:54 +03:00
if ( ntlmssp_state - > neg_flags & NTLMSSP_NEGOTIATE_NTLM2 ) {
2005-10-14 07:57:35 +04:00
flags | = CLI_CRED_NTLM2 ;
}
2009-12-30 19:57:54 +03:00
if ( ntlmssp_state - > use_ntlmv2 ) {
2005-10-14 07:57:35 +04:00
flags | = CLI_CRED_NTLMv2_AUTH ;
}
2009-12-30 19:57:54 +03:00
if ( ntlmssp_state - > use_nt_response ) {
2005-10-14 07:57:35 +04:00
flags | = CLI_CRED_NTLM_AUTH ;
}
2015-12-01 16:58:19 +03:00
if ( ntlmssp_state - > allow_lm_response ) {
2005-10-14 07:57:35 +04:00
flags | = CLI_CRED_LANMAN_AUTH ;
}
2005-04-25 09:03:50 +04:00
2015-11-19 18:26:49 +03:00
if ( target_info . length ! = 0 & & ! is_anonymous ) {
struct AV_PAIR * pairs = NULL ;
uint32_t count = 0 ;
enum ndr_err_code err ;
struct AV_PAIR * timestamp = NULL ;
struct AV_PAIR * eol = NULL ;
uint32_t i = 0 ;
const char * service = NULL ;
const char * hostname = NULL ;
err = ndr_pull_struct_blob ( & target_info ,
ntlmssp_state ,
& ntlmssp_state - > server . av_pair_list ,
( ndr_pull_flags_fn_t ) ndr_pull_AV_PAIR_LIST ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( err ) ) {
return ndr_map_error2ntstatus ( err ) ;
}
count = ntlmssp_state - > server . av_pair_list . count ;
/*
* We need room for Flags , SingleHost ,
* ChannelBindings and Target
*/
pairs = talloc_zero_array ( ntlmssp_state , struct AV_PAIR ,
count + 4 ) ;
if ( pairs = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
for ( i = 0 ; i < count ; i + + ) {
pairs [ i ] = ntlmssp_state - > server . av_pair_list . pair [ i ] ;
}
ntlmssp_state - > client . av_pair_list . count = count ;
ntlmssp_state - > client . av_pair_list . pair = pairs ;
eol = ndr_ntlmssp_find_av ( & ntlmssp_state - > client . av_pair_list ,
MsvAvEOL ) ;
if ( eol = = NULL ) {
return NT_STATUS_INVALID_PARAMETER ;
}
timestamp = ndr_ntlmssp_find_av ( & ntlmssp_state - > client . av_pair_list ,
MsvAvTimestamp ) ;
if ( timestamp ! = NULL ) {
uint32_t sign_features =
GENSEC_FEATURE_SESSION_KEY |
GENSEC_FEATURE_SIGN |
GENSEC_FEATURE_SEAL ;
server_timestamp = & timestamp - > Value . AvTimestamp ;
if ( ntlmssp_state - > force_old_spnego ) {
sign_features = 0 ;
}
if ( gensec_security - > want_features & sign_features ) {
struct AV_PAIR * av_flags = NULL ;
av_flags = ndr_ntlmssp_find_av ( & ntlmssp_state - > client . av_pair_list ,
MsvAvFlags ) ;
if ( av_flags = = NULL ) {
av_flags = eol ;
eol + + ;
count + + ;
* eol = * av_flags ;
av_flags - > AvId = MsvAvFlags ;
av_flags - > Value . AvFlags = 0 ;
}
av_flags - > Value . AvFlags | = NTLMSSP_AVFLAG_MIC_IN_AUTHENTICATE_MESSAGE ;
ntlmssp_state - > new_spnego = true ;
}
}
{
struct AV_PAIR * SingleHost = NULL ;
SingleHost = eol ;
eol + + ;
count + + ;
* eol = * SingleHost ;
/*
* This is not really used , but we want to
* add some more random bytes and match
* Windows .
*/
SingleHost - > AvId = MsvAvSingleHost ;
SingleHost - > Value . AvSingleHost . token_info . Flags = 0 ;
SingleHost - > Value . AvSingleHost . token_info . TokenIL = 0 ;
generate_random_buffer ( SingleHost - > Value . AvSingleHost . token_info . MachineId ,
sizeof ( SingleHost - > Value . AvSingleHost . token_info . MachineId ) ) ;
SingleHost - > Value . AvSingleHost . remaining = data_blob_null ;
}
{
struct AV_PAIR * ChannelBindings = NULL ;
ChannelBindings = eol ;
eol + + ;
count + + ;
* eol = * ChannelBindings ;
/*
* gensec doesn ' t support channel bindings yet ,
* but we want to match Windows on the wire
*/
ChannelBindings - > AvId = MsvChannelBindings ;
memset ( ChannelBindings - > Value . ChannelBindings , 0 ,
sizeof ( ChannelBindings - > Value . ChannelBindings ) ) ;
}
service = gensec_get_target_service ( gensec_security ) ;
hostname = gensec_get_target_hostname ( gensec_security ) ;
if ( service ! = NULL & & hostname ! = NULL ) {
struct AV_PAIR * target = NULL ;
target = eol ;
eol + + ;
count + + ;
* eol = * target ;
target - > AvId = MsvAvTargetName ;
target - > Value . AvTargetName = talloc_asprintf ( pairs , " %s/%s " ,
service ,
hostname ) ;
if ( target - > Value . AvTargetName = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
}
ntlmssp_state - > client . av_pair_list . count = count ;
ntlmssp_state - > client . av_pair_list . pair = pairs ;
err = ndr_push_struct_blob ( & target_info ,
ntlmssp_state ,
& ntlmssp_state - > client . av_pair_list ,
( ndr_push_flags_fn_t ) ndr_push_AV_PAIR_LIST ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( err ) ) {
return NT_STATUS_NO_MEMORY ;
}
}
2012-01-30 15:42:39 +04:00
nt_status = cli_credentials_get_ntlm_response ( gensec_security - > credentials , mem_ctx ,
2015-11-20 11:29:11 +03:00
& flags , challenge_blob ,
server_timestamp , target_info ,
2012-01-30 15:42:39 +04:00
& lm_response , & nt_response ,
2005-10-14 07:57:35 +04:00
& lm_session_key , & session_key ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
return nt_status ;
}
2012-01-30 15:42:39 +04:00
2005-10-14 07:57:35 +04:00
if ( ! ( flags & CLI_CRED_LANMAN_AUTH ) ) {
2011-12-27 12:50:36 +04:00
/* LM Key is still possible, just silly, so we do not
* allow it . Fortunetly all LM crypto is off by
* default and we require command line options to end
* up here */
ntlmssp_state - > neg_flags & = ~ NTLMSSP_NEGOTIATE_LM_KEY ;
2005-10-14 07:57:35 +04:00
}
2005-04-25 09:03:50 +04:00
2005-10-14 07:57:35 +04:00
if ( ! ( flags & CLI_CRED_NTLM2 ) ) {
/* NTLM2 is incompatible... */
2009-12-30 19:57:54 +03:00
ntlmssp_state - > neg_flags & = ~ NTLMSSP_NEGOTIATE_NTLM2 ;
2005-04-25 09:03:50 +04:00
}
2012-01-30 15:42:39 +04:00
2009-12-30 19:57:54 +03:00
if ( ( ntlmssp_state - > neg_flags & NTLMSSP_NEGOTIATE_LM_KEY )
2015-12-01 16:58:19 +03:00
& & ntlmssp_state - > allow_lm_key & & lm_session_key . length = = 16 ) {
2005-10-14 07:57:35 +04:00
DATA_BLOB new_session_key = data_blob_talloc ( mem_ctx , NULL , 16 ) ;
2005-04-25 09:03:50 +04:00
if ( lm_response . length = = 24 ) {
2012-01-30 15:42:39 +04:00
SMBsesskeygen_lm_sess_key ( lm_session_key . data , lm_response . data ,
2005-04-25 09:03:50 +04:00
new_session_key . data ) ;
} else {
static const uint8_t zeros [ 24 ] ;
SMBsesskeygen_lm_sess_key ( lm_session_key . data , zeros ,
new_session_key . data ) ;
}
session_key = new_session_key ;
dump_data_pw ( " LM session key \n " , session_key . data , session_key . length ) ;
}
/* Key exchange encryptes a new client-generated session key with
the password - derived key */
2009-12-30 19:57:54 +03:00
if ( ntlmssp_state - > neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH ) {
2005-04-25 09:03:50 +04:00
/* Make up a new session key */
uint8_t client_session_key [ 16 ] ;
2018-11-09 14:29:55 +03:00
gnutls_cipher_hd_t cipher_hnd ;
gnutls_datum_t enc_session_key = {
. data = session_key . data ,
. size = session_key . length ,
} ;
2019-08-12 20:07:15 +03:00
generate_random_buffer ( client_session_key , sizeof ( client_session_key ) ) ;
2005-04-25 09:03:50 +04:00
/* Encrypt the new session key with the old one */
2009-12-30 19:57:54 +03:00
encrypted_session_key = data_blob_talloc ( ntlmssp_state ,
2005-04-25 09:03:50 +04:00
client_session_key , sizeof ( client_session_key ) ) ;
dump_data_pw ( " KEY_EXCH session key: \n " , encrypted_session_key . data , encrypted_session_key . length ) ;
2018-11-09 14:29:55 +03:00
rc = gnutls_cipher_init ( & cipher_hnd ,
GNUTLS_CIPHER_ARCFOUR_128 ,
& enc_session_key ,
NULL ) ;
if ( rc < 0 ) {
nt_status = gnutls_error_to_ntstatus ( rc , NT_STATUS_NTLM_BLOCKED ) ;
ZERO_ARRAY ( client_session_key ) ;
goto done ;
}
rc = gnutls_cipher_encrypt ( cipher_hnd ,
encrypted_session_key . data ,
encrypted_session_key . length ) ;
gnutls_cipher_deinit ( cipher_hnd ) ;
if ( rc < 0 ) {
nt_status = gnutls_error_to_ntstatus ( rc , NT_STATUS_NTLM_BLOCKED ) ;
ZERO_ARRAY ( client_session_key ) ;
goto done ;
}
2005-04-25 09:03:50 +04:00
dump_data_pw ( " KEY_EXCH session key (enc): \n " , encrypted_session_key . data , encrypted_session_key . length ) ;
/* Mark the new session key as the 'real' session key */
2005-10-14 07:57:35 +04:00
session_key = data_blob_talloc ( mem_ctx , client_session_key , sizeof ( client_session_key ) ) ;
2018-11-09 14:29:55 +03:00
ZERO_ARRAY ( client_session_key ) ;
2005-04-25 09:03:50 +04:00
}
/* this generates the actual auth packet */
2012-01-30 15:42:39 +04:00
nt_status = msrpc_gen ( mem_ctx ,
out , auth_gen_string ,
" NTLMSSP " ,
NTLMSSP_AUTH ,
2005-04-25 09:03:50 +04:00
lm_response . data , lm_response . length ,
nt_response . data , nt_response . length ,
2012-01-30 15:42:39 +04:00
domain ,
user ,
2015-08-25 06:26:42 +03:00
workstation ,
2005-04-25 09:03:50 +04:00
encrypted_session_key . data , encrypted_session_key . length ,
2015-11-20 12:52:29 +03:00
ntlmssp_state - > neg_flags ,
2015-11-19 18:26:49 +03:00
version_blob . data , version_blob . length ,
mic_blob . data , mic_blob . length ) ;
2011-03-29 00:26:27 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
2005-10-14 07:57:35 +04:00
talloc_free ( mem_ctx ) ;
2011-03-29 00:26:27 +04:00
return nt_status ;
2005-04-25 09:03:50 +04:00
}
2019-03-27 19:51:04 +03:00
if ( DEBUGLEVEL > = 10 ) {
struct AUTHENTICATE_MESSAGE * authenticate =
talloc ( ntlmssp_state , struct AUTHENTICATE_MESSAGE ) ;
if ( authenticate ! = NULL ) {
NTSTATUS status ;
authenticate - > NegotiateFlags = ntlmssp_state - > neg_flags ;
status = ntlmssp_pull_AUTHENTICATE_MESSAGE (
out , authenticate , authenticate ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
NDR_PRINT_DEBUG ( AUTHENTICATE_MESSAGE ,
authenticate ) ;
}
TALLOC_FREE ( authenticate ) ;
}
}
2015-11-19 18:26:49 +03:00
/*
* We always include the MIC , even without :
* av_flags - > Value . AvFlags | = NTLMSSP_AVFLAG_MIC_IN_AUTHENTICATE_MESSAGE ;
* ntlmssp_state - > new_spnego = true ;
*
* This matches a Windows client .
*/
2018-10-30 11:31:19 +03:00
rc = gnutls_hmac_init ( & hmac_hnd ,
GNUTLS_MAC_MD5 ,
session_key . data ,
MIN ( session_key . length , 64 ) ) ;
if ( rc < 0 ) {
2019-06-11 16:16:31 +03:00
nt_status = gnutls_error_to_ntstatus ( rc , NT_STATUS_NTLM_BLOCKED ) ;
2018-10-30 11:31:19 +03:00
goto done ;
}
rc = gnutls_hmac ( hmac_hnd ,
ntlmssp_state - > negotiate_blob . data ,
ntlmssp_state - > negotiate_blob . length ) ;
if ( rc < 0 ) {
gnutls_hmac_deinit ( hmac_hnd , NULL ) ;
2019-06-11 16:16:31 +03:00
nt_status = gnutls_error_to_ntstatus ( rc , NT_STATUS_NTLM_BLOCKED ) ;
2018-10-30 11:31:19 +03:00
goto done ;
}
rc = gnutls_hmac ( hmac_hnd , in . data , in . length ) ;
if ( rc < 0 ) {
gnutls_hmac_deinit ( hmac_hnd , NULL ) ;
2019-06-11 16:16:31 +03:00
nt_status = gnutls_error_to_ntstatus ( rc , NT_STATUS_NTLM_BLOCKED ) ;
2018-10-30 11:31:19 +03:00
goto done ;
}
rc = gnutls_hmac ( hmac_hnd , out - > data , out - > length ) ;
if ( rc < 0 ) {
gnutls_hmac_deinit ( hmac_hnd , NULL ) ;
2019-06-11 16:16:31 +03:00
nt_status = gnutls_error_to_ntstatus ( rc , NT_STATUS_NTLM_BLOCKED ) ;
2018-10-30 11:31:19 +03:00
goto done ;
}
gnutls_hmac_deinit ( hmac_hnd , mic_buffer ) ;
2015-11-19 18:26:49 +03:00
memcpy ( out - > data + NTLMSSP_MIC_OFFSET , mic_buffer , NTLMSSP_MIC_SIZE ) ;
2018-10-30 11:31:19 +03:00
ZERO_ARRAY ( mic_buffer ) ;
2015-11-19 18:26:49 +03:00
2018-10-30 11:31:19 +03:00
nt_status = NT_STATUS_OK ;
2015-11-27 17:35:40 +03:00
done :
2018-10-30 11:31:19 +03:00
ZERO_ARRAY_LEN ( ntlmssp_state - > negotiate_blob . data ,
ntlmssp_state - > negotiate_blob . length ) ;
2015-11-19 18:26:49 +03:00
data_blob_free ( & ntlmssp_state - > negotiate_blob ) ;
2009-12-30 19:57:54 +03:00
ntlmssp_state - > session_key = session_key ;
talloc_steal ( ntlmssp_state , session_key . data ) ;
2005-10-14 07:57:35 +04:00
2015-11-27 17:35:40 +03:00
DEBUG ( 3 , ( " NTLMSSP: Set final flags: \n " ) ) ;
debug_ntlmssp_flags ( ntlmssp_state - > neg_flags ) ;
2005-10-14 07:57:35 +04:00
talloc_steal ( out_mem_ctx , out - > data ) ;
2005-04-25 09:03:50 +04:00
2009-12-30 19:57:54 +03:00
ntlmssp_state - > expected_state = NTLMSSP_DONE ;
2005-04-25 09:03:50 +04:00
2013-12-16 14:27:27 +04:00
if ( gensec_ntlmssp_have_feature ( gensec_security , GENSEC_FEATURE_SIGN ) ) {
2009-12-30 19:57:54 +03:00
nt_status = ntlmssp_sign_init ( ntlmssp_state ) ;
2005-08-23 09:29:37 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
2012-01-30 15:42:39 +04:00
DEBUG ( 1 , ( " Could not setup NTLMSSP signing/sealing system (error was: %s) \n " ,
2005-08-23 09:29:37 +04:00
nt_errstr ( nt_status ) ) ) ;
2005-10-14 07:57:35 +04:00
talloc_free ( mem_ctx ) ;
2005-08-23 09:29:37 +04:00
return nt_status ;
}
2005-04-25 09:03:50 +04:00
}
2005-10-14 07:57:35 +04:00
talloc_free ( mem_ctx ) ;
2018-10-30 11:31:19 +03:00
return nt_status ;
2005-04-25 09:03:50 +04:00
}
2007-12-03 19:41:50 +03:00
NTSTATUS gensec_ntlmssp_client_start ( struct gensec_security * gensec_security )
2005-04-25 09:03:50 +04:00
{
2009-12-30 10:23:13 +03:00
struct gensec_ntlmssp_context * gensec_ntlmssp ;
2009-12-30 19:57:54 +03:00
struct ntlmssp_state * ntlmssp_state ;
2005-04-25 14:33:00 +04:00
NTSTATUS nt_status ;
2005-04-25 09:03:50 +04:00
2005-04-25 14:33:00 +04:00
nt_status = gensec_ntlmssp_start ( gensec_security ) ;
NT_STATUS_NOT_OK_RETURN ( nt_status ) ;
2011-07-26 06:32:08 +04:00
gensec_ntlmssp =
talloc_get_type_abort ( gensec_security - > private_data ,
struct gensec_ntlmssp_context ) ;
ntlmssp_state = talloc_zero ( gensec_ntlmssp ,
struct ntlmssp_state ) ;
if ( ! ntlmssp_state ) {
return NT_STATUS_NO_MEMORY ;
}
gensec_ntlmssp - > ntlmssp_state = ntlmssp_state ;
2009-12-30 19:57:54 +03:00
ntlmssp_state = gensec_ntlmssp - > ntlmssp_state ;
2005-04-25 09:03:50 +04:00
2009-12-30 19:57:54 +03:00
ntlmssp_state - > role = NTLMSSP_CLIENT ;
2005-04-25 09:03:50 +04:00
2011-12-27 12:16:14 +04:00
ntlmssp_state - > client . netbios_domain = lpcfg_workgroup ( gensec_security - > settings - > lp_ctx ) ;
ntlmssp_state - > client . netbios_name = cli_credentials_get_workstation ( gensec_security - > credentials ) ;
2005-04-25 09:03:50 +04:00
2009-12-30 19:57:54 +03:00
ntlmssp_state - > unicode = gensec_setting_bool ( gensec_security - > settings , " ntlmssp_client " , " unicode " , true ) ;
2005-04-25 09:03:50 +04:00
2018-04-19 07:21:06 +03:00
ntlmssp_state - > use_nt_response = \
gensec_setting_bool ( gensec_security - > settings ,
" ntlmssp_client " ,
" send_nt_response " ,
true ) ;
2005-04-25 14:33:00 +04:00
2015-12-01 16:58:19 +03:00
ntlmssp_state - > allow_lm_response = lpcfg_client_lanman_auth ( gensec_security - > settings - > lp_ctx ) ;
ntlmssp_state - > allow_lm_key = ( ntlmssp_state - > allow_lm_response
2008-11-02 04:05:48 +03:00
& & ( gensec_setting_bool ( gensec_security - > settings , " ntlmssp_client " , " allow_lm_key " , false )
| | gensec_setting_bool ( gensec_security - > settings , " ntlmssp_client " , " lm_key " , false ) ) ) ;
2005-04-25 09:03:50 +04:00
2010-07-16 08:32:42 +04:00
ntlmssp_state - > use_ntlmv2 = lpcfg_client_ntlmv2_auth ( gensec_security - > settings - > lp_ctx ) ;
2005-04-25 09:03:50 +04:00
2016-04-25 16:58:27 +03:00
ntlmssp_state - > force_old_spnego = gensec_setting_bool ( gensec_security - > settings ,
" ntlmssp_client " , " force_old_spnego " , false ) ;
2009-12-30 19:57:54 +03:00
ntlmssp_state - > expected_state = NTLMSSP_INITIAL ;
2005-04-25 09:03:50 +04:00
2009-12-30 19:57:54 +03:00
ntlmssp_state - > neg_flags =
2005-04-25 09:03:50 +04:00
NTLMSSP_NEGOTIATE_NTLM |
2015-11-20 12:52:29 +03:00
NTLMSSP_NEGOTIATE_VERSION |
2005-04-25 09:03:50 +04:00
NTLMSSP_REQUEST_TARGET ;
2015-12-01 13:01:24 +03:00
if ( ntlmssp_state - > unicode ) {
ntlmssp_state - > neg_flags | = NTLMSSP_NEGOTIATE_UNICODE ;
} else {
ntlmssp_state - > neg_flags | = NTLMSSP_NEGOTIATE_OEM ;
}
2008-11-02 04:05:48 +03:00
if ( gensec_setting_bool ( gensec_security - > settings , " ntlmssp_client " , " 128bit " , true ) ) {
2009-12-30 19:57:54 +03:00
ntlmssp_state - > neg_flags | = NTLMSSP_NEGOTIATE_128 ;
2005-04-25 09:03:50 +04:00
}
2008-11-02 04:05:48 +03:00
if ( gensec_setting_bool ( gensec_security - > settings , " ntlmssp_client " , " 56bit " , false ) ) {
2009-12-30 19:57:54 +03:00
ntlmssp_state - > neg_flags | = NTLMSSP_NEGOTIATE_56 ;
2006-02-12 15:06:08 +03:00
}
2008-11-02 04:05:48 +03:00
if ( gensec_setting_bool ( gensec_security - > settings , " ntlmssp_client " , " lm_key " , false ) ) {
2009-12-30 19:57:54 +03:00
ntlmssp_state - > neg_flags | = NTLMSSP_NEGOTIATE_LM_KEY ;
2006-02-12 15:06:08 +03:00
}
2008-11-02 04:05:48 +03:00
if ( gensec_setting_bool ( gensec_security - > settings , " ntlmssp_client " , " keyexchange " , true ) ) {
2009-12-30 19:57:54 +03:00
ntlmssp_state - > neg_flags | = NTLMSSP_NEGOTIATE_KEY_EXCH ;
2005-04-25 09:03:50 +04:00
}
2008-11-02 04:05:48 +03:00
if ( gensec_setting_bool ( gensec_security - > settings , " ntlmssp_client " , " alwayssign " , true ) ) {
2009-12-30 19:57:54 +03:00
ntlmssp_state - > neg_flags | = NTLMSSP_NEGOTIATE_ALWAYS_SIGN ;
2006-11-20 23:58:00 +03:00
}
2008-11-02 04:05:48 +03:00
if ( gensec_setting_bool ( gensec_security - > settings , " ntlmssp_client " , " ntlm2 " , true ) ) {
2009-12-30 19:57:54 +03:00
ntlmssp_state - > neg_flags | = NTLMSSP_NEGOTIATE_NTLM2 ;
2005-04-25 09:03:50 +04:00
} else {
/* apparently we can't do ntlmv2 if we don't do ntlm2 */
2009-12-30 19:57:54 +03:00
ntlmssp_state - > use_ntlmv2 = false ;
2005-04-25 09:03:50 +04:00
}
2015-12-01 13:01:24 +03:00
if ( ntlmssp_state - > use_ntlmv2 ) {
2015-12-01 16:54:13 +03:00
ntlmssp_state - > required_flags | = NTLMSSP_NEGOTIATE_NTLM2 ;
2015-12-01 17:01:09 +03:00
ntlmssp_state - > allow_lm_response = false ;
ntlmssp_state - > allow_lm_key = false ;
2015-12-01 13:01:24 +03:00
}
2015-12-01 17:06:09 +03:00
if ( ntlmssp_state - > allow_lm_key ) {
ntlmssp_state - > neg_flags | = NTLMSSP_NEGOTIATE_LM_KEY ;
}
2005-04-25 09:03:50 +04:00
if ( gensec_security - > want_features & GENSEC_FEATURE_SESSION_KEY ) {
/*
* We need to set this to allow a later SetPassword
* via the SAMR pipe to succeed . Strange . . . . We could
* also add NTLMSSP_NEGOTIATE_SEAL here . JRA .
2012-01-30 15:42:39 +04:00
*
2005-04-25 09:03:50 +04:00
* Without this , Windows will not create the master key
2012-01-30 15:42:39 +04:00
* that it thinks is only used for NTLMSSP signing and
* sealing . ( It is actually pulled out and used directly )
2016-04-20 19:44:21 +03:00
*
* We don ' t require this here as some servers ( e . g . NetAPP )
* doesn ' t support this .
2005-04-25 09:03:50 +04:00
*/
2016-04-20 19:44:21 +03:00
ntlmssp_state - > neg_flags | = NTLMSSP_NEGOTIATE_SIGN ;
2005-04-25 09:03:50 +04:00
}
if ( gensec_security - > want_features & GENSEC_FEATURE_SIGN ) {
2015-12-01 16:54:13 +03:00
ntlmssp_state - > required_flags | = NTLMSSP_NEGOTIATE_SIGN ;
2015-12-09 16:48:14 +03:00
if ( gensec_security - > want_features & GENSEC_FEATURE_LDAP_STYLE ) {
/*
* We need to handle NTLMSSP_NEGOTIATE_SIGN as
* NTLMSSP_NEGOTIATE_SEAL if GENSEC_FEATURE_LDAP_STYLE
* is requested .
*/
ntlmssp_state - > force_wrap_seal = true ;
2018-05-09 14:30:13 +03:00
}
}
if ( ntlmssp_state - > force_wrap_seal ) {
bool ret ;
/*
* We want also work against old Samba servers
* which didn ' t had GENSEC_FEATURE_LDAP_STYLE
* we negotiate SEAL too . We may remove this
* in a few years . As all servers should have
* GENSEC_FEATURE_LDAP_STYLE by then .
*/
ret = gensec_setting_bool ( gensec_security - > settings ,
" ntlmssp_client " ,
" ldap_style_send_seal " ,
true ) ;
if ( ret ) {
2015-12-01 16:54:13 +03:00
ntlmssp_state - > required_flags | = NTLMSSP_NEGOTIATE_SEAL ;
2015-12-09 16:48:14 +03:00
}
2005-04-25 09:03:50 +04:00
}
if ( gensec_security - > want_features & GENSEC_FEATURE_SEAL ) {
2015-12-01 16:54:13 +03:00
ntlmssp_state - > required_flags | = NTLMSSP_NEGOTIATE_SIGN ;
ntlmssp_state - > required_flags | = NTLMSSP_NEGOTIATE_SEAL ;
2005-04-25 09:03:50 +04:00
}
2015-11-27 17:35:40 +03:00
if ( gensec_security - > want_features & GENSEC_FEATURE_NTLM_CCACHE ) {
ntlmssp_state - > use_ccache = true ;
}
2005-04-25 09:03:50 +04:00
2015-12-01 13:01:24 +03:00
ntlmssp_state - > neg_flags | = ntlmssp_state - > required_flags ;
ntlmssp_state - > conf_flags = ntlmssp_state - > neg_flags ;
2005-04-25 09:03:50 +04:00
return NT_STATUS_OK ;
}
2015-11-25 23:41:23 +03:00
NTSTATUS gensec_ntlmssp_resume_ccache_start ( struct gensec_security * gensec_security )
{
struct gensec_ntlmssp_context * gensec_ntlmssp = NULL ;
NTSTATUS status ;
status = gensec_ntlmssp_client_start ( gensec_security ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
gensec_ntlmssp = talloc_get_type_abort ( gensec_security - > private_data ,
struct gensec_ntlmssp_context ) ;
gensec_ntlmssp - > ntlmssp_state - > use_ccache = false ;
gensec_ntlmssp - > ntlmssp_state - > resume_ccache = true ;
gensec_ntlmssp - > ntlmssp_state - > expected_state = NTLMSSP_NEGOTIATE ;
return NT_STATUS_OK ;
}