2003-11-26 04:16:41 +03:00
/*
* Unix SMB / CIFS implementation .
* Version 3.0
* NTLMSSP Signing routines
* Copyright ( C ) Luke Kenneth Casson Leighton 1996 - 2001
2005-04-25 07:37:37 +04:00
* Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2003 - 2005
2003-11-26 04:16:41 +03:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software Foundation ,
* Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
# include "includes.h"
2004-11-02 05:57:18 +03:00
# include "auth/auth.h"
2005-04-25 09:03:50 +04:00
# include "auth/ntlmssp/ntlmssp.h"
2004-11-02 09:14:15 +03:00
# include "lib/crypto/crypto.h"
2003-11-26 04:16:41 +03:00
# define CLI_SIGN "session key to client-to-server signing key magic constant"
# define CLI_SEAL "session key to client-to-server sealing key magic constant"
# define SRV_SIGN "session key to server-to-client signing key magic constant"
# define SRV_SEAL "session key to server-to-client sealing key magic constant"
2004-05-25 18:06:28 +04:00
/**
* Some notes on then NTLM2 code :
*
2005-04-25 07:37:37 +04:00
* NTLM2 is a AEAD system . This means that the data encrypted is not
* all the data that is signed . In DCE - RPC case , the headers of the
* DCE - RPC packets are also signed . This prevents some of the
* fun - and - games one might have by changing them .
2004-05-25 18:06:28 +04:00
*
*/
2004-06-16 17:53:40 +04:00
2004-08-30 05:34:01 +04:00
static void calc_ntlmv2_key ( TALLOC_CTX * mem_ctx ,
DATA_BLOB * subkey ,
2004-06-16 17:53:40 +04:00
DATA_BLOB session_key ,
const char * constant )
2003-11-26 04:16:41 +03:00
{
struct MD5Context ctx3 ;
2004-08-30 05:34:01 +04:00
* subkey = data_blob_talloc ( mem_ctx , NULL , 16 ) ;
2003-11-26 04:16:41 +03:00
MD5Init ( & ctx3 ) ;
MD5Update ( & ctx3 , session_key . data , session_key . length ) ;
2005-08-20 10:14:14 +04:00
MD5Update ( & ctx3 , ( const uint8_t * ) constant , strlen ( constant ) + 1 ) ;
2004-08-30 05:34:01 +04:00
MD5Final ( subkey - > data , & ctx3 ) ;
2003-11-26 04:16:41 +03:00
}
enum ntlmssp_direction {
NTLMSSP_SEND ,
NTLMSSP_RECEIVE
} ;
2005-04-25 14:33:00 +04:00
static NTSTATUS ntlmssp_make_packet_signature ( struct gensec_ntlmssp_state * gensec_ntlmssp_state ,
2004-05-25 18:06:28 +04:00
TALLOC_CTX * sig_mem_ctx ,
2004-06-01 12:30:34 +04:00
const uint8_t * data , size_t length ,
2004-09-11 19:11:36 +04:00
const uint8_t * whole_pdu , size_t pdu_length ,
2003-11-26 04:16:41 +03:00
enum ntlmssp_direction direction ,
2004-09-12 10:38:00 +04:00
DATA_BLOB * sig , BOOL encrypt_sig )
2003-11-26 04:16:41 +03:00
{
2005-04-25 14:33:00 +04:00
if ( gensec_ntlmssp_state - > neg_flags & NTLMSSP_NEGOTIATE_NTLM2 ) {
2004-05-25 18:06:28 +04:00
2003-11-26 04:16:41 +03:00
HMACMD5Context ctx ;
2004-06-01 12:30:34 +04:00
uint8_t digest [ 16 ] ;
2004-08-30 05:34:01 +04:00
uint8_t seq_num [ 4 ] ;
2003-11-26 04:16:41 +03:00
2004-09-11 19:11:36 +04:00
* sig = data_blob_talloc ( sig_mem_ctx , NULL , NTLMSSP_SIG_SIZE ) ;
if ( ! sig - > data ) {
return NT_STATUS_NO_MEMORY ;
}
2004-05-25 18:06:28 +04:00
switch ( direction ) {
case NTLMSSP_SEND :
2005-05-11 23:22:22 +04:00
SIVAL ( seq_num , 0 , gensec_ntlmssp_state - > crypt . ntlm2 . send_seq_num ) ;
gensec_ntlmssp_state - > crypt . ntlm2 . send_seq_num + + ;
hmac_md5_init_limK_to_64 ( gensec_ntlmssp_state - > crypt . ntlm2 . send_sign_key . data ,
gensec_ntlmssp_state - > crypt . ntlm2 . send_sign_key . length , & ctx ) ;
2004-05-25 18:06:28 +04:00
break ;
case NTLMSSP_RECEIVE :
2005-05-11 23:22:22 +04:00
SIVAL ( seq_num , 0 , gensec_ntlmssp_state - > crypt . ntlm2 . recv_seq_num ) ;
gensec_ntlmssp_state - > crypt . ntlm2 . recv_seq_num + + ;
hmac_md5_init_limK_to_64 ( gensec_ntlmssp_state - > crypt . ntlm2 . recv_sign_key . data ,
gensec_ntlmssp_state - > crypt . ntlm2 . recv_sign_key . length , & ctx ) ;
2004-05-25 18:06:28 +04:00
break ;
}
2004-08-30 05:34:01 +04:00
hmac_md5_update ( seq_num , sizeof ( seq_num ) , & ctx ) ;
2004-09-11 19:11:36 +04:00
hmac_md5_update ( whole_pdu , pdu_length , & ctx ) ;
2003-11-26 04:16:41 +03:00
hmac_md5_final ( digest , & ctx ) ;
2005-04-25 14:33:00 +04:00
if ( encrypt_sig & & gensec_ntlmssp_state - > neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH ) {
2004-05-02 12:45:00 +04:00
switch ( direction ) {
case NTLMSSP_SEND :
2005-05-11 23:22:22 +04:00
arcfour_crypt_sbox ( gensec_ntlmssp_state - > crypt . ntlm2 . send_seal_arcfour_state , digest , 8 ) ;
2004-05-02 12:45:00 +04:00
break ;
case NTLMSSP_RECEIVE :
2005-05-11 23:22:22 +04:00
arcfour_crypt_sbox ( gensec_ntlmssp_state - > crypt . ntlm2 . recv_seal_arcfour_state , digest , 8 ) ;
2004-05-02 12:45:00 +04:00
break ;
}
2003-11-26 04:16:41 +03:00
}
2004-09-11 19:11:36 +04:00
2004-05-25 18:06:28 +04:00
SIVAL ( sig - > data , 0 , NTLMSSP_SIGN_VERSION ) ;
memcpy ( sig - > data + 4 , digest , 8 ) ;
memcpy ( sig - > data + 12 , seq_num , 4 ) ;
2003-11-26 04:16:41 +03:00
} else {
2004-05-25 20:24:13 +04:00
uint32_t crc ;
2004-11-25 21:02:35 +03:00
crc = crc32_calc_buffer ( data , length ) ;
2005-05-11 23:22:22 +04:00
if ( ! msrpc_gen ( sig_mem_ctx , sig , " dddd " , NTLMSSP_SIGN_VERSION , 0 , crc , gensec_ntlmssp_state - > crypt . ntlm . seq_num ) ) {
2004-06-28 10:46:27 +04:00
return NT_STATUS_NO_MEMORY ;
2003-11-26 04:16:41 +03:00
}
2005-05-11 23:22:22 +04:00
gensec_ntlmssp_state - > crypt . ntlm . seq_num + + ;
2004-09-11 19:11:36 +04:00
2005-05-11 23:22:22 +04:00
arcfour_crypt_sbox ( gensec_ntlmssp_state - > crypt . ntlm . arcfour_state , sig - > data + 4 , sig - > length - 4 ) ;
2003-11-26 04:16:41 +03:00
}
2004-06-16 17:53:40 +04:00
dump_data_pw ( " calculated ntlmssp signature \n " , sig - > data , sig - > length ) ;
2003-11-26 04:16:41 +03:00
return NT_STATUS_OK ;
}
2005-04-25 07:37:37 +04:00
NTSTATUS gensec_ntlmssp_sign_packet ( struct gensec_security * gensec_security ,
2005-04-25 14:33:00 +04:00
TALLOC_CTX * sig_mem_ctx ,
const uint8_t * data , size_t length ,
const uint8_t * whole_pdu , size_t pdu_length ,
DATA_BLOB * sig )
2003-11-26 04:16:41 +03:00
{
2005-04-25 07:37:37 +04:00
struct gensec_ntlmssp_state * gensec_ntlmssp_state = gensec_security - > private_data ;
2005-04-25 14:33:00 +04:00
return ntlmssp_make_packet_signature ( gensec_ntlmssp_state , sig_mem_ctx ,
2004-09-11 19:11:36 +04:00
data , length ,
whole_pdu , pdu_length ,
NTLMSSP_SEND , sig , True ) ;
2003-11-26 04:16:41 +03:00
}
/**
* Check the signature of an incoming packet
*
*/
2005-04-25 07:37:37 +04:00
NTSTATUS gensec_ntlmssp_check_packet ( struct gensec_security * gensec_security ,
TALLOC_CTX * sig_mem_ctx ,
const uint8_t * data , size_t length ,
const uint8_t * whole_pdu , size_t pdu_length ,
const DATA_BLOB * sig )
2003-11-26 04:16:41 +03:00
{
2005-04-25 07:37:37 +04:00
struct gensec_ntlmssp_state * gensec_ntlmssp_state = gensec_security - > private_data ;
2003-11-26 04:16:41 +03:00
DATA_BLOB local_sig ;
NTSTATUS nt_status ;
2005-04-25 14:33:00 +04:00
if ( ! gensec_ntlmssp_state - > session_key . length ) {
2004-05-02 12:45:00 +04:00
DEBUG ( 3 , ( " NO session key, cannot check packet signature \n " ) ) ;
return NT_STATUS_NO_USER_SESSION_KEY ;
}
2003-11-26 04:16:41 +03:00
if ( sig - > length < 8 ) {
DEBUG ( 0 , ( " NTLMSSP packet check failed due to short signature (%lu bytes)! \n " ,
( unsigned long ) sig - > length ) ) ;
}
2005-04-25 14:33:00 +04:00
nt_status = ntlmssp_make_packet_signature ( gensec_ntlmssp_state , sig_mem_ctx ,
2004-09-11 19:11:36 +04:00
data , length ,
whole_pdu , pdu_length ,
NTLMSSP_RECEIVE , & local_sig , True ) ;
2003-11-26 04:16:41 +03:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
DEBUG ( 0 , ( " NTLMSSP packet check failed with %s \n " , nt_errstr ( nt_status ) ) ) ;
return nt_status ;
}
2003-11-26 05:08:41 +03:00
2005-04-25 14:33:00 +04:00
if ( gensec_ntlmssp_state - > neg_flags & NTLMSSP_NEGOTIATE_NTLM2 ) {
2004-05-25 18:06:28 +04:00
if ( local_sig . length ! = sig - > length | |
memcmp ( local_sig . data ,
sig - > data , sig - > length ) ! = 0 ) {
DEBUG ( 5 , ( " BAD SIG NTLM2: wanted signature of \n " ) ) ;
dump_data ( 5 , local_sig . data , local_sig . length ) ;
DEBUG ( 5 , ( " BAD SIG: got signature of \n " ) ) ;
dump_data ( 5 , sig - > data , sig - > length ) ;
DEBUG ( 0 , ( " NTLMSSP NTLM2 packet check failed due to invalid signature! \n " ) ) ;
2004-06-18 15:59:52 +04:00
return NT_STATUS_ACCESS_DENIED ;
2004-05-25 18:06:28 +04:00
}
} else {
if ( local_sig . length ! = sig - > length | |
memcmp ( local_sig . data + 8 ,
sig - > data + 8 , sig - > length - 8 ) ! = 0 ) {
DEBUG ( 5 , ( " BAD SIG NTLM1: wanted signature of \n " ) ) ;
2004-11-25 21:02:35 +03:00
dump_data ( 5 , local_sig . data , local_sig . length ) ;
2004-05-25 18:06:28 +04:00
DEBUG ( 5 , ( " BAD SIG: got signature of \n " ) ) ;
2004-11-25 21:02:35 +03:00
dump_data ( 5 , sig - > data , sig - > length ) ;
2004-05-25 18:06:28 +04:00
DEBUG ( 0 , ( " NTLMSSP NTLM1 packet check failed due to invalid signature! \n " ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
2003-11-26 04:16:41 +03:00
}
2004-06-16 17:53:40 +04:00
dump_data_pw ( " checked ntlmssp signature \n " , sig - > data , sig - > length ) ;
2003-11-26 04:16:41 +03:00
return NT_STATUS_OK ;
}
/**
* Seal data with the NTLMSSP algorithm
*
*/
2005-04-25 07:37:37 +04:00
NTSTATUS gensec_ntlmssp_seal_packet ( struct gensec_security * gensec_security ,
TALLOC_CTX * sig_mem_ctx ,
uint8_t * data , size_t length ,
const uint8_t * whole_pdu , size_t pdu_length ,
DATA_BLOB * sig )
{
struct gensec_ntlmssp_state * gensec_ntlmssp_state = gensec_security - > private_data ;
2004-09-11 19:11:36 +04:00
NTSTATUS nt_status ;
2005-04-25 14:33:00 +04:00
if ( ! gensec_ntlmssp_state - > session_key . length ) {
2004-05-02 12:45:00 +04:00
DEBUG ( 3 , ( " NO session key, cannot seal packet \n " ) ) ;
return NT_STATUS_NO_USER_SESSION_KEY ;
}
2003-11-26 04:16:41 +03:00
DEBUG ( 10 , ( " ntlmssp_seal_data: seal \n " ) ) ;
dump_data_pw ( " ntlmssp clear data \n " , data , length ) ;
2005-04-25 14:33:00 +04:00
if ( gensec_ntlmssp_state - > neg_flags & NTLMSSP_NEGOTIATE_NTLM2 ) {
2004-05-25 18:06:28 +04:00
/* The order of these two operations matters - we must first seal the packet,
then seal the sequence number - this is becouse the send_seal_hash is not
constant , but is is rather updated with each iteration */
2005-04-25 14:33:00 +04:00
nt_status = ntlmssp_make_packet_signature ( gensec_ntlmssp_state , sig_mem_ctx ,
2004-09-11 19:11:36 +04:00
data , length ,
whole_pdu , pdu_length ,
2004-09-12 10:38:00 +04:00
NTLMSSP_SEND , sig , False ) ;
2005-05-11 23:22:22 +04:00
arcfour_crypt_sbox ( gensec_ntlmssp_state - > crypt . ntlm2 . send_seal_arcfour_state , data , length ) ;
2005-04-25 14:33:00 +04:00
if ( gensec_ntlmssp_state - > neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH ) {
2005-05-11 23:22:22 +04:00
arcfour_crypt_sbox ( gensec_ntlmssp_state - > crypt . ntlm2 . send_seal_arcfour_state , sig - > data + 4 , 8 ) ;
2004-09-12 10:38:00 +04:00
}
2003-11-26 04:16:41 +03:00
} else {
2004-05-25 20:24:13 +04:00
uint32_t crc ;
2004-11-25 21:02:35 +03:00
crc = crc32_calc_buffer ( data , length ) ;
2005-05-11 23:22:22 +04:00
if ( ! msrpc_gen ( sig_mem_ctx , sig , " dddd " , NTLMSSP_SIGN_VERSION , 0 , crc , gensec_ntlmssp_state - > crypt . ntlm . seq_num ) ) {
2004-06-28 10:46:27 +04:00
return NT_STATUS_NO_MEMORY ;
2003-11-26 04:16:41 +03:00
}
2004-09-12 10:38:00 +04:00
/* The order of these two operations matters - we must
first seal the packet , then seal the sequence
number - this is becouse the ntlmssp_hash is not
constant , but is is rather updated with each
iteration */
2003-11-26 04:16:41 +03:00
2005-05-11 23:22:22 +04:00
arcfour_crypt_sbox ( gensec_ntlmssp_state - > crypt . ntlm . arcfour_state , data , length ) ;
arcfour_crypt_sbox ( gensec_ntlmssp_state - > crypt . ntlm . arcfour_state , sig - > data + 4 , sig - > length - 4 ) ;
2004-09-11 19:11:36 +04:00
/* increment counter on send */
2005-05-11 23:22:22 +04:00
gensec_ntlmssp_state - > crypt . ntlm . seq_num + + ;
2004-09-11 19:11:36 +04:00
nt_status = NT_STATUS_OK ;
2003-11-26 04:16:41 +03:00
}
2004-06-16 17:53:40 +04:00
dump_data_pw ( " ntlmssp signature \n " , sig - > data , sig - > length ) ;
2003-11-26 04:16:41 +03:00
dump_data_pw ( " ntlmssp sealed data \n " , data , length ) ;
2004-09-11 19:11:36 +04:00
return nt_status ;
2003-11-26 04:16:41 +03:00
}
/**
* Unseal data with the NTLMSSP algorithm
*
*/
2005-04-25 07:37:37 +04:00
/*
wrappers for the ntlmssp_ * ( ) functions
*/
NTSTATUS gensec_ntlmssp_unseal_packet ( struct gensec_security * gensec_security ,
TALLOC_CTX * sig_mem_ctx ,
uint8_t * data , size_t length ,
const uint8_t * whole_pdu , size_t pdu_length ,
const DATA_BLOB * sig )
2003-11-26 04:16:41 +03:00
{
2005-04-25 07:37:37 +04:00
struct gensec_ntlmssp_state * gensec_ntlmssp_state = gensec_security - > private_data ;
2005-04-25 14:33:00 +04:00
if ( ! gensec_ntlmssp_state - > session_key . length ) {
2004-05-02 12:45:00 +04:00
DEBUG ( 3 , ( " NO session key, cannot unseal packet \n " ) ) ;
return NT_STATUS_NO_USER_SESSION_KEY ;
}
2003-11-26 04:16:41 +03:00
dump_data_pw ( " ntlmssp sealed data \n " , data , length ) ;
2005-04-25 14:33:00 +04:00
if ( gensec_ntlmssp_state - > neg_flags & NTLMSSP_NEGOTIATE_NTLM2 ) {
2005-05-11 23:22:22 +04:00
arcfour_crypt_sbox ( gensec_ntlmssp_state - > crypt . ntlm2 . recv_seal_arcfour_state , data , length ) ;
2003-11-26 04:16:41 +03:00
} else {
2005-05-11 23:22:22 +04:00
arcfour_crypt_sbox ( gensec_ntlmssp_state - > crypt . ntlm . arcfour_state , data , length ) ;
2003-11-26 04:16:41 +03:00
}
2005-08-20 10:14:14 +04:00
dump_data_pw ( " ntlmssp clear data \n " , data , length ) ;
return gensec_ntlmssp_check_packet ( gensec_security , sig_mem_ctx , data , length , whole_pdu , pdu_length , sig ) ;
2003-11-26 04:16:41 +03:00
}
/**
Initialise the state for NTLMSSP signing .
*/
2005-04-25 14:33:00 +04:00
NTSTATUS ntlmssp_sign_init ( struct gensec_ntlmssp_state * gensec_ntlmssp_state )
2003-11-26 04:16:41 +03:00
{
2004-05-29 12:11:46 +04:00
uint8_t p24 [ 24 ] ;
2003-11-26 04:16:41 +03:00
ZERO_STRUCT ( p24 ) ;
DEBUG ( 3 , ( " NTLMSSP Sign/Seal - Initialising with flags: \n " ) ) ;
2005-04-25 14:33:00 +04:00
debug_ntlmssp_flags ( gensec_ntlmssp_state - > neg_flags ) ;
2003-11-26 04:16:41 +03:00
2005-04-25 14:33:00 +04:00
if ( ! gensec_ntlmssp_state - > session_key . length ) {
2004-05-02 12:45:00 +04:00
DEBUG ( 3 , ( " NO session key, cannot intialise signing \n " ) ) ;
return NT_STATUS_NO_USER_SESSION_KEY ;
}
2005-04-25 14:33:00 +04:00
if ( gensec_ntlmssp_state - > neg_flags & NTLMSSP_NEGOTIATE_NTLM2 )
2003-11-26 04:16:41 +03:00
{
2005-04-25 14:33:00 +04:00
DATA_BLOB weak_session_key = gensec_ntlmssp_state - > session_key ;
2003-11-26 04:16:41 +03:00
const char * send_sign_const ;
const char * send_seal_const ;
const char * recv_sign_const ;
const char * recv_seal_const ;
2005-04-25 12:26:53 +04:00
DATA_BLOB send_seal_key ;
DATA_BLOB recv_seal_key ;
2005-04-25 14:33:00 +04:00
switch ( gensec_ntlmssp_state - > role ) {
2003-11-26 04:16:41 +03:00
case NTLMSSP_CLIENT :
send_sign_const = CLI_SIGN ;
send_seal_const = CLI_SEAL ;
recv_sign_const = SRV_SIGN ;
recv_seal_const = SRV_SEAL ;
break ;
case NTLMSSP_SERVER :
send_sign_const = SRV_SIGN ;
send_seal_const = SRV_SEAL ;
recv_sign_const = CLI_SIGN ;
recv_seal_const = CLI_SEAL ;
break ;
2004-12-02 07:51:56 +03:00
default :
return NT_STATUS_INTERNAL_ERROR ;
2003-11-26 04:16:41 +03:00
}
2004-06-16 17:53:40 +04:00
2005-05-11 23:22:22 +04:00
gensec_ntlmssp_state - > crypt . ntlm2 . send_seal_arcfour_state = talloc ( gensec_ntlmssp_state , struct arcfour_state ) ;
NT_STATUS_HAVE_NO_MEMORY ( gensec_ntlmssp_state - > crypt . ntlm2 . send_seal_arcfour_state ) ;
gensec_ntlmssp_state - > crypt . ntlm2 . recv_seal_arcfour_state = talloc ( gensec_ntlmssp_state , struct arcfour_state ) ;
NT_STATUS_HAVE_NO_MEMORY ( gensec_ntlmssp_state - > crypt . ntlm2 . send_seal_arcfour_state ) ;
2005-04-25 12:26:53 +04:00
2004-06-16 17:53:40 +04:00
/**
2005-08-20 10:14:14 +04:00
Weaken NTLMSSP keys to cope with down - level
clients , servers and export restrictions .
2004-06-16 17:53:40 +04:00
2005-08-20 10:14:14 +04:00
We probably should have some parameters to control
this , once we get NTLM2 working .
2004-06-16 17:53:40 +04:00
*/
2005-08-20 10:14:14 +04:00
/* Key weakening was not performed on the master key
* for NTLM2 ( in ntlmssp_weaken_keys ( ) ) , but must be
* done on the encryption subkeys only . That is why
* we don ' t have this code for the ntlmv1 case .
*/
2004-06-16 17:53:40 +04:00
2005-04-25 14:33:00 +04:00
if ( gensec_ntlmssp_state - > neg_flags & NTLMSSP_NEGOTIATE_128 ) {
2004-06-16 17:53:40 +04:00
2005-04-25 14:33:00 +04:00
} else if ( gensec_ntlmssp_state - > neg_flags & NTLMSSP_NEGOTIATE_56 ) {
2004-06-16 17:53:40 +04:00
weak_session_key . length = 6 ;
} else { /* forty bits */
weak_session_key . length = 5 ;
}
dump_data_pw ( " NTLMSSP weakend master key: \n " ,
weak_session_key . data ,
weak_session_key . length ) ;
2003-11-26 04:16:41 +03:00
2004-05-25 18:06:28 +04:00
/* SEND */
2005-04-25 14:33:00 +04:00
calc_ntlmv2_key ( gensec_ntlmssp_state ,
2005-05-11 23:22:22 +04:00
& gensec_ntlmssp_state - > crypt . ntlm2 . send_sign_key ,
2005-04-25 14:33:00 +04:00
gensec_ntlmssp_state - > session_key , send_sign_const ) ;
2004-05-25 18:06:28 +04:00
dump_data_pw ( " NTLMSSP send sign key: \n " ,
2005-05-11 23:22:22 +04:00
gensec_ntlmssp_state - > crypt . ntlm2 . send_sign_key . data ,
gensec_ntlmssp_state - > crypt . ntlm2 . send_sign_key . length ) ;
2004-05-25 18:06:28 +04:00
2005-04-25 14:33:00 +04:00
calc_ntlmv2_key ( gensec_ntlmssp_state ,
2005-04-25 12:26:53 +04:00
& send_seal_key ,
2004-06-16 17:53:40 +04:00
weak_session_key , send_seal_const ) ;
2004-05-25 18:06:28 +04:00
dump_data_pw ( " NTLMSSP send seal key: \n " ,
2005-04-25 12:26:53 +04:00
send_seal_key . data ,
send_seal_key . length ) ;
2004-06-16 17:53:40 +04:00
2005-05-11 23:22:22 +04:00
arcfour_init ( gensec_ntlmssp_state - > crypt . ntlm2 . send_seal_arcfour_state ,
2005-04-25 12:26:53 +04:00
& send_seal_key ) ;
2004-06-16 17:53:40 +04:00
2003-11-26 04:16:41 +03:00
dump_data_pw ( " NTLMSSP send sesl hash: \n " ,
2005-05-11 23:22:22 +04:00
gensec_ntlmssp_state - > crypt . ntlm2 . send_seal_arcfour_state - > sbox ,
sizeof ( gensec_ntlmssp_state - > crypt . ntlm2 . send_seal_arcfour_state - > sbox ) ) ;
2003-11-26 04:16:41 +03:00
2004-05-25 18:06:28 +04:00
/* RECV */
2005-04-25 14:33:00 +04:00
calc_ntlmv2_key ( gensec_ntlmssp_state ,
2005-05-11 23:22:22 +04:00
& gensec_ntlmssp_state - > crypt . ntlm2 . recv_sign_key ,
2005-04-25 14:33:00 +04:00
gensec_ntlmssp_state - > session_key , recv_sign_const ) ;
2004-05-25 18:06:28 +04:00
dump_data_pw ( " NTLMSSP recv sign key: \n " ,
2005-05-11 23:22:22 +04:00
gensec_ntlmssp_state - > crypt . ntlm2 . recv_sign_key . data ,
gensec_ntlmssp_state - > crypt . ntlm2 . recv_sign_key . length ) ;
2003-11-26 04:16:41 +03:00
2005-04-25 14:33:00 +04:00
calc_ntlmv2_key ( gensec_ntlmssp_state ,
2005-04-25 12:26:53 +04:00
& recv_seal_key ,
2004-06-16 17:53:40 +04:00
weak_session_key , recv_seal_const ) ;
2004-05-25 18:06:28 +04:00
dump_data_pw ( " NTLMSSP recv seal key: \n " ,
2005-04-25 12:26:53 +04:00
recv_seal_key . data ,
recv_seal_key . length ) ;
2005-05-11 23:22:22 +04:00
arcfour_init ( gensec_ntlmssp_state - > crypt . ntlm2 . recv_seal_arcfour_state ,
2005-04-25 12:26:53 +04:00
& recv_seal_key ) ;
2003-11-26 04:16:41 +03:00
2004-06-16 17:53:40 +04:00
dump_data_pw ( " NTLMSSP receive seal hash: \n " ,
2005-05-11 23:22:22 +04:00
gensec_ntlmssp_state - > crypt . ntlm2 . recv_seal_arcfour_state - > sbox ,
sizeof ( gensec_ntlmssp_state - > crypt . ntlm2 . recv_seal_arcfour_state - > sbox ) ) ;
2005-04-25 13:23:56 +04:00
2005-05-11 23:22:22 +04:00
gensec_ntlmssp_state - > crypt . ntlm2 . send_seq_num = 0 ;
gensec_ntlmssp_state - > crypt . ntlm2 . recv_seq_num = 0 ;
2005-04-25 13:23:56 +04:00
2003-11-26 04:16:41 +03:00
} else {
2004-06-16 17:53:40 +04:00
DEBUG ( 5 , ( " NTLMSSP Sign/Seal - using NTLM1 \n " ) ) ;
2003-11-26 04:16:41 +03:00
2005-05-11 23:22:22 +04:00
gensec_ntlmssp_state - > crypt . ntlm . arcfour_state = talloc ( gensec_ntlmssp_state , struct arcfour_state ) ;
NT_STATUS_HAVE_NO_MEMORY ( gensec_ntlmssp_state - > crypt . ntlm . arcfour_state ) ;
2005-04-25 12:26:53 +04:00
2005-05-11 23:22:22 +04:00
arcfour_init ( gensec_ntlmssp_state - > crypt . ntlm . arcfour_state ,
2005-04-25 14:33:00 +04:00
& gensec_ntlmssp_state - > session_key ) ;
2005-05-11 23:22:22 +04:00
dump_data_pw ( " NTLMSSP hash: \n " , gensec_ntlmssp_state - > crypt . ntlm . arcfour_state - > sbox ,
sizeof ( gensec_ntlmssp_state - > crypt . ntlm . arcfour_state - > sbox ) ) ;
2003-11-26 04:16:41 +03:00
2005-05-11 23:22:22 +04:00
gensec_ntlmssp_state - > crypt . ntlm . seq_num = 0 ;
2005-04-25 13:23:56 +04:00
}
2003-11-26 04:16:41 +03:00
return NT_STATUS_OK ;
}
2005-04-25 07:37:37 +04:00
size_t gensec_ntlmssp_sig_size ( struct gensec_security * gensec_security )
{
return NTLMSSP_SIG_SIZE ;
}
NTSTATUS gensec_ntlmssp_wrap ( struct gensec_security * gensec_security ,
TALLOC_CTX * sig_mem_ctx ,
const DATA_BLOB * in ,
DATA_BLOB * out )
{
DATA_BLOB sig ;
NTSTATUS nt_status ;
2005-08-20 10:14:14 +04:00
if ( gensec_have_feature ( gensec_security , GENSEC_FEATURE_SEAL ) ) {
2005-04-25 07:37:37 +04:00
* out = data_blob_talloc ( sig_mem_ctx , NULL , in - > length + NTLMSSP_SIG_SIZE ) ;
memcpy ( out - > data + NTLMSSP_SIG_SIZE , in - > data , in - > length ) ;
2005-08-20 10:14:14 +04:00
2005-04-25 07:37:37 +04:00
nt_status = gensec_ntlmssp_seal_packet ( gensec_security , sig_mem_ctx ,
out - > data + NTLMSSP_SIG_SIZE ,
out - > length - NTLMSSP_SIG_SIZE ,
out - > data + NTLMSSP_SIG_SIZE ,
out - > length - NTLMSSP_SIG_SIZE ,
& sig ) ;
2005-08-20 10:14:14 +04:00
2005-04-25 07:37:37 +04:00
if ( NT_STATUS_IS_OK ( nt_status ) ) {
memcpy ( out - > data , sig . data , NTLMSSP_SIG_SIZE ) ;
}
return nt_status ;
2005-08-20 10:14:14 +04:00
} else if ( gensec_have_feature ( gensec_security , GENSEC_FEATURE_SIGN ) ) {
2005-04-25 07:37:37 +04:00
* out = data_blob_talloc ( sig_mem_ctx , NULL , in - > length + NTLMSSP_SIG_SIZE ) ;
memcpy ( out - > data + NTLMSSP_SIG_SIZE , in - > data , in - > length ) ;
nt_status = gensec_ntlmssp_sign_packet ( gensec_security , sig_mem_ctx ,
2005-08-20 10:14:14 +04:00
out - > data + NTLMSSP_SIG_SIZE ,
out - > length - NTLMSSP_SIG_SIZE ,
out - > data + NTLMSSP_SIG_SIZE ,
out - > length - NTLMSSP_SIG_SIZE ,
& sig ) ;
2005-04-25 07:37:37 +04:00
if ( NT_STATUS_IS_OK ( nt_status ) ) {
memcpy ( out - > data , sig . data , NTLMSSP_SIG_SIZE ) ;
}
return nt_status ;
} else {
* out = * in ;
return NT_STATUS_OK ;
}
}
NTSTATUS gensec_ntlmssp_unwrap ( struct gensec_security * gensec_security ,
TALLOC_CTX * sig_mem_ctx ,
const DATA_BLOB * in ,
DATA_BLOB * out )
{
DATA_BLOB sig ;
2005-08-20 10:14:14 +04:00
if ( gensec_have_feature ( gensec_security , GENSEC_FEATURE_SEAL ) ) {
2005-04-25 07:37:37 +04:00
if ( in - > length < NTLMSSP_SIG_SIZE ) {
return NT_STATUS_INVALID_PARAMETER ;
}
sig . data = in - > data ;
sig . length = NTLMSSP_SIG_SIZE ;
* out = data_blob_talloc ( sig_mem_ctx , in - > data + NTLMSSP_SIG_SIZE , in - > length - NTLMSSP_SIG_SIZE ) ;
return gensec_ntlmssp_unseal_packet ( gensec_security , sig_mem_ctx ,
out - > data , out - > length ,
out - > data , out - > length ,
& sig ) ;
2005-08-20 10:14:14 +04:00
} else if ( gensec_have_feature ( gensec_security , GENSEC_FEATURE_SIGN ) ) {
2005-04-25 07:37:37 +04:00
if ( in - > length < NTLMSSP_SIG_SIZE ) {
return NT_STATUS_INVALID_PARAMETER ;
}
sig . data = in - > data ;
sig . length = NTLMSSP_SIG_SIZE ;
* out = data_blob_talloc ( sig_mem_ctx , in - > data + NTLMSSP_SIG_SIZE , in - > length - NTLMSSP_SIG_SIZE ) ;
return gensec_ntlmssp_check_packet ( gensec_security , sig_mem_ctx ,
2005-08-20 10:14:14 +04:00
out - > data , out - > length ,
out - > data , out - > length ,
& sig ) ;
2005-04-25 07:37:37 +04:00
} else {
* out = * in ;
return NT_STATUS_OK ;
}
}