2003-08-13 05:53:07 +04:00
/*
Unix SMB / CIFS implementation .
negprot reply code
Copyright ( C ) Andrew Tridgell 1992 - 1998
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 . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
2004-11-02 05:57:18 +03:00
# include "auth/auth.h"
2004-11-02 10:18:24 +03:00
# include "smb_server/smb_server.h"
2005-01-30 03:54:57 +03:00
# include "smbd/service_stream.h"
2004-11-02 10:18:24 +03:00
2003-08-13 05:53:07 +04:00
/* initialise the auth_context for this server and return the cryptkey */
2005-01-09 15:55:25 +03:00
static NTSTATUS get_challenge ( struct smbsrv_connection * smb_conn , uint8_t buff [ 8 ] )
2003-08-13 05:53:07 +04:00
{
NTSTATUS nt_status ;
2005-01-09 15:55:25 +03:00
const uint8_t * challenge ;
2003-08-13 05:53:07 +04:00
/* muliple negprots are not premitted */
2004-06-29 11:40:14 +04:00
if ( smb_conn - > negotiate . auth_context ) {
2003-08-13 05:53:07 +04:00
DEBUG ( 3 , ( " get challenge: is this a secondary negprot? auth_context is non-NULL! \n " ) ) ;
2005-01-09 15:55:25 +03:00
return NT_STATUS_FOOBAR ;
2003-08-13 05:53:07 +04:00
}
DEBUG ( 10 , ( " get challenge: creating negprot_global_auth_context \n " ) ) ;
2005-06-16 15:36:09 +04:00
nt_status = auth_context_create ( smb_conn , lp_auth_methods ( ) ,
& smb_conn - > negotiate . auth_context ,
smb_conn - > connection - > event . ctx ) ;
2005-01-09 15:55:25 +03:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
DEBUG ( 0 , ( " auth_context_create() returned %s " , nt_errstr ( nt_status ) ) ) ;
return nt_status ;
}
2003-08-13 05:53:07 +04:00
2005-01-09 15:55:25 +03:00
nt_status = auth_get_challenge ( smb_conn - > negotiate . auth_context , & challenge ) ;
2003-08-13 05:53:07 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
2005-01-09 15:55:25 +03:00
DEBUG ( 0 , ( " auth_get_challenge() returned %s " , nt_errstr ( nt_status ) ) ) ;
return nt_status ;
2003-08-13 05:53:07 +04:00
}
2005-01-09 15:55:25 +03:00
memcpy ( buff , challenge , 8 ) ;
return NT_STATUS_OK ;
2003-08-13 05:53:07 +04:00
}
/****************************************************************************
Reply for the core protocol .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-06-28 12:39:00 +04:00
static void reply_corep ( struct smbsrv_request * req , uint16_t choice )
2003-08-13 05:53:07 +04:00
{
req_setup_reply ( req , 1 , 0 ) ;
SSVAL ( req - > out . vwv , VWV ( 0 ) , choice ) ;
2004-06-29 11:40:14 +04:00
req - > smb_conn - > negotiate . protocol = PROTOCOL_CORE ;
2003-08-13 05:53:07 +04:00
2004-08-13 04:16:57 +04:00
if ( req - > smb_conn - > signing . mandatory_signing ) {
smbsrv_terminate_connection ( req - > smb_conn ,
2004-12-08 13:36:14 +03:00
" CORE does not support SMB signing, and it is mandatory \n " ) ;
2004-12-08 11:09:42 +03:00
return ;
2004-08-13 04:16:57 +04:00
}
2003-08-13 05:53:07 +04:00
req_send_reply ( req ) ;
}
/****************************************************************************
Reply for the coreplus protocol .
this is quite incomplete - we only fill in a small part of the reply , but as nobody uses
this any more it probably doesn ' t matter
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-06-28 12:39:00 +04:00
static void reply_coreplus ( struct smbsrv_request * req , uint16_t choice )
2003-08-13 05:53:07 +04:00
{
2004-05-25 21:24:24 +04:00
uint16_t raw = ( lp_readraw ( ) ? 1 : 0 ) | ( lp_writeraw ( ) ? 2 : 0 ) ;
2003-08-13 05:53:07 +04:00
req_setup_reply ( req , 13 , 0 ) ;
/* Reply, SMBlockread, SMBwritelock supported. */
SCVAL ( req - > out . hdr , HDR_FLG ,
CVAL ( req - > out . hdr , HDR_FLG ) | FLAG_SUPPORT_LOCKREAD ) ;
SSVAL ( req - > out . vwv , VWV ( 0 ) , choice ) ;
SSVAL ( req - > out . vwv , VWV ( 1 ) , 0x1 ) ; /* user level security, don't encrypt */
/* tell redirector we support
readbraw and writebraw ( possibly ) */
SSVAL ( req - > out . vwv , VWV ( 5 ) , raw ) ;
2004-06-29 11:40:14 +04:00
req - > smb_conn - > negotiate . protocol = PROTOCOL_COREPLUS ;
2003-08-13 05:53:07 +04:00
2004-08-13 04:16:57 +04:00
if ( req - > smb_conn - > signing . mandatory_signing ) {
smbsrv_terminate_connection ( req - > smb_conn ,
2004-12-08 13:36:14 +03:00
" COREPLUS does not support SMB signing, and it is mandatory \n " ) ;
2004-12-08 11:09:42 +03:00
return ;
2004-08-13 04:16:57 +04:00
}
2003-08-13 05:53:07 +04:00
req_send_reply ( req ) ;
}
/****************************************************************************
Reply for the lanman 1.0 protocol .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-06-28 12:39:00 +04:00
static void reply_lanman1 ( struct smbsrv_request * req , uint16_t choice )
2003-08-13 05:53:07 +04:00
{
int raw = ( lp_readraw ( ) ? 1 : 0 ) | ( lp_writeraw ( ) ? 2 : 0 ) ;
int secword = 0 ;
time_t t = req - > request_time . tv_sec ;
2004-06-29 11:40:14 +04:00
req - > smb_conn - > negotiate . encrypted_passwords = lp_encrypted_passwords ( ) ;
2003-08-13 05:53:07 +04:00
if ( lp_security ( ) ! = SEC_SHARE )
secword | = NEGOTIATE_SECURITY_USER_LEVEL ;
2004-06-29 11:40:14 +04:00
if ( req - > smb_conn - > negotiate . encrypted_passwords )
2003-08-13 05:53:07 +04:00
secword | = NEGOTIATE_SECURITY_CHALLENGE_RESPONSE ;
2004-06-29 11:40:14 +04:00
req - > smb_conn - > negotiate . protocol = PROTOCOL_LANMAN1 ;
2003-08-13 05:53:07 +04:00
2004-06-29 11:40:14 +04:00
req_setup_reply ( req , 13 , req - > smb_conn - > negotiate . encrypted_passwords ? 8 : 0 ) ;
2003-08-13 05:53:07 +04:00
/* SMBlockread, SMBwritelock supported. */
SCVAL ( req - > out . hdr , HDR_FLG ,
CVAL ( req - > out . hdr , HDR_FLG ) | FLAG_SUPPORT_LOCKREAD ) ;
SSVAL ( req - > out . vwv , VWV ( 0 ) , choice ) ;
SSVAL ( req - > out . vwv , VWV ( 1 ) , secword ) ;
2004-06-29 11:40:14 +04:00
SSVAL ( req - > out . vwv , VWV ( 2 ) , req - > smb_conn - > negotiate . max_recv ) ;
2003-08-13 05:53:07 +04:00
SSVAL ( req - > out . vwv , VWV ( 3 ) , lp_maxmux ( ) ) ;
SSVAL ( req - > out . vwv , VWV ( 4 ) , 1 ) ;
SSVAL ( req - > out . vwv , VWV ( 5 ) , raw ) ;
2005-01-30 03:54:57 +03:00
SIVAL ( req - > out . vwv , VWV ( 6 ) , req - > smb_conn - > connection - > server_id ) ;
2004-06-29 11:40:14 +04:00
srv_push_dos_date ( req - > smb_conn , req - > out . vwv , VWV ( 8 ) , t ) ;
SSVAL ( req - > out . vwv , VWV ( 10 ) , req - > smb_conn - > negotiate . zone_offset / 60 ) ;
2004-09-22 16:45:33 +04:00
SIVAL ( req - > out . vwv , VWV ( 11 ) , 0 ) ; /* reserved */
2003-08-13 05:53:07 +04:00
/* Create a token value and add it to the outgoing packet. */
2004-06-29 11:40:14 +04:00
if ( req - > smb_conn - > negotiate . encrypted_passwords ) {
2005-01-09 15:55:25 +03:00
NTSTATUS nt_status ;
2003-08-13 05:53:07 +04:00
SSVAL ( req - > out . vwv , VWV ( 11 ) , 8 ) ;
2005-01-09 15:55:25 +03:00
nt_status = get_challenge ( req - > smb_conn , req - > out . data ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
smbsrv_terminate_connection ( req - > smb_conn , " LANMAN1 get_challenge failed \n " ) ;
return ;
}
2003-08-13 05:53:07 +04:00
}
2004-08-13 04:16:57 +04:00
if ( req - > smb_conn - > signing . mandatory_signing ) {
smbsrv_terminate_connection ( req - > smb_conn ,
2004-12-08 13:36:14 +03:00
" LANMAN1 does not support SMB signing, and it is mandatory \n " ) ;
2004-12-08 11:09:42 +03:00
return ;
2004-08-13 04:16:57 +04:00
}
2003-08-13 05:53:07 +04:00
req_send_reply ( req ) ;
}
/****************************************************************************
Reply for the lanman 2.0 protocol .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-06-28 12:39:00 +04:00
static void reply_lanman2 ( struct smbsrv_request * req , uint16_t choice )
2003-08-13 05:53:07 +04:00
{
int raw = ( lp_readraw ( ) ? 1 : 0 ) | ( lp_writeraw ( ) ? 2 : 0 ) ;
int secword = 0 ;
time_t t = req - > request_time . tv_sec ;
2004-06-29 11:40:14 +04:00
req - > smb_conn - > negotiate . encrypted_passwords = lp_encrypted_passwords ( ) ;
2003-08-13 05:53:07 +04:00
if ( lp_security ( ) ! = SEC_SHARE )
secword | = NEGOTIATE_SECURITY_USER_LEVEL ;
2004-06-29 11:40:14 +04:00
if ( req - > smb_conn - > negotiate . encrypted_passwords )
2003-08-13 05:53:07 +04:00
secword | = NEGOTIATE_SECURITY_CHALLENGE_RESPONSE ;
2004-06-29 11:40:14 +04:00
req - > smb_conn - > negotiate . protocol = PROTOCOL_LANMAN2 ;
2003-08-13 05:53:07 +04:00
req_setup_reply ( req , 13 , 0 ) ;
SSVAL ( req - > out . vwv , VWV ( 0 ) , choice ) ;
SSVAL ( req - > out . vwv , VWV ( 1 ) , secword ) ;
2004-06-29 11:40:14 +04:00
SSVAL ( req - > out . vwv , VWV ( 2 ) , req - > smb_conn - > negotiate . max_recv ) ;
2003-08-13 05:53:07 +04:00
SSVAL ( req - > out . vwv , VWV ( 3 ) , lp_maxmux ( ) ) ;
SSVAL ( req - > out . vwv , VWV ( 4 ) , 1 ) ;
SSVAL ( req - > out . vwv , VWV ( 5 ) , raw ) ;
2005-01-30 03:54:57 +03:00
SIVAL ( req - > out . vwv , VWV ( 6 ) , req - > smb_conn - > connection - > server_id ) ;
2004-06-29 11:40:14 +04:00
srv_push_dos_date ( req - > smb_conn , req - > out . vwv , VWV ( 8 ) , t ) ;
SSVAL ( req - > out . vwv , VWV ( 10 ) , req - > smb_conn - > negotiate . zone_offset / 60 ) ;
2004-12-09 07:40:57 +03:00
SIVAL ( req - > out . vwv , VWV ( 11 ) , 0 ) ;
2003-08-13 05:53:07 +04:00
/* Create a token value and add it to the outgoing packet. */
2004-06-29 11:40:14 +04:00
if ( req - > smb_conn - > negotiate . encrypted_passwords ) {
2003-08-13 05:53:07 +04:00
SSVAL ( req - > out . vwv , VWV ( 11 ) , 8 ) ;
req_grow_data ( req , 8 ) ;
2004-06-29 11:40:14 +04:00
get_challenge ( req - > smb_conn , req - > out . data ) ;
2003-08-13 05:53:07 +04:00
}
req_push_str ( req , NULL , lp_workgroup ( ) , - 1 , STR_TERMINATE ) ;
2004-08-13 04:16:57 +04:00
if ( req - > smb_conn - > signing . mandatory_signing ) {
smbsrv_terminate_connection ( req - > smb_conn ,
2004-12-08 13:36:14 +03:00
" LANMAN2 does not support SMB signing, and it is mandatory \n " ) ;
2004-12-08 11:09:42 +03:00
return ;
2004-08-13 04:16:57 +04:00
}
2003-08-13 05:53:07 +04:00
2004-08-11 22:09:40 +04:00
req_send_reply ( req ) ;
2003-08-13 05:53:07 +04:00
}
/****************************************************************************
Reply for the nt protocol .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-06-28 12:39:00 +04:00
static void reply_nt1 ( struct smbsrv_request * req , uint16_t choice )
2003-08-13 05:53:07 +04:00
{
/* dual names + lock_and_read + nt SMBs + remote API calls */
int capabilities ;
int secword = 0 ;
time_t t = req - > request_time . tv_sec ;
2004-04-11 00:18:22 +04:00
NTTIME nttime ;
2003-08-13 05:53:07 +04:00
BOOL negotiate_spnego = False ;
2004-04-11 00:18:22 +04:00
unix_to_nt_time ( & nttime , t ) ;
2003-08-13 05:53:07 +04:00
capabilities =
CAP_NT_FIND | CAP_LOCK_AND_READ |
CAP_LEVEL_II_OPLOCKS | CAP_NT_SMBS | CAP_RPC_REMOTE_APIS ;
2004-06-29 11:40:14 +04:00
req - > smb_conn - > negotiate . encrypted_passwords = lp_encrypted_passwords ( ) ;
2003-08-13 05:53:07 +04:00
/* do spnego in user level security if the client
supports it and we can do encrypted passwords */
2004-08-13 04:16:57 +04:00
if ( req - > smb_conn - > negotiate . encrypted_passwords & &
2003-08-13 05:53:07 +04:00
( lp_security ( ) ! = SEC_SHARE ) & &
lp_use_spnego ( ) & &
( req - > flags2 & FLAGS2_EXTENDED_SECURITY ) ) {
2004-08-11 22:09:40 +04:00
negotiate_spnego = True ;
2003-08-13 05:53:07 +04:00
capabilities | = CAP_EXTENDED_SECURITY ;
}
if ( lp_unix_extensions ( ) ) {
capabilities | = CAP_UNIX ;
}
2004-05-25 17:57:39 +04:00
if ( lp_large_readwrite ( ) ) {
2003-08-13 05:53:07 +04:00
capabilities | = CAP_LARGE_READX | CAP_LARGE_WRITEX | CAP_W2K_SMBS ;
}
2004-05-25 17:57:39 +04:00
capabilities | = CAP_LARGE_FILES ;
2003-08-13 05:53:07 +04:00
if ( lp_readraw ( ) & & lp_writeraw ( ) ) {
capabilities | = CAP_RAW_MODE ;
}
/* allow for disabling unicode */
if ( lp_unicode ( ) ) {
capabilities | = CAP_UNICODE ;
}
if ( lp_nt_status_support ( ) ) {
capabilities | = CAP_STATUS32 ;
}
if ( lp_host_msdfs ( ) ) {
capabilities | = CAP_DFS ;
}
if ( lp_security ( ) ! = SEC_SHARE ) {
secword | = NEGOTIATE_SECURITY_USER_LEVEL ;
}
2004-06-29 11:40:14 +04:00
if ( req - > smb_conn - > negotiate . encrypted_passwords ) {
2003-08-13 05:53:07 +04:00
secword | = NEGOTIATE_SECURITY_CHALLENGE_RESPONSE ;
}
2004-05-22 15:16:21 +04:00
2004-08-13 04:16:57 +04:00
if ( req - > smb_conn - > signing . allow_smb_signing ) {
2004-05-22 15:16:21 +04:00
secword | = NEGOTIATE_SECURITY_SIGNATURES_ENABLED ;
2004-08-13 04:16:57 +04:00
}
if ( req - > smb_conn - > signing . mandatory_signing ) {
secword | = NEGOTIATE_SECURITY_SIGNATURES_REQUIRED ;
2004-05-22 15:16:21 +04:00
}
2003-08-13 05:53:07 +04:00
2004-06-29 11:40:14 +04:00
req - > smb_conn - > negotiate . protocol = PROTOCOL_NT1 ;
2003-08-13 05:53:07 +04:00
req_setup_reply ( req , 17 , 0 ) ;
SSVAL ( req - > out . vwv , VWV ( 0 ) , choice ) ;
SCVAL ( req - > out . vwv , VWV ( 1 ) , secword ) ;
/* notice the strange +1 on vwv here? That's because
this is the one and only SMB packet that is malformed in
the specification - all the command words after the secword
are offset by 1 byte */
SSVAL ( req - > out . vwv + 1 , VWV ( 1 ) , lp_maxmux ( ) ) ;
SSVAL ( req - > out . vwv + 1 , VWV ( 2 ) , 1 ) ; /* num vcs */
2004-06-29 11:40:14 +04:00
SIVAL ( req - > out . vwv + 1 , VWV ( 3 ) , req - > smb_conn - > negotiate . max_recv ) ;
2003-08-13 05:53:07 +04:00
SIVAL ( req - > out . vwv + 1 , VWV ( 5 ) , 0x10000 ) ; /* raw size. full 64k */
2005-01-30 03:54:57 +03:00
SIVAL ( req - > out . vwv + 1 , VWV ( 7 ) , req - > smb_conn - > connection - > server_id ) ; /* session key */
2003-08-13 05:53:07 +04:00
SIVAL ( req - > out . vwv + 1 , VWV ( 9 ) , capabilities ) ;
2004-05-25 17:57:39 +04:00
push_nttime ( req - > out . vwv + 1 , VWV ( 11 ) , nttime ) ;
2004-06-29 11:40:14 +04:00
SSVALS ( req - > out . vwv + 1 , VWV ( 15 ) , req - > smb_conn - > negotiate . zone_offset / 60 ) ;
2003-08-13 05:53:07 +04:00
if ( ! negotiate_spnego ) {
/* Create a token value and add it to the outgoing packet. */
2004-06-29 11:40:14 +04:00
if ( req - > smb_conn - > negotiate . encrypted_passwords ) {
2003-08-13 05:53:07 +04:00
req_grow_data ( req , 8 ) ;
/* note that we do not send a challenge at all if
we are using plaintext */
2004-06-29 11:40:14 +04:00
get_challenge ( req - > smb_conn , req - > out . ptr ) ;
2003-08-13 05:53:07 +04:00
req - > out . ptr + = 8 ;
SCVAL ( req - > out . vwv + 1 , VWV ( 16 ) , 8 ) ;
}
req_push_str ( req , NULL , lp_workgroup ( ) , - 1 , STR_UNICODE | STR_TERMINATE | STR_NOALIGN ) ;
2004-05-22 11:38:15 +04:00
req_push_str ( req , NULL , lp_netbios_name ( ) , - 1 , STR_UNICODE | STR_TERMINATE | STR_NOALIGN ) ;
2003-08-13 05:53:07 +04:00
DEBUG ( 3 , ( " not using SPNEGO \n " ) ) ;
} else {
2005-10-20 07:47:55 +04:00
struct cli_credentials * server_credentials ;
2004-08-11 22:09:40 +04:00
struct gensec_security * gensec_security ;
DATA_BLOB null_data_blob = data_blob ( NULL , 0 ) ;
DATA_BLOB blob ;
2005-06-16 15:36:09 +04:00
NTSTATUS nt_status = gensec_server_start ( req - > smb_conn ,
& gensec_security ,
req - > smb_conn - > connection - > event . ctx ) ;
2004-08-11 22:09:40 +04:00
2005-10-20 07:47:55 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
DEBUG ( 0 , ( " Failed to start GENSEC: %s \n " , nt_errstr ( nt_status ) ) ) ;
smbsrv_terminate_connection ( req - > smb_conn , " Failed to start GENSEC \n " ) ;
return ;
}
2004-08-11 22:09:40 +04:00
if ( req - > smb_conn - > negotiate . auth_context ) {
smbsrv_terminate_connection ( req - > smb_conn , " reply_nt1: is this a secondary negprot? auth_context is non-NULL! \n " ) ;
return ;
}
2005-10-20 07:47:55 +04:00
server_credentials
= cli_credentials_init ( req ) ;
if ( ! server_credentials ) {
smbsrv_terminate_connection ( req - > smb_conn , " Failed to init server credentials \n " ) ;
return ;
}
2004-08-11 22:09:40 +04:00
2005-10-20 07:47:55 +04:00
cli_credentials_set_conf ( server_credentials ) ;
nt_status = cli_credentials_set_machine_account ( server_credentials ) ;
2004-08-11 22:09:40 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
2005-10-20 07:47:55 +04:00
DEBUG ( 10 , ( " Failed to obtain server credentials, perhaps a standalone server?: %s \n " , nt_errstr ( nt_status ) ) ) ;
talloc_free ( server_credentials ) ;
server_credentials = NULL ;
2004-08-11 22:09:40 +04:00
}
2005-10-20 07:47:55 +04:00
req - > smb_conn - > negotiate . server_credentials = talloc_steal ( req - > smb_conn , server_credentials ) ;
gensec_set_target_service ( gensec_security , " cifs " ) ;
gensec_set_credentials ( gensec_security , server_credentials ) ;
2004-12-05 19:29:27 +03:00
nt_status = gensec_start_mech_by_oid ( gensec_security , GENSEC_OID_SPNEGO ) ;
2004-08-11 22:09:40 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
DEBUG ( 0 , ( " Failed to start SPNEGO: %s \n " , nt_errstr ( nt_status ) ) ) ;
smbsrv_terminate_connection ( req - > smb_conn , " Failed to start SPNEGO \n " ) ;
return ;
}
2004-09-08 09:39:06 +04:00
nt_status = gensec_update ( gensec_security , req , null_data_blob , & blob ) ;
2004-08-11 22:09:40 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) & & ! NT_STATUS_EQUAL ( nt_status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) {
DEBUG ( 0 , ( " Failed to get SPNEGO to give us the first token: %s \n " , nt_errstr ( nt_status ) ) ) ;
smbsrv_terminate_connection ( req - > smb_conn , " Failed to start SPNEGO - no first token \n " ) ;
return ;
}
req - > smb_conn - > negotiate . spnego_negotiated = True ;
req_grow_data ( req , blob . length + 16 ) ;
/* a NOT very random guid */
memset ( req - > out . ptr , ' \0 ' , 16 ) ;
req - > out . ptr + = 16 ;
2003-08-13 05:53:07 +04:00
memcpy ( req - > out . ptr , blob . data , blob . length ) ;
2004-08-11 22:09:40 +04:00
SCVAL ( req - > out . vwv + 1 , VWV ( 16 ) , blob . length + 16 ) ;
req - > out . ptr + = blob . length ;
2003-08-13 05:53:07 +04:00
DEBUG ( 3 , ( " using SPNEGO \n " ) ) ;
}
2004-05-22 15:16:21 +04:00
req_send_reply_nosign ( req ) ;
2003-08-13 05:53:07 +04:00
}
/* List of supported protocols, most desired first */
static const struct {
const char * proto_name ;
const char * short_name ;
2004-06-28 12:39:00 +04:00
void ( * proto_reply_fn ) ( struct smbsrv_request * req , uint16_t choice ) ;
2003-08-13 05:53:07 +04:00
int protocol_level ;
} supported_protocols [ ] = {
{ " NT LANMAN 1.0 " , " NT1 " , reply_nt1 , PROTOCOL_NT1 } ,
{ " NT LM 0.12 " , " NT1 " , reply_nt1 , PROTOCOL_NT1 } ,
2004-12-05 10:59:42 +03:00
{ " LANMAN2.1 " , " LANMAN2 " , reply_lanman2 , PROTOCOL_LANMAN2 } ,
2003-08-13 05:53:07 +04:00
{ " LM1.2X002 " , " LANMAN2 " , reply_lanman2 , PROTOCOL_LANMAN2 } ,
{ " Samba " , " LANMAN2 " , reply_lanman2 , PROTOCOL_LANMAN2 } ,
{ " DOS LM1.2X002 " , " LANMAN2 " , reply_lanman2 , PROTOCOL_LANMAN2 } ,
{ " LANMAN1.0 " , " LANMAN1 " , reply_lanman1 , PROTOCOL_LANMAN1 } ,
{ " MICROSOFT NETWORKS 3.0 " , " LANMAN1 " , reply_lanman1 , PROTOCOL_LANMAN1 } ,
{ " MICROSOFT NETWORKS 1.03 " , " COREPLUS " , reply_coreplus , PROTOCOL_COREPLUS } ,
{ " PC NETWORK PROGRAM 1.0 " , " CORE " , reply_corep , PROTOCOL_CORE } ,
{ NULL , NULL , NULL , 0 } ,
} ;
/****************************************************************************
Reply to a negprot .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-06-28 12:39:00 +04:00
void reply_negprot ( struct smbsrv_request * req )
2003-08-13 05:53:07 +04:00
{
int Index = 0 ;
int choice = - 1 ;
int protocol ;
2004-12-04 16:56:25 +03:00
uint8_t * p ;
2003-08-13 05:53:07 +04:00
2004-06-29 11:40:14 +04:00
if ( req - > smb_conn - > negotiate . done_negprot ) {
2004-07-14 01:04:56 +04:00
smbsrv_terminate_connection ( req - > smb_conn , " multiple negprot's are not permitted " ) ;
2004-09-23 04:27:21 +04:00
return ;
2003-08-13 05:53:07 +04:00
}
2004-06-29 11:40:14 +04:00
req - > smb_conn - > negotiate . done_negprot = True ;
2003-08-13 05:53:07 +04:00
p = req - > in . data + 1 ;
while ( p < req - > in . data + req - > in . data_size ) {
Index + + ;
2004-12-04 16:56:25 +03:00
DEBUG ( 3 , ( " Requested protocol [%s] \n " , ( const char * ) p ) ) ;
p + = strlen ( ( const char * ) p ) + 2 ;
2003-08-13 05:53:07 +04:00
}
/* Check for protocols, most desirable first */
for ( protocol = 0 ; supported_protocols [ protocol ] . proto_name ; protocol + + ) {
p = req - > in . data + 1 ;
Index = 0 ;
if ( ( supported_protocols [ protocol ] . protocol_level < = lp_maxprotocol ( ) ) & &
( supported_protocols [ protocol ] . protocol_level > = lp_minprotocol ( ) ) )
while ( p < ( req - > in . data + req - > in . data_size ) ) {
2004-12-04 16:56:25 +03:00
if ( strequal ( ( const char * ) p , supported_protocols [ protocol ] . proto_name ) )
2003-08-13 05:53:07 +04:00
choice = Index ;
Index + + ;
2004-12-04 16:56:25 +03:00
p + = strlen ( ( const char * ) p ) + 2 ;
2003-08-13 05:53:07 +04:00
}
if ( choice ! = - 1 )
break ;
}
if ( choice ! = - 1 ) {
sub_set_remote_proto ( supported_protocols [ protocol ] . short_name ) ;
supported_protocols [ protocol ] . proto_reply_fn ( req , choice ) ;
DEBUG ( 3 , ( " Selected protocol %s \n " , supported_protocols [ protocol ] . proto_name ) ) ;
} else {
DEBUG ( 0 , ( " No protocol supported ! \n " ) ) ;
}
DEBUG ( 5 , ( " negprot index=%d \n " , choice ) ) ;
}