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
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2003-08-13 05:53:07 +04:00
( 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
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-08-13 05:53:07 +04:00
*/
# include "includes.h"
2006-11-07 03:48:36 +03:00
# include "auth/credentials/credentials.h"
# include "auth/gensec/gensec.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"
2006-03-06 17:19:11 +03:00
# include "libcli/smb2/smb2.h"
# include "smb_server/smb2/smb2_server.h"
2006-04-28 05:55:17 +04:00
# include "smb_server/service_smb_proto.h"
2005-01-30 03:54:57 +03:00
# include "smbd/service_stream.h"
2006-03-06 17:19:11 +03:00
# include "lib/stream/packet.h"
2007-09-08 16:42:09 +04:00
# include "param/param.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 " ) ) ;
2007-07-03 12:05:55 +04:00
nt_status = auth_context_create ( smb_conn ,
2006-07-31 18:05:08 +04:00
smb_conn - > connection - > event . ctx ,
smb_conn - > connection - > msg_ctx ,
& smb_conn - > negotiate . auth_context ) ;
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
{
2006-03-06 19:19:27 +03:00
smbsrv_setup_reply ( req , 1 , 0 ) ;
2003-08-13 05:53:07 +04:00
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
}
2006-03-06 19:19:27 +03:00
smbsrv_send_reply ( req ) ;
2003-08-13 05:53:07 +04:00
}
/****************************************************************************
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
{
2007-09-28 05:17:46 +04:00
uint16_t raw = ( lp_readraw ( global_loadparm ) ? 1 : 0 ) | ( lp_writeraw ( global_loadparm ) ? 2 : 0 ) ;
2003-08-13 05:53:07 +04:00
2006-03-06 19:19:27 +03:00
smbsrv_setup_reply ( req , 13 , 0 ) ;
2003-08-13 05:53:07 +04:00
/* 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
}
2006-03-06 19:19:27 +03:00
smbsrv_send_reply ( req ) ;
2003-08-13 05:53:07 +04:00
}
/****************************************************************************
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
{
2007-09-28 05:17:46 +04:00
int raw = ( lp_readraw ( global_loadparm ) ? 1 : 0 ) | ( lp_writeraw ( global_loadparm ) ? 2 : 0 ) ;
2003-08-13 05:53:07 +04:00
int secword = 0 ;
time_t t = req - > request_time . tv_sec ;
2007-09-28 05:17:46 +04:00
req - > smb_conn - > negotiate . encrypted_passwords = lp_encrypted_passwords ( global_loadparm ) ;
2003-08-13 05:53:07 +04:00
2007-09-28 05:17:46 +04:00
if ( lp_security ( global_loadparm ) ! = SEC_SHARE )
2003-08-13 05:53:07 +04:00
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
2006-03-06 19:19:27 +03:00
smbsrv_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 ) ;
2007-09-28 05:17:46 +04:00
SSVAL ( req - > out . vwv , VWV ( 3 ) , lp_maxmux ( global_loadparm ) ) ;
2003-08-13 05:53:07 +04:00
SSVAL ( req - > out . vwv , VWV ( 4 ) , 1 ) ;
SSVAL ( req - > out . vwv , VWV ( 5 ) , raw ) ;
2007-01-10 13:52:09 +03:00
SIVAL ( req - > out . vwv , VWV ( 6 ) , req - > smb_conn - > connection - > server_id . 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
}
2006-03-06 19:19:27 +03:00
smbsrv_send_reply ( req ) ;
2003-08-13 05:53:07 +04:00
}
/****************************************************************************
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
{
2007-09-28 05:17:46 +04:00
int raw = ( lp_readraw ( global_loadparm ) ? 1 : 0 ) | ( lp_writeraw ( global_loadparm ) ? 2 : 0 ) ;
2003-08-13 05:53:07 +04:00
int secword = 0 ;
time_t t = req - > request_time . tv_sec ;
2007-09-28 05:17:46 +04:00
req - > smb_conn - > negotiate . encrypted_passwords = lp_encrypted_passwords ( global_loadparm ) ;
2003-08-13 05:53:07 +04:00
2007-09-28 05:17:46 +04:00
if ( lp_security ( global_loadparm ) ! = SEC_SHARE )
2003-08-13 05:53:07 +04:00
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
2006-03-06 19:19:27 +03:00
smbsrv_setup_reply ( req , 13 , 0 ) ;
2003-08-13 05:53:07 +04:00
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 ) ;
2007-09-28 05:17:46 +04:00
SSVAL ( req - > out . vwv , VWV ( 3 ) , lp_maxmux ( global_loadparm ) ) ;
2003-08-13 05:53:07 +04:00
SSVAL ( req - > out . vwv , VWV ( 4 ) , 1 ) ;
SSVAL ( req - > out . vwv , VWV ( 5 ) , raw ) ;
2007-01-10 13:52:09 +03:00
SIVAL ( req - > out . vwv , VWV ( 6 ) , req - > smb_conn - > connection - > server_id . 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
}
2007-09-28 05:17:46 +04:00
req_push_str ( req , NULL , lp_workgroup ( global_loadparm ) , - 1 , STR_TERMINATE ) ;
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
" 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
2006-03-06 19:19:27 +03:00
smbsrv_send_reply ( req ) ;
2003-08-13 05:53:07 +04:00
}
2006-02-09 06:04:48 +03:00
static void reply_nt1_orig ( struct smbsrv_request * req )
{
/* Create a token value and add it to the outgoing packet. */
if ( req - > smb_conn - > negotiate . encrypted_passwords ) {
req_grow_data ( req , 8 ) ;
/* note that we do not send a challenge at all if
we are using plaintext */
get_challenge ( req - > smb_conn , req - > out . ptr ) ;
req - > out . ptr + = 8 ;
SCVAL ( req - > out . vwv + 1 , VWV ( 16 ) , 8 ) ;
}
2007-09-28 05:17:46 +04:00
req_push_str ( req , NULL , lp_workgroup ( global_loadparm ) , - 1 , STR_UNICODE | STR_TERMINATE | STR_NOALIGN ) ;
req_push_str ( req , NULL , lp_netbios_name ( global_loadparm ) , - 1 , STR_UNICODE | STR_TERMINATE | STR_NOALIGN ) ;
2006-03-07 06:34:14 +03:00
DEBUG ( 3 , ( " not using extended security (SPNEGO or NTLMSSP) \n " ) ) ;
2006-02-09 06:04:48 +03:00
}
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 ;
2006-10-28 10:06:15 +04:00
char * large_test_path ;
2003-08-13 05:53:07 +04:00
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 ;
2007-09-28 05:17:46 +04:00
req - > smb_conn - > negotiate . encrypted_passwords = lp_encrypted_passwords ( global_loadparm ) ;
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 & &
2007-09-28 05:17:46 +04:00
( lp_security ( global_loadparm ) ! = SEC_SHARE ) & &
lp_use_spnego ( global_loadparm ) & &
2003-08-13 05:53:07 +04:00
( 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 ;
}
2007-09-28 05:17:46 +04:00
if ( lp_unix_extensions ( global_loadparm ) ) {
2003-08-13 05:53:07 +04:00
capabilities | = CAP_UNIX ;
}
2007-09-28 05:17:46 +04:00
if ( lp_large_readwrite ( global_loadparm ) ) {
2003-08-13 05:53:07 +04:00
capabilities | = CAP_LARGE_READX | CAP_LARGE_WRITEX | CAP_W2K_SMBS ;
}
2006-10-28 10:06:15 +04:00
2007-10-01 22:52:55 +04:00
large_test_path = lock_path ( req , global_loadparm , " large_test.dat " ) ;
2006-10-28 10:06:15 +04:00
if ( large_file_support ( large_test_path ) ) {
capabilities | = CAP_LARGE_FILES ;
}
2003-08-13 05:53:07 +04:00
2007-09-28 05:17:46 +04:00
if ( lp_readraw ( global_loadparm ) & & lp_writeraw ( global_loadparm ) ) {
2003-08-13 05:53:07 +04:00
capabilities | = CAP_RAW_MODE ;
}
/* allow for disabling unicode */
2007-09-28 05:17:46 +04:00
if ( lp_unicode ( global_loadparm ) ) {
2003-08-13 05:53:07 +04:00
capabilities | = CAP_UNICODE ;
}
2007-09-28 05:17:46 +04:00
if ( lp_nt_status_support ( global_loadparm ) ) {
2003-08-13 05:53:07 +04:00
capabilities | = CAP_STATUS32 ;
}
2007-09-28 05:17:46 +04:00
if ( lp_host_msdfs ( global_loadparm ) ) {
2003-08-13 05:53:07 +04:00
capabilities | = CAP_DFS ;
}
2007-09-28 05:17:46 +04:00
if ( lp_security ( global_loadparm ) ! = SEC_SHARE ) {
2003-08-13 05:53:07 +04:00
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
2006-03-06 19:19:27 +03:00
smbsrv_setup_reply ( req , 17 , 0 ) ;
2003-08-13 05:53:07 +04:00
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 */
2007-09-28 05:17:46 +04:00
SSVAL ( req - > out . vwv + 1 , VWV ( 1 ) , lp_maxmux ( global_loadparm ) ) ;
2003-08-13 05:53:07 +04:00
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 */
2007-01-10 13:52:09 +03:00
SIVAL ( req - > out . vwv + 1 , VWV ( 7 ) , req - > smb_conn - > connection - > server_id . 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 ) {
2006-02-09 06:04:48 +03:00
reply_nt1_orig ( req ) ;
2003-08-13 05:53:07 +04:00
} 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 ;
2006-02-09 06:04:48 +03:00
const char * oid ;
2006-07-31 18:05:08 +04:00
NTSTATUS nt_status ;
nt_status = gensec_server_start ( req - > smb_conn ,
req - > smb_conn - > connection - > event . ctx ,
req - > smb_conn - > connection - > msg_ctx ,
& gensec_security ) ;
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
2007-09-28 05:17:46 +04:00
cli_credentials_set_conf ( server_credentials , global_loadparm ) ;
2005-10-20 07:47:55 +04:00
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 ) ;
2006-02-09 06:04:48 +03:00
oid = GENSEC_OID_SPNEGO ;
nt_status = gensec_start_mech_by_oid ( gensec_security , oid ) ;
2004-08-11 22:09:40 +04:00
2005-12-01 08:06:52 +03:00
if ( NT_STATUS_IS_OK ( nt_status ) ) {
/* Get and push the proposed OID list into the packets */
nt_status = gensec_update ( gensec_security , req , null_data_blob , & blob ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) & & ! NT_STATUS_EQUAL ( nt_status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) {
2006-02-09 06:04:48 +03:00
DEBUG ( 1 , ( " Failed to get SPNEGO to give us the first token: %s \n " , nt_errstr ( nt_status ) ) ) ;
2005-12-01 08:06:52 +03:00
}
2006-02-09 06:04:48 +03:00
}
2006-03-07 06:34:14 +03:00
if ( NT_STATUS_EQUAL ( nt_status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) {
DEBUG ( 3 , ( " using SPNEGO \n " ) ) ;
} else {
2005-12-01 08:06:52 +03:00
DEBUG ( 5 , ( " Failed to start SPNEGO, falling back to NTLMSSP only: %s \n " , nt_errstr ( nt_status ) ) ) ;
2006-02-09 06:04:48 +03:00
oid = GENSEC_OID_NTLMSSP ;
nt_status = gensec_start_mech_by_oid ( gensec_security , oid ) ;
2005-12-01 08:06:52 +03:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
DEBUG ( 0 , ( " Failed to start SPNEGO as well as NTLMSSP fallback: %s \n " , nt_errstr ( nt_status ) ) ) ;
2006-02-09 06:04:48 +03:00
reply_nt1_orig ( req ) ;
2005-12-01 08:06:52 +03:00
return ;
}
/* NTLMSSP is a client-first exchange */
blob = data_blob ( NULL , 0 ) ;
2006-03-07 06:34:14 +03:00
DEBUG ( 3 , ( " using raw-NTLMSSP \n " ) ) ;
2004-08-11 22:09:40 +04:00
}
2006-02-09 06:04:48 +03:00
req - > smb_conn - > negotiate . oid = oid ;
2004-08-11 22:09:40 +04:00
req_grow_data ( req , blob . length + 16 ) ;
2005-12-01 08:06:52 +03:00
/* a NOT very random guid, perhaps we should get it
* from the credentials ( kitchen sink . . . ) */
2004-08-11 22:09:40 +04:00
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
}
2006-03-06 19:19:27 +03:00
smbsrv_send_reply_nosign ( req ) ;
2003-08-13 05:53:07 +04:00
}
2006-03-06 17:19:11 +03:00
/****************************************************************************
Reply for the SMB2 2.001 protocol
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void reply_smb2 ( struct smbsrv_request * req , uint16_t choice )
{
struct smbsrv_connection * smb_conn = req - > smb_conn ;
2007-05-10 12:39:44 +04:00
NTSTATUS status ;
talloc_free ( smb_conn - > sessions . idtree_vuid ) ;
ZERO_STRUCT ( smb_conn - > sessions ) ;
talloc_free ( smb_conn - > smb_tcons . idtree_tid ) ;
ZERO_STRUCT ( smb_conn - > smb_tcons ) ;
ZERO_STRUCT ( smb_conn - > signing ) ;
2006-03-06 17:19:11 +03:00
/* reply with a SMB2 packet */
2007-05-10 12:39:44 +04:00
status = smbsrv_init_smb2_connection ( smb_conn ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
smbsrv_terminate_connection ( smb_conn , nt_errstr ( status ) ) ;
talloc_free ( req ) ;
return ;
}
2006-07-01 18:18:20 +04:00
packet_set_callback ( smb_conn - > packet , smbsrv_recv_smb2_request ) ;
2006-03-06 17:19:11 +03:00
smb2srv_reply_smb_negprot ( req ) ;
req = NULL ;
}
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 [ ] = {
2006-03-06 17:19:11 +03:00
{ " SMB 2.001 " , " SMB2 " , reply_smb2 , PROTOCOL_SMB2 } ,
2006-03-06 16:17:16 +03:00
{ " NT LANMAN 1.0 " , " NT1 " , reply_nt1 , PROTOCOL_NT1 } ,
{ " NT LM 0.12 " , " NT1 " , reply_nt1 , PROTOCOL_NT1 } ,
{ " LANMAN2.1 " , " LANMAN2 " , reply_lanman2 , PROTOCOL_LANMAN2 } ,
{ " LM1.2X002 " , " LANMAN2 " , reply_lanman2 , PROTOCOL_LANMAN2 } ,
{ " Samba " , " LANMAN2 " , reply_lanman2 , PROTOCOL_LANMAN2 } ,
{ " DOS LM1.2X002 " , " LANMAN2 " , reply_lanman2 , PROTOCOL_LANMAN2 } ,
{ " Windows for Workgroups 3.1a " , " LANMAN1 " , reply_lanman1 , PROTOCOL_LANMAN1 } ,
{ " 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 } ,
2003-08-13 05:53:07 +04:00
{ NULL , NULL , NULL , 0 } ,
} ;
/****************************************************************************
Reply to a negprot .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-03-06 18:31:01 +03:00
void smbsrv_reply_negprot ( struct smbsrv_request * req )
2003-08-13 05:53:07 +04:00
{
int protocol ;
2004-12-04 16:56:25 +03:00
uint8_t * p ;
2006-03-06 16:22:16 +03:00
uint32_t protos_count = 0 ;
char * * protos = NULL ;
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
2006-03-06 16:22:16 +03:00
p = req - > in . data ;
while ( True ) {
size_t len ;
2003-08-13 05:53:07 +04:00
2006-03-06 16:22:16 +03:00
protos = talloc_realloc ( req , protos , char * , protos_count + 1 ) ;
if ( ! protos ) {
smbsrv_terminate_connection ( req - > smb_conn , nt_errstr ( NT_STATUS_NO_MEMORY ) ) ;
return ;
}
protos [ protos_count ] = NULL ;
len = req_pull_ascii4 ( req , ( const char * * ) & protos [ protos_count ] , p , STR_ASCII | STR_TERMINATE ) ;
p + = len ;
if ( len = = 0 | | ! protos [ protos_count ] ) break ;
2006-03-08 18:14:59 +03:00
DEBUG ( 5 , ( " Requested protocol [%d][%s] \n " , protos_count , protos [ protos_count ] ) ) ;
2006-03-06 16:22:16 +03:00
protos_count + + ;
2003-08-13 05:53:07 +04:00
}
2006-03-06 16:22:16 +03:00
2003-08-13 05:53:07 +04:00
/* Check for protocols, most desirable first */
for ( protocol = 0 ; supported_protocols [ protocol ] . proto_name ; protocol + + ) {
2006-03-06 16:22:16 +03:00
int i ;
2007-09-28 05:17:46 +04:00
if ( supported_protocols [ protocol ] . protocol_level > lp_srv_maxprotocol ( global_loadparm ) )
continue ;
if ( supported_protocols [ protocol ] . protocol_level < lp_srv_minprotocol ( global_loadparm ) )
continue ;
2006-03-06 16:22:16 +03:00
for ( i = 0 ; i < protos_count ; i + + ) {
if ( strcmp ( supported_protocols [ protocol ] . proto_name , protos [ i ] ) ! = 0 ) continue ;
supported_protocols [ protocol ] . proto_reply_fn ( req , i ) ;
DEBUG ( 3 , ( " Selected protocol [%d][%s] \n " ,
i , supported_protocols [ protocol ] . proto_name ) ) ;
return ;
}
2003-08-13 05:53:07 +04:00
}
2006-03-06 16:22:16 +03:00
smbsrv_terminate_connection ( req - > smb_conn , " No protocol supported ! " ) ;
2003-08-13 05:53:07 +04:00
}