2016-01-26 01:10:25 +01:00
/*
Unix SMB / CIFS implementation .
Copyright ( C ) Stefan Metzmacher 2014
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 3 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 , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
# include "system/filesys.h"
# include <tevent.h>
2017-01-01 20:00:55 +00:00
# include "lib/util/server_id.h"
2016-01-26 01:10:25 +01:00
# include "smbd/smbd.h"
# include "smbd/globals.h"
# include "dbwrap/dbwrap.h"
# include "dbwrap/dbwrap_rbt.h"
# include "dbwrap/dbwrap_open.h"
# include "dbwrap/dbwrap_watch.h"
# include "session.h"
# include "auth.h"
# include "auth/gensec/gensec.h"
# include "../lib/tsocket/tsocket.h"
# include "../libcli/security/security.h"
# include "messages.h"
# include "lib/util/util_tdb.h"
# include "librpc/gen_ndr/ndr_smbXsrv.h"
# include "serverid.h"
# include "lib/util/tevent_ntstatus.h"
# include "lib/util/iov_buf.h"
struct smbXsrv_client_table {
struct {
uint32_t max_clients ;
uint32_t num_clients ;
} local ;
struct {
struct db_context * db_ctx ;
} global ;
} ;
static struct db_context * smbXsrv_client_global_db_ctx = NULL ;
NTSTATUS smbXsrv_client_global_init ( void )
{
const char * global_path = NULL ;
struct db_context * db_ctx = NULL ;
if ( smbXsrv_client_global_db_ctx ! = NULL ) {
return NT_STATUS_OK ;
}
/*
* This contains secret information like client keys !
*/
global_path = lock_path ( " smbXsrv_client_global.tdb " ) ;
2016-02-03 09:10:46 +01:00
if ( global_path = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2016-01-26 01:10:25 +01:00
db_ctx = db_open ( NULL , global_path ,
0 , /* hash_size */
TDB_DEFAULT |
TDB_CLEAR_IF_FIRST |
TDB_INCOMPATIBLE_HASH ,
O_RDWR | O_CREAT , 0600 ,
DBWRAP_LOCK_ORDER_1 ,
DBWRAP_FLAG_NONE ) ;
if ( db_ctx = = NULL ) {
NTSTATUS status ;
status = map_nt_error_from_unix_common ( errno ) ;
return status ;
}
smbXsrv_client_global_db_ctx = db_ctx ;
return NT_STATUS_OK ;
}
/*
* NOTE :
* We need to store the keys in big endian so that dbwrap_rbt ' s memcmp
* has the same result as integer comparison between the uint32_t
* values .
*
* TODO : implement string based key
*/
# define SMBXSRV_CLIENT_GLOBAL_TDB_KEY_SIZE 16
static TDB_DATA smbXsrv_client_global_id_to_key ( const struct GUID * client_guid ,
uint8_t * key_buf )
{
TDB_DATA key = { . dsize = 0 , } ;
NTSTATUS status ;
DATA_BLOB b ;
status = GUID_to_ndr_blob ( client_guid , talloc_tos ( ) , & b ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return key ;
}
memcpy ( key_buf , b . data , SMBXSRV_CLIENT_GLOBAL_TDB_KEY_SIZE ) ;
data_blob_free ( & b ) ;
key = make_tdb_data ( key_buf , SMBXSRV_CLIENT_GLOBAL_TDB_KEY_SIZE ) ;
return key ;
}
2016-02-27 01:58:45 +01:00
static struct db_record * smbXsrv_client_global_fetch_locked (
struct db_context * db ,
const struct GUID * client_guid ,
TALLOC_CTX * mem_ctx )
{
TDB_DATA key ;
uint8_t key_buf [ SMBXSRV_CLIENT_GLOBAL_TDB_KEY_SIZE ] ;
struct db_record * rec = NULL ;
key = smbXsrv_client_global_id_to_key ( client_guid , key_buf ) ;
rec = dbwrap_fetch_locked ( db , mem_ctx , key ) ;
if ( rec = = NULL ) {
DBG_DEBUG ( " Failed to lock guid [%s], key '%s' \n " ,
GUID_string ( talloc_tos ( ) , client_guid ) ,
hex_encode_talloc ( talloc_tos ( ) , key . dptr , key . dsize ) ) ;
}
return rec ;
}
2016-01-26 01:10:25 +01:00
static NTSTATUS smbXsrv_client_table_create ( TALLOC_CTX * mem_ctx ,
struct messaging_context * msg_ctx ,
uint32_t max_clients ,
struct smbXsrv_client_table * * _table )
{
struct smbXsrv_client_table * table ;
NTSTATUS status ;
if ( max_clients > 1 ) {
return NT_STATUS_INTERNAL_ERROR ;
}
table = talloc_zero ( mem_ctx , struct smbXsrv_client_table ) ;
if ( table = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
table - > local . max_clients = max_clients ;
status = smbXsrv_client_global_init ( ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( table ) ;
return status ;
}
table - > global . db_ctx = smbXsrv_client_global_db_ctx ;
* _table = table ;
return NT_STATUS_OK ;
}
static int smbXsrv_client_global_destructor ( struct smbXsrv_client_global0 * global )
{
return 0 ;
}
static void smbXsrv_client_global_verify_record ( struct db_record * db_rec ,
bool * is_free ,
bool * was_free ,
TALLOC_CTX * mem_ctx ,
struct smbXsrv_client_global0 * * _g )
{
TDB_DATA key ;
TDB_DATA val ;
DATA_BLOB blob ;
struct smbXsrv_client_globalB global_blob ;
enum ndr_err_code ndr_err ;
struct smbXsrv_client_global0 * global = NULL ;
bool exists ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
* is_free = false ;
if ( was_free ) {
* was_free = false ;
}
if ( _g ) {
* _g = NULL ;
}
key = dbwrap_record_get_key ( db_rec ) ;
val = dbwrap_record_get_value ( db_rec ) ;
if ( val . dsize = = 0 ) {
TALLOC_FREE ( frame ) ;
* is_free = true ;
if ( was_free ) {
* was_free = true ;
}
return ;
}
blob = data_blob_const ( val . dptr , val . dsize ) ;
ndr_err = ndr_pull_struct_blob ( & blob , frame , & global_blob ,
( ndr_pull_flags_fn_t ) ndr_pull_smbXsrv_client_globalB ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
NTSTATUS status = ndr_map_error2ntstatus ( ndr_err ) ;
DBG_WARNING ( " smbXsrv_client_global_verify_record: "
" key '%s' ndr_pull_struct_blob - %s \n " ,
hex_encode_talloc ( frame , key . dptr , key . dsize ) ,
nt_errstr ( status ) ) ;
TALLOC_FREE ( frame ) ;
return ;
}
DBG_DEBUG ( " client_global: \n " ) ;
if ( DEBUGLVL ( DBGLVL_DEBUG ) ) {
NDR_PRINT_DEBUG ( smbXsrv_client_globalB , & global_blob ) ;
}
if ( global_blob . version ! = SMBXSRV_VERSION_0 ) {
DBG_ERR ( " key '%s' use unsupported version %u \n " ,
hex_encode_talloc ( frame , key . dptr , key . dsize ) ,
global_blob . version ) ;
NDR_PRINT_DEBUG ( smbXsrv_client_globalB , & global_blob ) ;
TALLOC_FREE ( frame ) ;
return ;
}
global = global_blob . info . info0 ;
exists = serverid_exists ( & global - > server_id ) ;
if ( ! exists ) {
struct server_id_buf tmp ;
DBG_NOTICE ( " key '%s' server_id %s does not exist. \n " ,
hex_encode_talloc ( frame , key . dptr , key . dsize ) ,
server_id_str_buf ( global - > server_id , & tmp ) ) ;
if ( DEBUGLVL ( DBGLVL_NOTICE ) ) {
NDR_PRINT_DEBUG ( smbXsrv_client_globalB , & global_blob ) ;
}
TALLOC_FREE ( frame ) ;
dbwrap_record_delete ( db_rec ) ;
* is_free = true ;
return ;
}
if ( _g ) {
* _g = talloc_move ( mem_ctx , & global ) ;
}
TALLOC_FREE ( frame ) ;
}
NTSTATUS smb2srv_client_lookup_global ( struct smbXsrv_client * client ,
struct GUID client_guid ,
TALLOC_CTX * mem_ctx ,
struct smbXsrv_client_global0 * * _global )
{
struct smbXsrv_client_table * table = client - > table ;
struct smbXsrv_client_global0 * global = NULL ;
bool is_free = false ;
struct db_record * db_rec ;
2016-02-27 01:58:45 +01:00
db_rec = smbXsrv_client_global_fetch_locked ( table - > global . db_ctx ,
& client_guid ,
talloc_tos ( ) ) ;
2016-01-26 01:10:25 +01:00
if ( db_rec = = NULL ) {
return NT_STATUS_INTERNAL_DB_ERROR ;
}
smbXsrv_client_global_verify_record ( db_rec ,
& is_free ,
NULL ,
mem_ctx ,
& global ) ;
TALLOC_FREE ( db_rec ) ;
if ( is_free ) {
return NT_STATUS_OBJECTID_NOT_FOUND ;
}
* _global = global ;
return NT_STATUS_OK ;
}
NTSTATUS smb2srv_client_connection_pass ( struct smbd_smb2_request * smb2req ,
struct smbXsrv_client_global0 * global )
{
DATA_BLOB blob ;
enum ndr_err_code ndr_err ;
NTSTATUS status ;
struct smbXsrv_connection_pass0 pass_info0 ;
struct smbXsrv_connection_passB pass_blob ;
2016-02-03 09:18:14 +01:00
ssize_t reqlen ;
2016-01-26 01:10:25 +01:00
struct iovec iov ;
pass_info0 . initial_connect_time = global - > initial_connect_time ;
pass_info0 . client_guid = global - > client_guid ;
2016-02-03 09:18:14 +01:00
reqlen = iov_buflen ( smb2req - > in . vector , smb2req - > in . vector_count ) ;
if ( reqlen = = - 1 ) {
return NT_STATUS_INVALID_BUFFER_SIZE ;
}
pass_info0 . negotiate_request . length = reqlen ;
2016-01-26 01:10:25 +01:00
pass_info0 . negotiate_request . data = talloc_array ( talloc_tos ( ) , uint8_t ,
2016-02-03 09:18:14 +01:00
reqlen ) ;
2016-01-26 01:10:25 +01:00
if ( pass_info0 . negotiate_request . data = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
iov_buf ( smb2req - > in . vector , smb2req - > in . vector_count ,
pass_info0 . negotiate_request . data ,
pass_info0 . negotiate_request . length ) ;
ZERO_STRUCT ( pass_blob ) ;
pass_blob . version = smbXsrv_version_global_current ( ) ;
pass_blob . info . info0 = & pass_info0 ;
if ( DEBUGLVL ( DBGLVL_DEBUG ) ) {
NDR_PRINT_DEBUG ( smbXsrv_connection_passB , & pass_blob ) ;
}
ndr_err = ndr_push_struct_blob ( & blob , talloc_tos ( ) , & pass_blob ,
( ndr_push_flags_fn_t ) ndr_push_smbXsrv_connection_passB ) ;
data_blob_free ( & pass_info0 . negotiate_request ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
status = ndr_map_error2ntstatus ( ndr_err ) ;
return status ;
}
iov . iov_base = blob . data ;
iov . iov_len = blob . length ;
status = messaging_send_iov ( smb2req - > xconn - > msg_ctx ,
global - > server_id ,
MSG_SMBXSRV_CONNECTION_PASS ,
& iov , 1 ,
& smb2req - > xconn - > transport . sock , 1 ) ;
data_blob_free ( & blob ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
return NT_STATUS_OK ;
}
static NTSTATUS smbXsrv_client_global_store ( struct smbXsrv_client_global0 * global )
{
struct smbXsrv_client_globalB global_blob ;
DATA_BLOB blob = data_blob_null ;
TDB_DATA key ;
TDB_DATA val ;
NTSTATUS status ;
enum ndr_err_code ndr_err ;
bool saved_stored = global - > stored ;
/*
* TODO : if we use other versions than ' 0 '
* we would add glue code here , that would be able to
* store the information in the old format .
*/
if ( global - > db_rec = = NULL ) {
return NT_STATUS_INTERNAL_ERROR ;
}
key = dbwrap_record_get_key ( global - > db_rec ) ;
val = dbwrap_record_get_value ( global - > db_rec ) ;
ZERO_STRUCT ( global_blob ) ;
global_blob . version = smbXsrv_version_global_current ( ) ;
if ( val . dsize > = 8 ) {
global_blob . seqnum = IVAL ( val . dptr , 4 ) ;
}
global_blob . seqnum + = 1 ;
global_blob . info . info0 = global ;
global - > stored = true ;
ndr_err = ndr_push_struct_blob ( & blob , global - > db_rec , & global_blob ,
( ndr_push_flags_fn_t ) ndr_push_smbXsrv_client_globalB ) ;
global - > stored = saved_stored ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
status = ndr_map_error2ntstatus ( ndr_err ) ;
DBG_WARNING ( " key '%s' ndr_push - %s \n " ,
hex_encode_talloc ( global - > db_rec , key . dptr , key . dsize ) ,
nt_errstr ( status ) ) ;
TALLOC_FREE ( global - > db_rec ) ;
return status ;
}
val = make_tdb_data ( blob . data , blob . length ) ;
status = dbwrap_record_store ( global - > db_rec , val , TDB_REPLACE ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_WARNING ( " key '%s' store - %s \n " ,
hex_encode_talloc ( global - > db_rec , key . dptr , key . dsize ) ,
nt_errstr ( status ) ) ;
TALLOC_FREE ( global - > db_rec ) ;
return status ;
}
global - > stored = true ;
if ( DEBUGLVL ( DBGLVL_DEBUG ) ) {
DBG_DEBUG ( " key '%s' stored \n " ,
hex_encode_talloc ( global - > db_rec , key . dptr , key . dsize ) ) ;
NDR_PRINT_DEBUG ( smbXsrv_client_globalB , & global_blob ) ;
}
TALLOC_FREE ( global - > db_rec ) ;
return NT_STATUS_OK ;
}
static NTSTATUS smbXsrv_client_global_remove ( struct smbXsrv_client_global0 * global )
{
TDB_DATA key ;
NTSTATUS status ;
/*
* TODO : if we use other versions than ' 0 '
* we would add glue code here , that would be able to
* store the information in the old format .
*/
if ( global - > db_rec = = NULL ) {
return NT_STATUS_INTERNAL_ERROR ;
}
key = dbwrap_record_get_key ( global - > db_rec ) ;
status = dbwrap_record_delete ( global - > db_rec ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_WARNING ( " key '%s' delete - %s \n " ,
hex_encode_talloc ( global - > db_rec , key . dptr , key . dsize ) ,
nt_errstr ( status ) ) ;
TALLOC_FREE ( global - > db_rec ) ;
return status ;
}
global - > stored = false ;
2016-03-01 20:40:47 +01:00
DBG_DEBUG ( " key '%s' delete \n " ,
hex_encode_talloc ( global - > db_rec , key . dptr , key . dsize ) ) ;
2016-01-26 01:10:25 +01:00
TALLOC_FREE ( global - > db_rec ) ;
return NT_STATUS_OK ;
}
static int smbXsrv_client_destructor ( struct smbXsrv_client * client )
{
NTSTATUS status ;
status = smbXsrv_client_remove ( client ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_ERR ( " smbXsrv_client_remove() failed: %s \n " ,
nt_errstr ( status ) ) ;
}
TALLOC_FREE ( client - > global ) ;
return 0 ;
}
static bool smbXsrv_client_connection_pass_filter ( struct messaging_rec * rec , void * private_data ) ;
static void smbXsrv_client_connection_pass_loop ( struct tevent_req * subreq ) ;
NTSTATUS smbXsrv_client_create ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
NTTIME now ,
struct smbXsrv_client * * _client )
{
struct smbXsrv_client_table * table ;
struct smbXsrv_client * client = NULL ;
struct smbXsrv_client_global0 * global = NULL ;
NTSTATUS status ;
struct tevent_req * subreq = NULL ;
status = smbXsrv_client_table_create ( mem_ctx ,
msg_ctx ,
1 , /* max_clients */
& table ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( table - > local . num_clients > = table - > local . max_clients ) {
TALLOC_FREE ( table ) ;
return NT_STATUS_INSUFFICIENT_RESOURCES ;
}
client = talloc_zero ( mem_ctx , struct smbXsrv_client ) ;
if ( client = = NULL ) {
TALLOC_FREE ( table ) ;
return NT_STATUS_NO_MEMORY ;
}
client - > ev_ctx = ev_ctx ;
client - > msg_ctx = msg_ctx ;
2016-01-26 08:16:51 +01:00
client - > server_multi_channel_enabled = lp_server_multi_channel_support ( ) ;
2016-01-26 01:10:25 +01:00
client - > table = talloc_move ( client , & table ) ;
table = client - > table ;
global = talloc_zero ( client , struct smbXsrv_client_global0 ) ;
if ( global = = NULL ) {
TALLOC_FREE ( client ) ;
return NT_STATUS_NO_MEMORY ;
}
talloc_set_destructor ( global , smbXsrv_client_global_destructor ) ;
client - > global = global ;
global - > initial_connect_time = now ;
global - > server_id = messaging_server_id ( client - > msg_ctx ) ;
table - > local . num_clients + = 1 ;
talloc_set_destructor ( client , smbXsrv_client_destructor ) ;
if ( DEBUGLVL ( DBGLVL_DEBUG ) ) {
struct smbXsrv_clientB client_blob ;
ZERO_STRUCT ( client_blob ) ;
client_blob . version = SMBXSRV_VERSION_0 ;
client_blob . info . info0 = client ;
DBG_DEBUG ( " client_guid[%s] stored \n " ,
GUID_string ( talloc_tos ( ) , & global - > client_guid ) ) ;
NDR_PRINT_DEBUG ( smbXsrv_clientB , & client_blob ) ;
}
subreq = messaging_filtered_read_send ( client , client - > ev_ctx , client - > msg_ctx ,
smbXsrv_client_connection_pass_filter ,
client ) ;
if ( subreq = = NULL ) {
TALLOC_FREE ( client ) ;
return NT_STATUS_NO_MEMORY ;
}
tevent_req_set_callback ( subreq , smbXsrv_client_connection_pass_loop , client ) ;
* _client = client ;
return NT_STATUS_OK ;
}
static bool smbXsrv_client_connection_pass_filter ( struct messaging_rec * rec , void * private_data )
{
if ( rec - > msg_type ! = MSG_SMBXSRV_CONNECTION_PASS ) {
return false ;
}
if ( rec - > num_fds ! = 1 ) {
return false ;
}
if ( rec - > buf . length < SMB2_HDR_BODY ) {
return false ;
}
/* TODO: verify client_guid...? */
return true ;
}
static void smbXsrv_client_connection_pass_loop ( struct tevent_req * subreq )
{
struct smbXsrv_client * client =
tevent_req_callback_data ( subreq ,
struct smbXsrv_client ) ;
struct smbXsrv_connection * xconn = NULL ;
int ret ;
struct messaging_rec * rec = NULL ;
struct smbXsrv_connection_passB pass_blob ;
enum ndr_err_code ndr_err ;
struct smbXsrv_connection_pass0 * pass_info0 = NULL ;
NTSTATUS status ;
int sock_fd = - 1 ;
uint64_t seq_low ;
ret = messaging_filtered_read_recv ( subreq , talloc_tos ( ) , & rec ) ;
TALLOC_FREE ( subreq ) ;
if ( ret ! = 0 ) {
goto next ;
}
ndr_err = ndr_pull_struct_blob ( & rec - > buf , rec , & pass_blob ,
( ndr_pull_flags_fn_t ) ndr_pull_smbXsrv_connection_passB ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
status = ndr_map_error2ntstatus ( ndr_err ) ;
DBG_WARNING ( " ndr_pull_struct_blob - %s \n " , nt_errstr ( status ) ) ;
goto next ;
}
DBG_DEBUG ( " MSG_SMBXSRV_CLIENT_CLOSE \n " ) ;
if ( DEBUGLVL ( DBGLVL_DEBUG ) ) {
NDR_PRINT_DEBUG ( smbXsrv_connection_passB , & pass_blob ) ;
}
if ( pass_blob . version ! = SMBXSRV_VERSION_0 ) {
DBG_ERR ( " ignore invalid version %u \n " , pass_blob . version ) ;
NDR_PRINT_DEBUG ( smbXsrv_connection_passB , & pass_blob ) ;
goto next ;
}
pass_info0 = pass_blob . info . info0 ;
if ( pass_info0 = = NULL ) {
DBG_ERR ( " ignore NULL info %u \n " , pass_blob . version ) ;
NDR_PRINT_DEBUG ( smbXsrv_connection_passB , & pass_blob ) ;
goto next ;
}
if ( ! GUID_equal ( & client - > global - > client_guid , & pass_info0 - > client_guid ) )
{
DBG_WARNING ( " client's client_guid [%s] != passed guid [%s] \n " ,
GUID_string ( talloc_tos ( ) , & client - > global - > client_guid ) ,
GUID_string ( talloc_tos ( ) , & pass_info0 - > client_guid ) ) ;
if ( DEBUGLVL ( DBGLVL_WARNING ) ) {
NDR_PRINT_DEBUG ( smbXsrv_connection_passB , & pass_blob ) ;
}
goto next ;
}
if ( client - > global - > initial_connect_time ! =
pass_info0 - > initial_connect_time )
{
DBG_WARNING ( " client's initial connect time [%s] (%llu) != "
" passed initial connect time [%s] (%llu) \n " ,
nt_time_string ( talloc_tos ( ) ,
client - > global - > initial_connect_time ) ,
( unsigned long long ) client - > global - > initial_connect_time ,
nt_time_string ( talloc_tos ( ) ,
pass_info0 - > initial_connect_time ) ,
( unsigned long long ) pass_info0 - > initial_connect_time ) ;
if ( DEBUGLVL ( DBGLVL_WARNING ) ) {
NDR_PRINT_DEBUG ( smbXsrv_connection_passB , & pass_blob ) ;
}
goto next ;
}
SMB_ASSERT ( rec - > num_fds = = 1 ) ;
sock_fd = rec - > fds [ 0 ] ;
DBG_ERR ( " got connection sockfd[%d] \n " , sock_fd ) ;
NDR_PRINT_DEBUG ( smbXsrv_connection_passB , & pass_blob ) ;
status = smbd_add_connection ( client , sock_fd , & xconn ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
close ( sock_fd ) ;
sock_fd = - 1 ;
DBG_ERR ( " smbd_add_connection => %s \n " , nt_errstr ( status ) ) ;
NDR_PRINT_DEBUG ( smbXsrv_connection_passB , & pass_blob ) ;
goto next ;
}
/*
* Set seq_low to mid received in negprot
*/
seq_low = BVAL ( pass_info0 - > negotiate_request . data ,
SMB2_HDR_MESSAGE_ID ) ;
xconn - > smb2 . client . guid_verified = true ;
smbd_smb2_process_negprot ( xconn , seq_low ,
pass_info0 - > negotiate_request . data ,
pass_info0 - > negotiate_request . length ) ;
next :
TALLOC_FREE ( rec ) ;
subreq = messaging_filtered_read_send ( client , client - > ev_ctx , client - > msg_ctx ,
smbXsrv_client_connection_pass_filter ,
client ) ;
if ( subreq = = NULL ) {
const char * r ;
r = " messaging_read_send(MSG_SMBXSRV_CONNECTION_PASS failed " ;
exit_server_cleanly ( r ) ;
return ;
}
tevent_req_set_callback ( subreq , smbXsrv_client_connection_pass_loop , client ) ;
}
NTSTATUS smbXsrv_client_update ( struct smbXsrv_client * client )
{
struct smbXsrv_client_table * table = client - > table ;
NTSTATUS status ;
if ( client - > global - > db_rec ! = NULL ) {
DBG_ERR ( " guid [%s]: Called with db_rec != NULL' \n " ,
GUID_string ( talloc_tos ( ) ,
& client - > global - > client_guid ) ) ;
return NT_STATUS_INTERNAL_ERROR ;
}
2016-02-27 01:58:45 +01:00
client - > global - > db_rec = smbXsrv_client_global_fetch_locked (
table - > global . db_ctx ,
& client - > global - > client_guid ,
client - > global /* TALLOC_CTX */ ) ;
2016-01-26 01:10:25 +01:00
if ( client - > global - > db_rec = = NULL ) {
return NT_STATUS_INTERNAL_DB_ERROR ;
}
status = smbXsrv_client_global_store ( client - > global ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_ERR ( " client_guid[%s] store failed - %s \n " ,
GUID_string ( talloc_tos ( ) , & client - > global - > client_guid ) ,
nt_errstr ( status ) ) ;
return status ;
}
if ( DEBUGLVL ( DBGLVL_DEBUG ) ) {
struct smbXsrv_clientB client_blob ;
ZERO_STRUCT ( client_blob ) ;
client_blob . version = SMBXSRV_VERSION_0 ;
client_blob . info . info0 = client ;
DBG_DEBUG ( " client_guid[%s] stored \n " ,
GUID_string ( talloc_tos ( ) , & client - > global - > client_guid ) ) ;
NDR_PRINT_DEBUG ( smbXsrv_clientB , & client_blob ) ;
}
return NT_STATUS_OK ;
}
NTSTATUS smbXsrv_client_remove ( struct smbXsrv_client * client )
{
struct smbXsrv_client_table * table = client - > table ;
NTSTATUS status ;
if ( client - > global - > db_rec ! = NULL ) {
DBG_ERR ( " client_guid[%s]: Called with db_rec != NULL' \n " ,
GUID_string ( talloc_tos ( ) , & client - > global - > client_guid ) ) ;
return NT_STATUS_INTERNAL_ERROR ;
}
if ( ! client - > global - > stored ) {
return NT_STATUS_OK ;
}
2016-02-27 01:58:45 +01:00
client - > global - > db_rec = smbXsrv_client_global_fetch_locked (
table - > global . db_ctx ,
& client - > global - > client_guid ,
client - > global /* TALLOC_CTX */ ) ;
2016-01-26 01:10:25 +01:00
if ( client - > global - > db_rec = = NULL ) {
return NT_STATUS_INTERNAL_DB_ERROR ;
}
status = smbXsrv_client_global_remove ( client - > global ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_ERR ( " client_guid[%s] store failed - %s \n " ,
GUID_string ( talloc_tos ( ) , & client - > global - > client_guid ) ,
nt_errstr ( status ) ) ;
return status ;
}
if ( DEBUGLVL ( DBGLVL_DEBUG ) ) {
struct smbXsrv_clientB client_blob ;
ZERO_STRUCT ( client_blob ) ;
client_blob . version = SMBXSRV_VERSION_0 ;
client_blob . info . info0 = client ;
DBG_DEBUG ( " client_guid[%s] stored \n " ,
GUID_string ( talloc_tos ( ) , & client - > global - > client_guid ) ) ;
NDR_PRINT_DEBUG ( smbXsrv_clientB , & client_blob ) ;
}
return NT_STATUS_OK ;
}