2005-11-12 05:12:51 +03:00
/*
Unix SMB / CIFS implementation .
SMB2 composite connection setup
Copyright ( C ) Andrew Tridgell 2005
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
2005-11-12 05:12:51 +03: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/>.
2005-11-12 05:12:51 +03:00
*/
# include "includes.h"
# include "libcli/raw/libcliraw.h"
# include "libcli/smb2/smb2.h"
# include "libcli/smb2/smb2_calls.h"
# include "libcli/composite/composite.h"
2006-03-07 14:07:23 +03:00
# include "libcli/resolve/resolve.h"
2007-09-08 16:42:09 +04:00
# include "param/param.h"
2005-11-12 05:12:51 +03:00
struct smb2_connect_state {
struct cli_credentials * credentials ;
const char * host ;
const char * share ;
struct smb2_negprot negprot ;
struct smb2_tree_connect tcon ;
struct smb2_session * session ;
struct smb2_tree * tree ;
} ;
/*
continue after tcon reply
*/
static void continue_tcon ( struct smb2_request * req )
{
struct composite_context * c = talloc_get_type ( req - > async . private ,
struct composite_context ) ;
struct smb2_connect_state * state = talloc_get_type ( c - > private_data ,
struct smb2_connect_state ) ;
c - > status = smb2_tree_connect_recv ( req , & state - > tcon ) ;
2005-11-19 02:48:51 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2005-11-12 05:12:51 +03:00
state - > tree - > tid = state - > tcon . out . tid ;
composite_done ( c ) ;
}
/*
continue after a session setup
*/
static void continue_session ( struct composite_context * creq )
{
struct composite_context * c = talloc_get_type ( creq - > async . private_data ,
struct composite_context ) ;
struct smb2_connect_state * state = talloc_get_type ( c - > private_data ,
struct smb2_connect_state ) ;
2005-11-19 02:15:32 +03:00
struct smb2_request * req ;
2005-11-12 05:12:51 +03:00
c - > status = smb2_session_setup_spnego_recv ( creq ) ;
2005-11-19 02:48:51 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2005-11-12 05:12:51 +03:00
state - > tree = smb2_tree_init ( state - > session , state , True ) ;
2005-11-19 02:34:47 +03:00
if ( composite_nomem ( state - > tree , c ) ) return ;
2005-11-12 05:12:51 +03:00
state - > tcon . in . unknown1 = 0x09 ;
state - > tcon . in . path = talloc_asprintf ( state , " \\ \\ %s \\ %s " ,
state - > host , state - > share ) ;
2005-11-19 02:34:47 +03:00
if ( composite_nomem ( state - > tcon . in . path , c ) ) return ;
2005-11-12 05:12:51 +03:00
2005-11-19 02:15:32 +03:00
req = smb2_tree_connect_send ( state - > tree , & state - > tcon ) ;
2005-11-19 02:34:47 +03:00
if ( composite_nomem ( req , c ) ) return ;
2005-11-12 05:12:51 +03:00
2005-11-19 02:15:32 +03:00
req - > async . fn = continue_tcon ;
req - > async . private = c ;
2005-11-12 05:12:51 +03:00
}
/*
continue after negprot reply
*/
static void continue_negprot ( struct smb2_request * req )
{
struct composite_context * c = talloc_get_type ( req - > async . private ,
struct composite_context ) ;
struct smb2_connect_state * state = talloc_get_type ( c - > private_data ,
struct smb2_connect_state ) ;
struct smb2_transport * transport = req - > transport ;
2005-11-19 02:15:32 +03:00
struct composite_context * creq ;
2005-11-12 05:12:51 +03:00
c - > status = smb2_negprot_recv ( req , c , & state - > negprot ) ;
2005-11-19 02:48:51 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2005-11-12 05:12:51 +03:00
state - > session = smb2_session_init ( transport , state , True ) ;
2005-11-19 02:34:47 +03:00
if ( composite_nomem ( state - > session , c ) ) return ;
2005-11-12 05:12:51 +03:00
2005-11-19 02:15:32 +03:00
creq = smb2_session_setup_spnego_send ( state - > session , state - > credentials ) ;
2005-11-12 05:12:51 +03:00
2005-11-19 02:34:47 +03:00
composite_continue ( c , creq , continue_session , c ) ;
2005-11-12 05:12:51 +03:00
}
/*
continue after a socket connect completes
*/
static void continue_socket ( struct composite_context * creq )
{
struct composite_context * c = talloc_get_type ( creq - > async . private_data ,
struct composite_context ) ;
struct smb2_connect_state * state = talloc_get_type ( c - > private_data ,
struct smb2_connect_state ) ;
struct smbcli_socket * sock ;
struct smb2_transport * transport ;
2005-11-19 02:15:32 +03:00
struct smb2_request * req ;
2005-11-12 05:12:51 +03:00
c - > status = smbcli_sock_connect_recv ( creq , state , & sock ) ;
2005-11-19 02:48:51 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2005-11-12 05:12:51 +03:00
transport = smb2_transport_init ( sock , state ) ;
2005-11-19 02:34:47 +03:00
if ( composite_nomem ( transport , c ) ) return ;
2005-11-12 05:12:51 +03:00
ZERO_STRUCT ( state - > negprot ) ;
2005-11-16 14:01:15 +03:00
state - > negprot . in . unknown1 = 0x0001 ;
2005-11-19 02:15:32 +03:00
req = smb2_negprot_send ( transport , & state - > negprot ) ;
2005-11-19 02:34:47 +03:00
if ( composite_nomem ( req , c ) ) return ;
2005-11-12 05:12:51 +03:00
2005-11-19 02:15:32 +03:00
req - > async . fn = continue_negprot ;
req - > async . private = c ;
2005-11-12 05:12:51 +03:00
}
/*
continue after a resolve finishes
*/
static void continue_resolve ( struct composite_context * creq )
{
struct composite_context * c = talloc_get_type ( creq - > async . private_data ,
struct composite_context ) ;
struct smb2_connect_state * state = talloc_get_type ( c - > private_data ,
struct smb2_connect_state ) ;
const char * addr ;
c - > status = resolve_name_recv ( creq , state , & addr ) ;
2005-11-19 02:48:51 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2005-11-12 05:12:51 +03:00
2005-11-19 02:15:32 +03:00
creq = smbcli_sock_connect_send ( state , addr , 445 , state - > host , c - > event_ctx ) ;
2005-11-12 05:12:51 +03:00
2005-11-19 02:34:47 +03:00
composite_continue ( c , creq , continue_socket , c ) ;
2005-11-12 05:12:51 +03:00
}
/*
a composite function that does a full negprot / sesssetup / tcon , returning
a connected smb2_tree
*/
struct composite_context * smb2_connect_send ( TALLOC_CTX * mem_ctx ,
const char * host ,
const char * share ,
struct cli_credentials * credentials ,
struct event_context * ev )
{
struct composite_context * c ;
struct smb2_connect_state * state ;
struct nbt_name name ;
2005-11-19 02:15:32 +03:00
struct composite_context * creq ;
2005-11-12 05:12:51 +03:00
2006-07-30 21:29:02 +04:00
c = composite_create ( mem_ctx , ev ) ;
2005-11-12 05:12:51 +03:00
if ( c = = NULL ) return NULL ;
state = talloc ( c , struct smb2_connect_state ) ;
2006-07-30 21:29:02 +04:00
if ( composite_nomem ( state , c ) ) return c ;
2005-11-12 05:12:51 +03:00
c - > private_data = state ;
state - > credentials = credentials ;
state - > host = talloc_strdup ( c , host ) ;
2006-07-30 21:29:02 +04:00
if ( composite_nomem ( state - > host , c ) ) return c ;
2005-11-12 05:12:51 +03:00
state - > share = talloc_strdup ( c , share ) ;
2006-07-30 21:29:02 +04:00
if ( composite_nomem ( state - > share , c ) ) return c ;
2005-11-12 05:12:51 +03:00
ZERO_STRUCT ( name ) ;
name . name = host ;
2007-10-01 22:52:55 +04:00
creq = resolve_name_send ( & name , c - > event_ctx ,
lp_name_resolve_order ( global_loadparm ) ) ;
2005-11-19 02:34:47 +03:00
composite_continue ( c , creq , continue_resolve , c ) ;
2005-11-12 05:12:51 +03:00
return c ;
}
/*
receive a connect reply
*/
NTSTATUS smb2_connect_recv ( struct composite_context * c , TALLOC_CTX * mem_ctx ,
struct smb2_tree * * tree )
{
NTSTATUS status ;
struct smb2_connect_state * state = talloc_get_type ( c - > private_data ,
struct smb2_connect_state ) ;
status = composite_wait ( c ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
* tree = talloc_steal ( mem_ctx , state - > tree ) ;
}
talloc_free ( c ) ;
return status ;
}
/*
sync version of smb2_connect
*/
NTSTATUS smb2_connect ( TALLOC_CTX * mem_ctx ,
const char * host , const char * share ,
struct cli_credentials * credentials ,
struct smb2_tree * * tree ,
struct event_context * ev )
{
struct composite_context * c = smb2_connect_send ( mem_ctx , host , share ,
credentials , ev ) ;
return smb2_connect_recv ( c , mem_ctx , tree ) ;
}