2006-01-10 01:12:53 +03:00
2003-08-13 05:53:07 +04:00
/*
Unix SMB / CIFS implementation .
handle SMBsessionsetup
2005-04-10 11:39:51 +04:00
Copyright ( C ) Andrew Tridgell 1998 - 2001
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2001 - 2005
Copyright ( C ) Jim McDonough 2002
Copyright ( C ) Luke Howard 2003
2005-11-18 15:57:48 +03:00
Copyright ( C ) Stefan Metzmacher 2005
2003-08-13 05:53:07 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
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"
2009-12-22 18:24:44 +03:00
# include <tevent.h>
2005-01-18 13:10:35 +03:00
# include "version.h"
2006-11-07 03:48:36 +03:00
# 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"
2020-11-20 17:27:17 +03:00
# include "samba/service_stream.h"
2007-09-08 16:42:09 +04:00
# include "param/param.h"
2009-12-23 12:19:43 +03:00
# include "../lib/tsocket/tsocket.h"
2010-09-12 16:24:46 +04:00
# include "lib/stream/packet.h"
2003-08-13 05:53:07 +04:00
2010-04-13 06:00:06 +04:00
struct sesssetup_context {
2011-05-07 10:14:06 +04:00
struct auth4_context * auth_context ;
2010-04-13 06:00:06 +04:00
struct smbsrv_request * req ;
} ;
2017-03-01 06:28:06 +03:00
/*
* Log the SMB authentication , as by not calling GENSEC we won ' t log
* it during the gensec_session_info ( ) .
*/
void smbsrv_not_spengo_sesssetup_authz_log ( struct smbsrv_request * req ,
struct auth_session_info * session_info )
{
struct tsocket_address * local_address ;
struct tsocket_address * remote_address ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
remote_address = socket_get_remote_addr ( req - > smb_conn - > connection - > socket ,
frame ) ;
local_address = socket_get_local_addr ( req - > smb_conn - > connection - > socket ,
frame ) ;
2017-03-24 05:18:46 +03:00
log_successful_authz_event ( req - > smb_conn - > connection - > msg_ctx ,
req - > smb_conn - > lp_ctx ,
remote_address ,
2017-03-01 06:28:06 +03:00
local_address ,
" SMB " ,
" bare-NTLM " ,
2017-03-06 04:10:17 +03:00
AUTHZ_TRANSPORT_PROTECTION_SMB ,
2023-06-15 08:07:05 +03:00
session_info ,
NULL /* client_audit_info */ ,
NULL /* server_audit_info */ ) ;
2017-03-01 06:28:06 +03:00
talloc_free ( frame ) ;
return ;
}
2003-08-13 05:53:07 +04:00
/*
setup the OS , Lanman and domain portions of a session setup reply
*/
2004-06-28 12:39:00 +04:00
static void sesssetup_common_strings ( struct smbsrv_request * req ,
2003-08-13 05:53:07 +04:00
char * * os , char * * lanman , char * * domain )
{
2004-09-08 09:39:06 +04:00
( * os ) = talloc_asprintf ( req , " Unix " ) ;
( * lanman ) = talloc_asprintf ( req , " Samba %s " , SAMBA_VERSION_STRING ) ;
2007-12-03 23:25:17 +03:00
( * domain ) = talloc_asprintf ( req , " %s " ,
2010-07-16 08:32:42 +04:00
lpcfg_workgroup ( req - > smb_conn - > lp_ctx ) ) ;
2003-08-13 05:53:07 +04:00
}
2006-07-27 23:07:15 +04:00
static void smbsrv_sesssetup_backend_send ( struct smbsrv_request * req ,
union smb_sesssetup * sess ,
NTSTATUS status )
{
if ( NT_STATUS_IS_OK ( status ) ) {
2007-10-07 02:10:49 +04:00
req - > smb_conn - > negotiate . done_sesssetup = true ;
2007-05-20 13:44:03 +04:00
/* we need to keep the session long term */
req - > session = talloc_steal ( req - > smb_conn , req - > session ) ;
2006-07-27 23:07:15 +04:00
}
smbsrv_reply_sesssetup_send ( req , sess , status ) ;
}
2009-12-23 11:09:37 +03:00
static void sesssetup_old_send ( struct tevent_req * subreq )
2006-07-27 23:07:15 +04:00
{
2010-04-13 06:00:06 +04:00
struct sesssetup_context * state = tevent_req_callback_data ( subreq , struct sesssetup_context ) ;
struct smbsrv_request * req = state - > req ;
2006-07-27 23:07:15 +04:00
union smb_sesssetup * sess = talloc_get_type ( req - > io_ptr , union smb_sesssetup ) ;
2011-02-08 08:53:13 +03:00
struct auth_user_info_dc * user_info_dc = NULL ;
2006-07-27 23:07:15 +04:00
struct auth_session_info * session_info ;
2007-05-20 12:57:01 +04:00
struct smbsrv_session * smb_sess ;
2006-07-27 23:07:15 +04:00
NTSTATUS status ;
2021-10-26 18:42:41 +03:00
uint8_t authoritative = 1 ;
2010-04-19 09:51:57 +04:00
uint32_t flags ;
2006-07-27 23:07:15 +04:00
2017-03-17 13:16:36 +03:00
status = auth_check_password_recv ( subreq , req , & user_info_dc ,
& authoritative ) ;
2009-12-23 11:09:37 +03:00
TALLOC_FREE ( subreq ) ;
2006-07-27 23:07:15 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) goto failed ;
2010-04-19 09:51:57 +04:00
flags = AUTH_SESSION_INFO_DEFAULT_GROUPS ;
2022-12-12 00:50:01 +03:00
if ( ! ( user_info_dc - > info - > user_flags & NETLOGON_GUEST ) ) {
2010-04-19 09:51:57 +04:00
flags | = AUTH_SESSION_INFO_AUTHENTICATED ;
}
2011-02-08 08:53:13 +03:00
/* This references user_info_dc into session_info */
2012-02-04 10:49:49 +04:00
status = req - > smb_conn - > negotiate . auth_context - > generate_session_info ( req - > smb_conn - > negotiate . auth_context ,
req ,
2012-01-30 14:49:33 +04:00
user_info_dc , sess - > old . in . user ,
flags , & session_info ) ;
2006-07-27 23:07:15 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) goto failed ;
/* allocate a new session */
2007-05-20 13:44:03 +04:00
smb_sess = smbsrv_session_new ( req - > smb_conn , req , NULL ) ;
2006-07-27 23:07:15 +04:00
if ( ! smb_sess ) {
status = NT_STATUS_INSUFFICIENT_RESOURCES ;
goto failed ;
}
2017-03-01 06:28:06 +03:00
smbsrv_not_spengo_sesssetup_authz_log ( req , session_info ) ;
2006-07-27 23:07:15 +04:00
/* Ensure this is marked as a 'real' vuid, not one
* simply valid for the session setup leg */
status = smbsrv_session_sesssetup_finished ( smb_sess , session_info ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) goto failed ;
/* To correctly process any AndX packet (like a tree connect)
* we need to fill in the session on the request here */
req - > session = smb_sess ;
sess - > old . out . vuid = smb_sess - > vuid ;
failed :
2011-03-03 03:05:33 +03:00
status = nt_status_squash ( status ) ;
2006-07-27 23:07:15 +04:00
smbsrv_sesssetup_backend_send ( req , sess , status ) ;
}
2003-08-13 05:53:07 +04:00
/*
handler for old style session setup
*/
2006-07-27 23:07:15 +04:00
static void sesssetup_old ( struct smbsrv_request * req , union smb_sesssetup * sess )
2003-08-13 05:53:07 +04:00
{
2004-06-05 05:39:08 +04:00
struct auth_usersupplied_info * user_info = NULL ;
2017-02-23 04:31:52 +03:00
struct tsocket_address * remote_address , * local_address ;
2005-07-22 08:10:07 +04:00
const char * remote_machine = NULL ;
2009-12-23 11:09:37 +03:00
struct tevent_req * subreq ;
2010-04-13 06:00:06 +04:00
struct sesssetup_context * state ;
2005-01-09 15:55:25 +03:00
2005-11-18 14:39:31 +03:00
sess - > old . out . vuid = 0 ;
2005-04-10 11:39:51 +04:00
sess - > old . out . action = 0 ;
2006-07-27 23:07:15 +04:00
sesssetup_common_strings ( req ,
& sess - > old . out . os ,
& sess - > old . out . lanman ,
& sess - > old . out . domain ) ;
2004-06-29 11:40:14 +04:00
if ( ! req - > smb_conn - > negotiate . done_sesssetup ) {
req - > smb_conn - > negotiate . max_send = sess - > old . in . bufsize ;
2003-08-13 05:53:07 +04:00
}
2006-07-27 23:07:15 +04:00
2005-10-13 02:25:51 +04:00
if ( req - > smb_conn - > negotiate . calling_name ) {
remote_machine = req - > smb_conn - > negotiate . calling_name - > name ;
2005-07-22 08:10:07 +04:00
}
2009-12-23 12:19:43 +03:00
remote_address = socket_get_remote_addr ( req - > smb_conn - > connection - > socket , req ) ;
2006-07-27 23:07:15 +04:00
if ( ! remote_address ) goto nomem ;
2006-01-10 01:12:53 +03:00
2005-07-22 08:10:07 +04:00
if ( ! remote_machine ) {
2009-12-23 12:19:43 +03:00
remote_machine = tsocket_address_inet_addr_string ( remote_address , req ) ;
if ( ! remote_machine ) goto nomem ;
2005-07-22 08:10:07 +04:00
}
2017-02-23 04:31:52 +03:00
local_address = socket_get_local_addr ( req - > smb_conn - > connection - > socket , req ) ;
if ( ! local_address ) goto nomem ;
2010-05-04 10:44:08 +04:00
user_info = talloc_zero ( req , struct auth_usersupplied_info ) ;
2006-07-27 23:07:15 +04:00
if ( ! user_info ) goto nomem ;
2017-02-20 04:52:07 +03:00
user_info - > service_description = " SMB " ;
2005-07-22 08:10:07 +04:00
2005-10-28 13:14:16 +04:00
user_info - > logon_parameters = 0 ;
2005-07-22 08:10:07 +04:00
user_info - > flags = 0 ;
user_info - > client . account_name = sess - > old . in . user ;
user_info - > client . domain_name = sess - > old . in . domain ;
user_info - > workstation_name = remote_machine ;
2017-02-23 04:31:52 +03:00
2006-01-10 01:12:53 +03:00
user_info - > remote_host = talloc_steal ( user_info , remote_address ) ;
2017-02-23 04:31:52 +03:00
user_info - > local_host = talloc_steal ( user_info , local_address ) ;
2005-07-22 08:10:07 +04:00
user_info - > password_state = AUTH_PASSWORD_RESPONSE ;
user_info - > password . response . lanman = sess - > old . in . password ;
user_info - > password . response . lanman . data = talloc_steal ( user_info , sess - > old . in . password . data ) ;
user_info - > password . response . nt = data_blob ( NULL , 0 ) ;
2003-08-13 05:53:07 +04:00
2010-04-13 06:00:06 +04:00
state = talloc ( req , struct sesssetup_context ) ;
if ( ! state ) goto nomem ;
if ( req - > smb_conn - > negotiate . auth_context ) {
state - > auth_context = req - > smb_conn - > negotiate . auth_context ;
} else {
/* TODO: should we use just "anonymous" here? */
NTSTATUS status = auth_context_create ( state ,
req - > smb_conn - > connection - > event . ctx ,
req - > smb_conn - > connection - > msg_ctx ,
req - > smb_conn - > lp_ctx ,
& state - > auth_context ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
smbsrv_sesssetup_backend_send ( req , sess , status ) ;
return ;
}
}
state - > req = req ;
subreq = auth_check_password_send ( state ,
2009-12-23 11:09:37 +03:00
req - > smb_conn - > connection - > event . ctx ,
req - > smb_conn - > negotiate . auth_context ,
user_info ) ;
if ( ! subreq ) goto nomem ;
2010-04-13 06:00:06 +04:00
tevent_req_set_callback ( subreq , sesssetup_old_send , state ) ;
2006-07-27 23:07:15 +04:00
return ;
nomem :
smbsrv_sesssetup_backend_send ( req , sess , NT_STATUS_NO_MEMORY ) ;
}
2009-12-23 11:09:37 +03:00
static void sesssetup_nt1_send ( struct tevent_req * subreq )
2006-07-27 23:07:15 +04:00
{
2010-04-13 06:00:06 +04:00
struct sesssetup_context * state = tevent_req_callback_data ( subreq , struct sesssetup_context ) ;
struct smbsrv_request * req = state - > req ;
2006-07-27 23:07:15 +04:00
union smb_sesssetup * sess = talloc_get_type ( req - > io_ptr , union smb_sesssetup ) ;
2011-02-08 08:53:13 +03:00
struct auth_user_info_dc * user_info_dc = NULL ;
2006-07-27 23:07:15 +04:00
struct auth_session_info * session_info ;
2007-05-20 12:57:01 +04:00
struct smbsrv_session * smb_sess ;
2021-10-26 18:42:41 +03:00
uint8_t authoritative = 1 ;
2010-04-19 09:51:57 +04:00
uint32_t flags ;
2006-07-27 23:07:15 +04:00
NTSTATUS status ;
2017-03-17 13:16:36 +03:00
status = auth_check_password_recv ( subreq , req , & user_info_dc ,
& authoritative ) ;
2009-12-23 11:09:37 +03:00
TALLOC_FREE ( subreq ) ;
2006-07-27 23:07:15 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) goto failed ;
2004-05-02 12:45:00 +04:00
2010-04-19 09:51:57 +04:00
flags = AUTH_SESSION_INFO_DEFAULT_GROUPS ;
2022-12-12 00:50:01 +03:00
if ( ! ( user_info_dc - > info - > user_flags & NETLOGON_GUEST ) ) {
2010-04-19 09:51:57 +04:00
flags | = AUTH_SESSION_INFO_AUTHENTICATED ;
}
2011-02-08 08:53:13 +03:00
/* This references user_info_dc into session_info */
2012-02-04 10:49:49 +04:00
status = state - > auth_context - > generate_session_info ( state - > auth_context ,
req ,
2011-02-08 08:53:13 +03:00
user_info_dc ,
2012-01-30 14:49:33 +04:00
sess - > nt1 . in . user ,
2010-04-19 09:51:57 +04:00
flags ,
2010-04-13 06:00:06 +04:00
& session_info ) ;
2006-07-27 23:07:15 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) goto failed ;
2003-08-13 05:53:07 +04:00
2005-11-18 15:57:48 +03:00
/* allocate a new session */
2007-05-20 13:44:03 +04:00
smb_sess = smbsrv_session_new ( req - > smb_conn , req , NULL ) ;
2005-04-10 11:39:51 +04:00
if ( ! smb_sess ) {
2006-07-27 23:07:15 +04:00
status = NT_STATUS_INSUFFICIENT_RESOURCES ;
goto failed ;
2004-07-05 11:29:14 +04:00
}
2005-04-10 11:39:51 +04:00
2017-03-01 06:28:06 +03:00
smbsrv_not_spengo_sesssetup_authz_log ( req , session_info ) ;
2005-04-10 11:39:51 +04:00
/* Ensure this is marked as a 'real' vuid, not one
* simply valid for the session setup leg */
2005-11-18 15:57:48 +03:00
status = smbsrv_session_sesssetup_finished ( smb_sess , session_info ) ;
2006-07-27 23:07:15 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) goto failed ;
2005-04-10 11:39:51 +04:00
/* To correctly process any AndX packet (like a tree connect)
* we need to fill in the session on the request here */
req - > session = smb_sess ;
2006-07-27 23:07:15 +04:00
sess - > nt1 . out . vuid = smb_sess - > vuid ;
2005-04-10 11:39:51 +04:00
2006-07-27 23:07:15 +04:00
if ( ! smbsrv_setup_signing ( req - > smb_conn , & session_info - > session_key , & sess - > nt1 . in . password2 ) ) {
/* Already signing, or disabled */
goto done ;
}
2003-08-13 05:53:07 +04:00
2006-07-27 23:07:15 +04:00
done :
status = NT_STATUS_OK ;
failed :
2011-03-03 03:05:33 +03:00
status = nt_status_squash ( status ) ;
2006-07-27 23:07:15 +04:00
smbsrv_sesssetup_backend_send ( req , sess , status ) ;
}
2003-08-13 05:53:07 +04:00
/*
handler for NT1 style session setup
*/
2006-07-27 23:07:15 +04:00
static void sesssetup_nt1 ( struct smbsrv_request * req , union smb_sesssetup * sess )
2003-08-13 05:53:07 +04:00
{
NTSTATUS status ;
2004-06-05 05:39:08 +04:00
struct auth_usersupplied_info * user_info = NULL ;
2017-02-23 04:31:52 +03:00
struct tsocket_address * remote_address , * local_address ;
2005-11-18 14:39:31 +03:00
const char * remote_machine = NULL ;
2009-12-23 11:09:37 +03:00
struct tevent_req * subreq ;
2010-04-13 06:00:06 +04:00
struct sesssetup_context * state ;
2016-03-01 12:25:54 +03:00
bool allow_raw = lpcfg_raw_ntlmv2_auth ( req - > smb_conn - > lp_ctx ) ;
2009-12-23 11:09:37 +03:00
2005-11-18 14:39:31 +03:00
sess - > nt1 . out . vuid = 0 ;
2005-04-10 11:39:51 +04:00
sess - > nt1 . out . action = 0 ;
2006-07-27 23:07:15 +04:00
sesssetup_common_strings ( req ,
& sess - > nt1 . out . os ,
& sess - > nt1 . out . lanman ,
& sess - > nt1 . out . domain ) ;
2004-06-29 11:40:14 +04:00
if ( ! req - > smb_conn - > negotiate . done_sesssetup ) {
req - > smb_conn - > negotiate . max_send = sess - > nt1 . in . bufsize ;
req - > smb_conn - > negotiate . client_caps = sess - > nt1 . in . capabilities ;
2003-08-13 05:53:07 +04:00
}
2010-04-13 06:00:06 +04:00
state = talloc ( req , struct sesssetup_context ) ;
if ( ! state ) goto nomem ;
state - > req = req ;
2006-02-09 06:04:48 +03:00
if ( req - > smb_conn - > negotiate . oid ) {
2004-08-12 10:58:10 +04:00
if ( sess - > nt1 . in . user & & * sess - > nt1 . in . user ) {
2005-07-22 08:10:07 +04:00
/* We can't accept a normal login, because we
* don ' t have a challenge */
2006-07-27 23:07:15 +04:00
status = NT_STATUS_LOGON_FAILURE ;
goto failed ;
2004-08-11 22:09:40 +04:00
}
2005-07-22 09:04:45 +04:00
/* TODO: should we use just "anonymous" here? */
2010-04-13 06:00:06 +04:00
status = auth_context_create ( state ,
2006-07-31 18:05:08 +04:00
req - > smb_conn - > connection - > event . ctx ,
req - > smb_conn - > connection - > msg_ctx ,
2007-12-03 23:25:17 +03:00
req - > smb_conn - > lp_ctx ,
2010-04-13 06:00:06 +04:00
& state - > auth_context ) ;
2006-07-27 23:07:15 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) goto failed ;
2010-04-13 06:00:06 +04:00
} else if ( req - > smb_conn - > negotiate . auth_context ) {
state - > auth_context = req - > smb_conn - > negotiate . auth_context ;
2005-07-22 09:04:45 +04:00
} else {
2010-04-13 06:00:06 +04:00
/* TODO: should we use just "anonymous" here? */
status = auth_context_create ( state ,
req - > smb_conn - > connection - > event . ctx ,
req - > smb_conn - > connection - > msg_ctx ,
req - > smb_conn - > lp_ctx ,
& state - > auth_context ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) goto failed ;
2003-08-13 05:53:07 +04:00
}
2005-10-13 02:25:51 +04:00
if ( req - > smb_conn - > negotiate . calling_name ) {
remote_machine = req - > smb_conn - > negotiate . calling_name - > name ;
2005-07-22 08:10:07 +04:00
}
2005-11-18 15:57:48 +03:00
2009-12-23 12:19:43 +03:00
remote_address = socket_get_remote_addr ( req - > smb_conn - > connection - > socket , req ) ;
2006-07-27 23:07:15 +04:00
if ( ! remote_address ) goto nomem ;
2006-01-10 01:12:53 +03:00
2005-07-22 08:10:07 +04:00
if ( ! remote_machine ) {
2009-12-23 12:19:43 +03:00
remote_machine = tsocket_address_inet_addr_string ( remote_address , req ) ;
if ( ! remote_machine ) goto nomem ;
2005-07-22 08:10:07 +04:00
}
2006-01-10 01:12:53 +03:00
2017-02-23 04:31:52 +03:00
local_address = socket_get_local_addr ( req - > smb_conn - > connection - > socket , req ) ;
if ( ! local_address ) goto nomem ;
2010-05-04 10:44:08 +04:00
user_info = talloc_zero ( req , struct auth_usersupplied_info ) ;
2006-07-27 23:07:15 +04:00
if ( ! user_info ) goto nomem ;
2017-02-20 04:52:07 +03:00
user_info - > service_description = " SMB " ;
2017-03-01 06:28:06 +03:00
user_info - > auth_description = " bare-NTLM " ;
2017-02-20 04:52:07 +03:00
2005-10-28 13:14:16 +04:00
user_info - > logon_parameters = 0 ;
2005-07-22 08:10:07 +04:00
user_info - > flags = 0 ;
user_info - > client . account_name = sess - > nt1 . in . user ;
user_info - > client . domain_name = sess - > nt1 . in . domain ;
user_info - > workstation_name = remote_machine ;
2006-01-10 01:12:53 +03:00
user_info - > remote_host = talloc_steal ( user_info , remote_address ) ;
2017-02-23 04:31:52 +03:00
user_info - > local_host = talloc_steal ( user_info , local_address ) ;
2005-07-22 08:10:07 +04:00
user_info - > password_state = AUTH_PASSWORD_RESPONSE ;
user_info - > password . response . lanman = sess - > nt1 . in . password1 ;
user_info - > password . response . lanman . data = talloc_steal ( user_info , sess - > nt1 . in . password1 . data ) ;
user_info - > password . response . nt = sess - > nt1 . in . password2 ;
user_info - > password . response . nt . data = talloc_steal ( user_info , sess - > nt1 . in . password2 . data ) ;
2016-03-01 12:25:54 +03:00
if ( ! allow_raw & & user_info - > password . response . nt . length > = 48 ) {
/*
* NTLMv2_RESPONSE has at least 48 bytes
* and should only be supported via NTLMSSP .
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto failed ;
}
2010-04-13 06:00:06 +04:00
subreq = auth_check_password_send ( state ,
2009-12-23 11:09:37 +03:00
req - > smb_conn - > connection - > event . ctx ,
2010-04-13 06:00:06 +04:00
state - > auth_context ,
2009-12-23 11:09:37 +03:00
user_info ) ;
if ( ! subreq ) goto nomem ;
2010-04-13 06:00:06 +04:00
tevent_req_set_callback ( subreq , sesssetup_nt1_send , state ) ;
2009-12-23 11:09:37 +03:00
2006-07-27 23:07:15 +04:00
return ;
2004-05-02 12:45:00 +04:00
2006-07-27 23:07:15 +04:00
nomem :
status = NT_STATUS_NO_MEMORY ;
failed :
2011-03-03 03:05:33 +03:00
status = nt_status_squash ( status ) ;
2006-07-27 23:07:15 +04:00
smbsrv_sesssetup_backend_send ( req , sess , status ) ;
}
2004-10-03 11:32:08 +04:00
2006-07-27 23:07:15 +04:00
struct sesssetup_spnego_state {
struct smbsrv_request * req ;
union smb_sesssetup * sess ;
struct smbsrv_session * smb_sess ;
} ;
2005-04-10 11:39:51 +04:00
2009-12-22 18:24:44 +03:00
static void sesssetup_spnego_send ( struct tevent_req * subreq )
2006-07-27 23:07:15 +04:00
{
2009-12-22 18:24:44 +03:00
struct sesssetup_spnego_state * s = tevent_req_callback_data ( subreq ,
2006-07-27 23:07:15 +04:00
struct sesssetup_spnego_state ) ;
struct smbsrv_request * req = s - > req ;
union smb_sesssetup * sess = s - > sess ;
struct smbsrv_session * smb_sess = s - > smb_sess ;
struct auth_session_info * session_info = NULL ;
NTSTATUS status ;
NTSTATUS skey_status ;
DATA_BLOB session_key ;
2005-04-10 11:39:51 +04:00
2009-12-22 18:24:44 +03:00
status = gensec_update_recv ( subreq , req , & sess - > spnego . out . secblob ) ;
2010-09-12 16:24:46 +04:00
packet_recv_enable ( req - > smb_conn - > packet ) ;
2009-12-22 18:24:44 +03:00
TALLOC_FREE ( subreq ) ;
2006-07-27 23:07:15 +04:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) {
goto done ;
} else if ( ! NT_STATUS_IS_OK ( status ) ) {
goto failed ;
}
2005-04-10 11:39:51 +04:00
2011-08-01 09:39:01 +04:00
status = gensec_session_info ( smb_sess - > gensec_ctx , smb_sess , & session_info ) ;
2006-07-27 23:07:15 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) goto failed ;
2005-11-18 14:39:31 +03:00
2011-08-01 09:39:01 +04:00
/* The session_key is only needed until the end of the smbsrv_setup_signing() call */
skey_status = gensec_session_key ( smb_sess - > gensec_ctx , req , & session_key ) ;
2008-09-23 04:30:15 +04:00
if ( NT_STATUS_IS_OK ( skey_status ) ) {
smbsrv_setup_signing ( req - > smb_conn , & session_key , NULL ) ;
2004-08-13 04:16:57 +04:00
}
2005-01-09 15:55:25 +03:00
2006-07-27 23:07:15 +04:00
/* Ensure this is marked as a 'real' vuid, not one
* simply valid for the session setup leg */
status = smbsrv_session_sesssetup_finished ( smb_sess , session_info ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) goto failed ;
2005-04-10 11:39:51 +04:00
2006-07-27 23:07:15 +04:00
req - > session = smb_sess ;
2004-08-10 08:56:44 +04:00
2006-07-27 23:07:15 +04:00
done :
sess - > spnego . out . vuid = smb_sess - > vuid ;
failed :
2011-03-03 03:05:33 +03:00
status = nt_status_squash ( status ) ;
2006-07-27 23:07:15 +04:00
smbsrv_sesssetup_backend_send ( req , sess , status ) ;
2007-05-20 13:44:03 +04:00
if ( ! NT_STATUS_IS_OK ( status ) & &
! NT_STATUS_EQUAL ( status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) {
talloc_free ( smb_sess ) ;
}
2003-08-13 05:53:07 +04:00
}
/*
handler for SPNEGO style session setup
*/
2006-07-27 23:07:15 +04:00
static void sesssetup_spnego ( struct smbsrv_request * req , union smb_sesssetup * sess )
2003-08-13 05:53:07 +04:00
{
2005-12-07 11:11:50 +03:00
NTSTATUS status ;
struct smbsrv_session * smb_sess = NULL ;
2013-11-08 19:14:35 +04:00
bool is_smb_sess_new = false ;
2006-07-27 23:07:15 +04:00
struct sesssetup_spnego_state * s = NULL ;
2004-08-11 22:09:40 +04:00
uint16_t vuid ;
2009-12-22 18:24:44 +03:00
struct tevent_req * subreq ;
2004-08-11 22:09:40 +04:00
2005-11-18 14:39:31 +03:00
sess - > spnego . out . vuid = 0 ;
2005-04-10 11:39:51 +04:00
sess - > spnego . out . action = 0 ;
sesssetup_common_strings ( req ,
& sess - > spnego . out . os ,
& sess - > spnego . out . lanman ,
& sess - > spnego . out . workgroup ) ;
2004-08-11 22:09:40 +04:00
if ( ! req - > smb_conn - > negotiate . done_sesssetup ) {
2006-07-27 18:19:51 +04:00
req - > smb_conn - > negotiate . max_send = sess - > spnego . in . bufsize ;
req - > smb_conn - > negotiate . client_caps = sess - > spnego . in . capabilities ;
2004-08-11 22:09:40 +04:00
}
vuid = SVAL ( req - > in . hdr , HDR_UID ) ;
2005-12-07 11:11:50 +03:00
/* lookup an existing session */
2012-05-06 23:09:47 +04:00
if ( vuid = = 0 ) {
2005-12-07 11:11:50 +03:00
struct gensec_security * gensec_ctx ;
2017-02-23 04:31:52 +03:00
struct tsocket_address * remote_address , * local_address ;
2009-02-13 02:24:16 +03:00
status = samba_server_gensec_start ( req ,
req - > smb_conn - > connection - > event . ctx ,
req - > smb_conn - > connection - > msg_ctx ,
req - > smb_conn - > lp_ctx ,
req - > smb_conn - > negotiate . server_credentials ,
" cifs " ,
& gensec_ctx ) ;
2004-08-11 22:09:40 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " Failed to start GENSEC server code: %s \n " , nt_errstr ( status ) ) ) ;
2006-07-27 23:07:15 +04:00
goto failed ;
2004-08-11 22:09:40 +04:00
}
2004-12-06 18:44:17 +03:00
gensec_want_feature ( gensec_ctx , GENSEC_FEATURE_SESSION_KEY ) ;
2017-03-06 04:10:17 +03:00
gensec_want_feature ( gensec_ctx , GENSEC_FEATURE_SMB_TRANSPORT ) ;
2004-08-25 06:25:20 +04:00
2017-02-23 04:31:52 +03:00
remote_address = socket_get_remote_addr ( req - > smb_conn - > connection - > socket ,
req ) ;
if ( ! remote_address ) {
status = NT_STATUS_INTERNAL_ERROR ;
2023-08-07 07:54:43 +03:00
DBG_ERR ( " Failed to obtain remote address \n " ) ;
2017-02-23 04:31:52 +03:00
goto failed ;
}
status = gensec_set_remote_address ( gensec_ctx ,
remote_address ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2023-08-07 07:54:43 +03:00
DBG_ERR ( " Failed to set remote address \n " ) ;
2017-02-23 04:31:52 +03:00
goto failed ;
}
local_address = socket_get_local_addr ( req - > smb_conn - > connection - > socket ,
req ) ;
if ( ! local_address ) {
status = NT_STATUS_INTERNAL_ERROR ;
2023-08-07 07:54:43 +03:00
DBG_ERR ( " Failed to obtain local address \n " ) ;
2017-02-23 04:31:52 +03:00
goto failed ;
}
status = gensec_set_local_address ( gensec_ctx ,
local_address ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2023-08-07 07:54:43 +03:00
DBG_ERR ( " Failed to set local address \n " ) ;
2017-02-23 04:31:52 +03:00
goto failed ;
}
status = gensec_set_target_service_description ( gensec_ctx ,
" SMB " ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2023-08-07 07:54:43 +03:00
DBG_ERR ( " Failed to set service description \n " ) ;
2017-02-23 04:31:52 +03:00
goto failed ;
}
2006-02-09 06:04:48 +03:00
status = gensec_start_mech_by_oid ( gensec_ctx , req - > smb_conn - > negotiate . oid ) ;
2004-08-11 22:09:40 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-02-09 06:04:48 +03:00
DEBUG ( 1 , ( " Failed to start GENSEC %s server code: %s \n " ,
2008-11-03 01:58:49 +03:00
gensec_get_name_by_oid ( gensec_ctx , req - > smb_conn - > negotiate . oid ) , nt_errstr ( status ) ) ) ;
2006-07-27 23:07:15 +04:00
goto failed ;
2004-08-11 22:09:40 +04:00
}
2005-12-07 11:11:50 +03:00
/* allocate a new session */
2007-05-20 13:44:03 +04:00
smb_sess = smbsrv_session_new ( req - > smb_conn , req - > smb_conn , gensec_ctx ) ;
2006-07-27 23:07:15 +04:00
if ( ! smb_sess ) {
status = NT_STATUS_INSUFFICIENT_RESOURCES ;
goto failed ;
}
2013-11-08 19:14:35 +04:00
is_smb_sess_new = true ;
2012-05-06 23:09:47 +04:00
} else {
smb_sess = smbsrv_session_find_sesssetup ( req - > smb_conn , vuid ) ;
2004-08-12 07:23:19 +04:00
}
2005-12-07 11:11:50 +03:00
if ( ! smb_sess ) {
2012-05-06 23:09:47 +04:00
status = NT_STATUS_DOS ( ERRSRV , ERRbaduid ) ;
goto failed ;
}
if ( smb_sess - > session_info ) {
status = NT_STATUS_INVALID_PARAMETER ;
2006-07-27 23:07:15 +04:00
goto failed ;
2005-12-07 11:11:50 +03:00
}
2005-04-10 11:39:51 +04:00
2005-12-07 11:11:50 +03:00
if ( ! smb_sess - > gensec_ctx ) {
status = NT_STATUS_INTERNAL_ERROR ;
DEBUG ( 1 , ( " Internal ERROR: no gensec_ctx on session: %s \n " , nt_errstr ( status ) ) ) ;
goto failed ;
}
2006-07-27 23:07:15 +04:00
s = talloc ( req , struct sesssetup_spnego_state ) ;
if ( ! s ) goto nomem ;
s - > req = req ;
s - > sess = sess ;
s - > smb_sess = smb_sess ;
2005-12-07 11:11:50 +03:00
2009-12-22 18:24:44 +03:00
subreq = gensec_update_send ( s ,
req - > smb_conn - > connection - > event . ctx ,
smb_sess - > gensec_ctx ,
sess - > spnego . in . secblob ) ;
if ( ! subreq ) {
goto nomem ;
}
2010-09-12 16:24:46 +04:00
/* disable receipt of more packets on this socket until we've
finished with the session setup . This avoids a problem with
crashes if we get EOF on the socket while processing a session
setup */
packet_recv_disable ( req - > smb_conn - > packet ) ;
2009-12-22 18:24:44 +03:00
tevent_req_set_callback ( subreq , sesssetup_spnego_send , s ) ;
2006-07-27 23:07:15 +04:00
return ;
2004-08-11 22:09:40 +04:00
2006-07-27 23:07:15 +04:00
nomem :
status = NT_STATUS_NO_MEMORY ;
2005-12-07 11:11:50 +03:00
failed :
2013-11-08 19:14:35 +04:00
if ( is_smb_sess_new ) {
talloc_free ( smb_sess ) ;
}
2011-03-03 03:05:33 +03:00
status = nt_status_squash ( status ) ;
2006-07-27 23:07:15 +04:00
smbsrv_sesssetup_backend_send ( req , sess , status ) ;
2003-08-13 05:53:07 +04:00
}
/*
2004-06-27 15:06:10 +04:00
backend for sessionsetup call - this takes all 3 variants of the call
2003-08-13 05:53:07 +04:00
*/
2006-07-27 23:07:15 +04:00
void smbsrv_sesssetup_backend ( struct smbsrv_request * req ,
union smb_sesssetup * sess )
2003-08-13 05:53:07 +04:00
{
2005-01-16 14:15:08 +03:00
switch ( sess - > old . level ) {
2003-08-13 05:53:07 +04:00
case RAW_SESSSETUP_OLD :
2006-07-27 23:07:15 +04:00
sesssetup_old ( req , sess ) ;
return ;
2003-08-13 05:53:07 +04:00
case RAW_SESSSETUP_NT1 :
2006-07-27 23:07:15 +04:00
sesssetup_nt1 ( req , sess ) ;
return ;
2003-08-13 05:53:07 +04:00
case RAW_SESSSETUP_SPNEGO :
2006-07-27 23:07:15 +04:00
sesssetup_spnego ( req , sess ) ;
return ;
2006-05-20 14:46:38 +04:00
case RAW_SESSSETUP_SMB2 :
break ;
2003-08-13 05:53:07 +04:00
}
2006-07-27 23:07:15 +04:00
smbsrv_sesssetup_backend_send ( req , sess , NT_STATUS_INVALID_LEVEL ) ;
2003-08-13 05:53:07 +04:00
}