2005-12-06 11:56:13 +03:00
/*
Unix SMB / CIFS implementation .
dcerpc connect functions
Copyright ( C ) Andrew Tridgell 2003
Copyright ( C ) Jelmer Vernooij 2004
2007-07-16 15:27:29 +04:00
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2005 - 2007
2005-12-06 11:56:13 +03:00
Copyright ( C ) Rafal Szczesniak 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-12-06 11:56:13 +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-12-06 11:56:13 +03:00
*/
# include "includes.h"
# include "libcli/composite/composite.h"
# include "libcli/smb_composite/smb_composite.h"
2006-05-04 14:03:41 +04:00
# include "lib/events/events.h"
2005-12-28 18:38:36 +03:00
# include "libcli/smb2/smb2.h"
2006-01-03 20:27:33 +03:00
# include "libcli/smb2/smb2_calls.h"
2006-03-18 18:42:57 +03:00
# include "librpc/rpc/dcerpc.h"
2006-05-04 21:39:35 +04:00
# include "auth/credentials/credentials.h"
2007-09-08 16:42:09 +04:00
# include "param/param.h"
2007-12-10 20:41:19 +03:00
# include "libcli/resolve/resolve.h"
2005-12-06 11:56:13 +03:00
struct pipe_np_smb_state {
struct smb_composite_connect conn ;
struct smbcli_tree * tree ;
struct dcerpc_pipe_connect io ;
} ;
2005-12-06 22:44:49 +03:00
/*
2005-12-10 13:10:44 +03:00
Stage 3 of ncacn_np_smb : Named pipe opened ( or not )
2005-12-06 22:44:49 +03:00
*/
2006-03-10 02:21:49 +03:00
static void continue_pipe_open_smb ( struct composite_context * ctx )
2005-12-06 11:56:13 +03:00
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
2005-12-10 13:10:44 +03:00
/* receive result of named pipe open request on smb */
2005-12-06 11:56:13 +03:00
c - > status = dcerpc_pipe_open_smb_recv ( ctx ) ;
2006-03-10 23:08:15 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2005-12-06 11:56:13 +03:00
composite_done ( c ) ;
}
2006-05-04 21:39:35 +04:00
2005-12-06 22:44:49 +03:00
/*
Stage 2 of ncacn_np_smb : Open a named pipe after successful smb connection
*/
2006-03-10 02:21:49 +03:00
static void continue_smb_connect ( struct composite_context * ctx )
2005-12-06 11:56:13 +03:00
{
struct composite_context * open_ctx ;
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
struct pipe_np_smb_state * s = talloc_get_type ( c - > private_data ,
struct pipe_np_smb_state ) ;
2005-12-06 22:44:49 +03:00
/* receive result of smb connect request */
2005-12-06 11:56:13 +03:00
c - > status = smb_composite_connect_recv ( ctx , c ) ;
2006-03-10 23:08:15 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2005-12-06 11:56:13 +03:00
2005-12-06 22:44:49 +03:00
/* prepare named pipe open parameters */
2005-12-06 11:56:13 +03:00
s - > tree = s - > conn . out . tree ;
s - > io . pipe_name = s - > io . binding - > endpoint ;
2005-12-06 22:44:49 +03:00
/* send named pipe open request */
2007-02-26 08:37:19 +03:00
open_ctx = dcerpc_pipe_open_smb_send ( s - > io . pipe , s - > tree , s - > io . pipe_name ) ;
2006-03-10 02:21:49 +03:00
if ( composite_nomem ( open_ctx , c ) ) return ;
2005-12-06 11:56:13 +03:00
composite_continue ( c , open_ctx , continue_pipe_open_smb , c ) ;
}
2005-12-06 22:44:49 +03:00
/*
Initiate async open of a rpc connection to a rpc pipe on SMB using
the binding structure to determine the endpoint and options
*/
2008-01-03 00:00:58 +03:00
static struct composite_context * dcerpc_pipe_connect_ncacn_np_smb_send ( TALLOC_CTX * mem_ctx , struct dcerpc_pipe_connect * io , struct loadparm_context * lp_ctx )
2005-12-06 11:56:13 +03:00
{
struct composite_context * c ;
struct pipe_np_smb_state * s ;
struct composite_context * conn_req ;
struct smb_composite_connect * conn ;
2005-12-06 22:44:49 +03:00
/* composite context allocation and setup */
2006-07-30 22:24:07 +04:00
c = composite_create ( mem_ctx , io - > pipe - > conn - > event_ctx ) ;
2005-12-06 11:56:13 +03:00
if ( c = = NULL ) return NULL ;
2005-12-06 14:52:16 +03:00
s = talloc_zero ( c , struct pipe_np_smb_state ) ;
2006-03-10 02:21:49 +03:00
if ( composite_nomem ( s , c ) ) return c ;
2005-12-06 20:42:04 +03:00
c - > private_data = s ;
2005-12-06 11:56:13 +03:00
s - > io = * io ;
conn = & s - > conn ;
2005-12-06 22:44:49 +03:00
/* prepare smb connection parameters: we're connecting to IPC$ share on
remote rpc server */
2005-12-06 11:56:13 +03:00
conn - > in . dest_host = s - > io . binding - > host ;
2008-01-03 00:00:58 +03:00
conn - > in . dest_ports = lp_smb_ports ( lp_ctx ) ;
2007-09-03 17:13:25 +04:00
if ( s - > io . binding - > target_hostname = = NULL )
2007-09-07 15:47:03 +04:00
conn - > in . called_name = " *SMBSERVER " ; /* FIXME: This is invalid */
2007-09-03 17:13:25 +04:00
else
conn - > in . called_name = s - > io . binding - > target_hostname ;
2005-12-06 11:56:13 +03:00
conn - > in . service = " IPC$ " ;
conn - > in . service_type = NULL ;
2008-01-03 00:00:58 +03:00
conn - > in . workgroup = lp_workgroup ( lp_ctx ) ;
2005-12-06 11:56:13 +03:00
2005-12-06 22:44:49 +03:00
/*
2006-01-12 12:33:49 +03:00
* provide proper credentials - user supplied , but allow a
* fallback to anonymous if this is an schannel connection
* ( might be NT4 not allowing machine logins at session
* setup ) .
2005-12-06 22:44:49 +03:00
*/
2006-01-12 12:33:49 +03:00
s - > conn . in . credentials = s - > io . creds ;
2005-12-06 11:56:13 +03:00
if ( s - > io . binding - > flags & DCERPC_SCHANNEL ) {
2007-09-25 20:05:08 +04:00
conn - > in . fallback_to_anonymous = true ;
2005-12-06 11:56:13 +03:00
} else {
2007-09-25 20:05:08 +04:00
conn - > in . fallback_to_anonymous = false ;
2005-12-06 11:56:13 +03:00
}
2005-12-06 22:44:49 +03:00
/* send smb connect request */
2008-01-03 03:39:01 +03:00
conn_req = smb_composite_connect_send ( conn , s - > io . pipe - > conn ,
lp_resolve_context ( lp_ctx ) ,
s - > io . pipe - > conn - > event_ctx ) ;
2006-03-10 02:21:49 +03:00
if ( composite_nomem ( conn_req , c ) ) return c ;
2005-12-06 11:56:13 +03:00
composite_continue ( c , conn_req , continue_smb_connect , c ) ;
2005-12-06 14:11:11 +03:00
return c ;
2005-12-06 11:56:13 +03:00
}
2005-12-06 22:44:49 +03:00
/*
Receive result of a rpc connection to a rpc pipe on SMB
*/
2006-10-24 11:56:59 +04:00
static NTSTATUS dcerpc_pipe_connect_ncacn_np_smb_recv ( struct composite_context * c )
2005-12-06 11:56:13 +03:00
{
NTSTATUS status = composite_wait ( c ) ;
talloc_free ( c ) ;
return status ;
}
2005-12-09 03:04:38 +03:00
struct pipe_np_smb2_state {
struct smb2_tree * tree ;
struct dcerpc_pipe_connect io ;
} ;
2005-12-10 13:10:44 +03:00
/*
Stage 3 of ncacn_np_smb : Named pipe opened ( or not )
*/
2006-03-10 02:21:49 +03:00
static void continue_pipe_open_smb2 ( struct composite_context * ctx )
2005-12-09 03:04:38 +03:00
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
2005-12-10 13:10:44 +03:00
/* receive result of named pipe open request on smb2 */
2005-12-09 03:04:38 +03:00
c - > status = dcerpc_pipe_open_smb2_recv ( ctx ) ;
2006-03-10 23:08:15 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2005-12-09 03:04:38 +03:00
composite_done ( c ) ;
}
2005-12-10 13:10:44 +03:00
/*
Stage 2 of ncacn_np_smb2 : Open a named pipe after successful smb2 connection
*/
2006-03-10 02:21:49 +03:00
static void continue_smb2_connect ( struct composite_context * ctx )
2005-12-09 03:04:38 +03:00
{
struct composite_context * open_req ;
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
struct pipe_np_smb2_state * s = talloc_get_type ( c - > private_data ,
struct pipe_np_smb2_state ) ;
2005-12-10 13:10:44 +03:00
/* receive result of smb2 connect request */
2005-12-09 03:04:38 +03:00
c - > status = smb2_connect_recv ( ctx , c , & s - > tree ) ;
2006-03-10 23:08:15 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2005-12-10 13:10:44 +03:00
/* prepare named pipe open parameters */
2005-12-09 03:04:38 +03:00
s - > io . pipe_name = s - > io . binding - > endpoint ;
2005-12-10 13:10:44 +03:00
/* send named pipe open request */
2007-02-26 08:37:19 +03:00
open_req = dcerpc_pipe_open_smb2_send ( s - > io . pipe , s - > tree , s - > io . pipe_name ) ;
2006-03-10 02:21:49 +03:00
if ( composite_nomem ( open_req , c ) ) return ;
2005-12-09 03:04:38 +03:00
composite_continue ( c , open_req , continue_pipe_open_smb2 , c ) ;
}
2005-12-10 13:10:44 +03:00
/*
Initiate async open of a rpc connection request on SMB2 using
the binding structure to determine the endpoint and options
*/
2007-12-04 03:51:36 +03:00
static struct composite_context * dcerpc_pipe_connect_ncacn_np_smb2_send (
TALLOC_CTX * mem_ctx ,
2008-01-03 00:00:58 +03:00
struct dcerpc_pipe_connect * io ,
struct loadparm_context * lp_ctx )
2005-12-09 03:04:38 +03:00
{
struct composite_context * c ;
struct pipe_np_smb2_state * s ;
struct composite_context * conn_req ;
2005-12-10 13:10:44 +03:00
/* composite context allocation and setup */
2006-07-30 22:24:07 +04:00
c = composite_create ( mem_ctx , io - > pipe - > conn - > event_ctx ) ;
2005-12-09 03:04:38 +03:00
if ( c = = NULL ) return NULL ;
s = talloc_zero ( c , struct pipe_np_smb2_state ) ;
2006-03-10 02:21:49 +03:00
if ( composite_nomem ( s , c ) ) return c ;
2005-12-09 03:04:38 +03:00
c - > private_data = s ;
s - > io = * io ;
2005-12-10 13:10:44 +03:00
/*
* provide proper credentials - user supplied or anonymous in case this is
* schannel connection
*/
2005-12-09 03:04:38 +03:00
if ( s - > io . binding - > flags & DCERPC_SCHANNEL ) {
s - > io . creds = cli_credentials_init ( mem_ctx ) ;
2006-03-10 02:21:49 +03:00
if ( composite_nomem ( s - > io . creds , c ) ) return c ;
2005-12-09 03:04:38 +03:00
2008-01-03 00:00:58 +03:00
cli_credentials_guess ( s - > io . creds , lp_ctx ) ;
2005-12-09 03:04:38 +03:00
}
2005-12-10 13:10:44 +03:00
/* send smb2 connect request */
2007-12-03 23:25:06 +03:00
conn_req = smb2_connect_send ( mem_ctx , s - > io . binding - > host , " IPC$ " ,
2007-12-10 20:41:19 +03:00
s - > io . resolve_ctx ,
2007-12-03 23:25:06 +03:00
s - > io . creds ,
2005-12-09 03:04:38 +03:00
c - > event_ctx ) ;
composite_continue ( c , conn_req , continue_smb2_connect , c ) ;
return c ;
}
2005-12-10 13:10:44 +03:00
/*
Receive result of a rpc connection to a rpc pipe on SMB2
*/
2006-10-24 11:56:59 +04:00
static NTSTATUS dcerpc_pipe_connect_ncacn_np_smb2_recv ( struct composite_context * c )
2005-12-09 03:04:38 +03:00
{
NTSTATUS status = composite_wait ( c ) ;
talloc_free ( c ) ;
return status ;
}
2006-02-19 19:58:48 +03:00
struct pipe_ip_tcp_state {
struct dcerpc_pipe_connect io ;
const char * host ;
2006-10-13 17:01:48 +04:00
const char * target_hostname ;
2006-02-19 19:58:48 +03:00
uint32_t port ;
} ;
2006-02-20 20:30:15 +03:00
/*
Stage 2 of ncacn_ip_tcp : rpc pipe opened ( or not )
*/
2006-03-10 02:21:49 +03:00
static void continue_pipe_open_ncacn_ip_tcp ( struct composite_context * ctx )
2006-02-19 19:58:48 +03:00
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
2006-02-20 20:30:15 +03:00
/* receive result of named pipe open request on tcp/ip */
2006-02-19 19:58:48 +03:00
c - > status = dcerpc_pipe_open_tcp_recv ( ctx ) ;
2006-03-10 23:08:15 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2006-02-19 19:58:48 +03:00
composite_done ( c ) ;
}
2006-02-20 20:30:15 +03:00
/*
Initiate async open of a rpc connection to a rpc pipe on TCP / IP using
the binding structure to determine the endpoint and options
*/
2006-10-24 11:56:59 +04:00
static struct composite_context * dcerpc_pipe_connect_ncacn_ip_tcp_send ( TALLOC_CTX * mem_ctx ,
struct dcerpc_pipe_connect * io )
2006-02-19 19:58:48 +03:00
{
struct composite_context * c ;
struct pipe_ip_tcp_state * s ;
struct composite_context * pipe_req ;
/* composite context allocation and setup */
2006-07-30 22:24:07 +04:00
c = composite_create ( mem_ctx , io - > pipe - > conn - > event_ctx ) ;
2006-02-19 19:58:48 +03:00
if ( c = = NULL ) return NULL ;
s = talloc_zero ( c , struct pipe_ip_tcp_state ) ;
2006-03-10 02:21:49 +03:00
if ( composite_nomem ( s , c ) ) return c ;
2006-02-19 19:58:48 +03:00
c - > private_data = s ;
2006-02-20 20:30:15 +03:00
/* store input parameters in state structure */
2006-10-13 17:01:48 +04:00
s - > io = * io ;
s - > host = talloc_reference ( c , io - > binding - > host ) ;
s - > target_hostname = talloc_reference ( c , io - > binding - > target_hostname ) ;
/* port number is a binding endpoint here */
s - > port = atoi ( io - > binding - > endpoint ) ;
2006-02-19 19:58:48 +03:00
2006-02-20 20:30:15 +03:00
/* send pipe open request on tcp/ip */
2006-10-13 17:01:48 +04:00
pipe_req = dcerpc_pipe_open_tcp_send ( s - > io . pipe - > conn , s - > host , s - > target_hostname ,
2007-12-10 20:41:19 +03:00
s - > port , io - > resolve_ctx ) ;
2006-02-19 19:58:48 +03:00
composite_continue ( c , pipe_req , continue_pipe_open_ncacn_ip_tcp , c ) ;
return c ;
}
2006-02-20 20:30:15 +03:00
/*
Receive result of a rpc connection to a rpc pipe on TCP / IP
*/
2006-10-24 11:56:59 +04:00
static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp_recv ( struct composite_context * c )
2006-02-19 19:58:48 +03:00
{
NTSTATUS status = composite_wait ( c ) ;
talloc_free ( c ) ;
return status ;
}
struct pipe_unix_state {
struct dcerpc_pipe_connect io ;
const char * path ;
} ;
2006-02-20 20:30:15 +03:00
/*
Stage 2 of ncacn_unix : rpc pipe opened ( or not )
*/
2006-03-10 02:21:49 +03:00
static void continue_pipe_open_ncacn_unix_stream ( struct composite_context * ctx )
2006-02-19 19:58:48 +03:00
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
2006-02-20 20:30:15 +03:00
/* receive result of pipe open request on unix socket */
2006-02-19 19:58:48 +03:00
c - > status = dcerpc_pipe_open_unix_stream_recv ( ctx ) ;
2006-03-10 23:08:15 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2006-02-19 19:58:48 +03:00
composite_done ( c ) ;
}
2006-02-20 20:30:15 +03:00
/*
Initiate async open of a rpc connection to a rpc pipe on unix socket using
the binding structure to determine the endpoint and options
*/
2006-10-24 11:56:59 +04:00
static struct composite_context * dcerpc_pipe_connect_ncacn_unix_stream_send ( TALLOC_CTX * mem_ctx ,
struct dcerpc_pipe_connect * io )
2006-02-19 19:58:48 +03:00
{
struct composite_context * c ;
struct pipe_unix_state * s ;
struct composite_context * pipe_req ;
/* composite context allocation and setup */
2006-07-30 22:24:07 +04:00
c = composite_create ( mem_ctx , io - > pipe - > conn - > event_ctx ) ;
2006-02-19 19:58:48 +03:00
if ( c = = NULL ) return NULL ;
s = talloc_zero ( c , struct pipe_unix_state ) ;
2006-03-10 02:21:49 +03:00
if ( composite_nomem ( s , c ) ) return c ;
2006-02-19 19:58:48 +03:00
c - > private_data = s ;
2006-02-20 20:30:15 +03:00
/* prepare pipe open parameters and store them in state structure
also , verify whether biding endpoint is not null */
s - > io = * io ;
2006-02-19 19:58:48 +03:00
if ( ! io - > binding - > endpoint ) {
DEBUG ( 0 , ( " Path to unix socket not specified \n " ) ) ;
composite_error ( c , NT_STATUS_INVALID_PARAMETER ) ;
2006-03-10 02:21:49 +03:00
return c ;
2006-02-19 19:58:48 +03:00
}
s - > path = talloc_strdup ( c , io - > binding - > endpoint ) ; /* path is a binding endpoint here */
2006-07-30 22:24:07 +04:00
if ( composite_nomem ( s - > path , c ) ) return c ;
2006-02-20 20:30:15 +03:00
/* send pipe open request on unix socket */
2006-02-19 19:58:48 +03:00
pipe_req = dcerpc_pipe_open_unix_stream_send ( s - > io . pipe - > conn , s - > path ) ;
composite_continue ( c , pipe_req , continue_pipe_open_ncacn_unix_stream , c ) ;
return c ;
}
2006-02-20 20:30:15 +03:00
/*
Receive result of a rpc connection to a pipe on unix socket
*/
2006-10-24 11:56:59 +04:00
static NTSTATUS dcerpc_pipe_connect_ncacn_unix_stream_recv ( struct composite_context * c )
2006-02-19 19:58:48 +03:00
{
NTSTATUS status = composite_wait ( c ) ;
talloc_free ( c ) ;
return status ;
}
struct pipe_ncalrpc_state {
struct dcerpc_pipe_connect io ;
} ;
2006-10-24 11:56:59 +04:00
static NTSTATUS dcerpc_pipe_connect_ncalrpc_recv ( struct composite_context * c ) ;
2006-02-19 19:58:48 +03:00
2006-02-20 20:30:15 +03:00
/*
Stage 2 of ncalrpc : rpc pipe opened ( or not )
*/
2006-03-10 02:21:49 +03:00
static void continue_pipe_open_ncalrpc ( struct composite_context * ctx )
2006-02-19 19:58:48 +03:00
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
2006-02-20 20:30:15 +03:00
/* receive result of pipe open request on ncalrpc */
2006-02-19 19:58:48 +03:00
c - > status = dcerpc_pipe_connect_ncalrpc_recv ( ctx ) ;
2006-03-10 23:08:15 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2006-02-19 19:58:48 +03:00
composite_done ( c ) ;
}
2006-02-20 20:30:15 +03:00
/*
Initiate async open of a rpc connection request on NCALRPC using
the binding structure to determine the endpoint and options
*/
2006-10-24 11:56:59 +04:00
static struct composite_context * dcerpc_pipe_connect_ncalrpc_send ( TALLOC_CTX * mem_ctx ,
2008-01-03 00:00:58 +03:00
struct dcerpc_pipe_connect * io , struct loadparm_context * lp_ctx )
2006-02-19 19:58:48 +03:00
{
struct composite_context * c ;
struct pipe_ncalrpc_state * s ;
struct composite_context * pipe_req ;
/* composite context allocation and setup */
2006-07-30 22:24:07 +04:00
c = composite_create ( mem_ctx , io - > pipe - > conn - > event_ctx ) ;
2006-02-19 19:58:48 +03:00
if ( c = = NULL ) return NULL ;
s = talloc_zero ( c , struct pipe_ncalrpc_state ) ;
2006-03-10 02:21:49 +03:00
if ( composite_nomem ( s , c ) ) return c ;
2006-02-19 19:58:48 +03:00
c - > private_data = s ;
2006-02-20 20:30:15 +03:00
/* store input parameters in state structure */
2006-02-19 19:58:48 +03:00
s - > io = * io ;
2006-02-20 20:30:15 +03:00
/* send pipe open request */
2008-01-03 00:00:58 +03:00
pipe_req = dcerpc_pipe_open_pipe_send ( s - > io . pipe - > conn , lp_ncalrpc_dir ( lp_ctx ) ,
2007-12-06 18:54:34 +03:00
s - > io . binding - > endpoint ) ;
2006-02-19 19:58:48 +03:00
composite_continue ( c , pipe_req , continue_pipe_open_ncalrpc , c ) ;
return c ;
}
2006-02-20 20:30:15 +03:00
/*
Receive result of a rpc connection to a rpc pipe on NCALRPC
*/
2006-10-24 11:56:59 +04:00
static NTSTATUS dcerpc_pipe_connect_ncalrpc_recv ( struct composite_context * c )
2006-02-19 19:58:48 +03:00
{
NTSTATUS status = composite_wait ( c ) ;
talloc_free ( c ) ;
return status ;
}
2006-03-10 02:21:49 +03:00
struct pipe_connect_state {
struct dcerpc_pipe * pipe ;
struct dcerpc_binding * binding ;
2007-08-20 00:46:45 +04:00
const struct ndr_interface_table * table ;
2006-03-10 02:21:49 +03:00
struct cli_credentials * credentials ;
2007-12-07 04:37:04 +03:00
struct loadparm_context * lp_ctx ;
2006-03-10 02:21:49 +03:00
} ;
static void continue_map_binding ( struct composite_context * ctx ) ;
static void continue_connect ( struct composite_context * c , struct pipe_connect_state * s ) ;
static void continue_pipe_connect_ncacn_np_smb2 ( struct composite_context * ctx ) ;
static void continue_pipe_connect_ncacn_np_smb ( struct composite_context * ctx ) ;
static void continue_pipe_connect_ncacn_ip_tcp ( struct composite_context * ctx ) ;
static void continue_pipe_connect_ncacn_unix ( struct composite_context * ctx ) ;
static void continue_pipe_connect_ncalrpc ( struct composite_context * ctx ) ;
static void continue_pipe_connect ( struct composite_context * c , struct pipe_connect_state * s ) ;
static void continue_pipe_auth ( struct composite_context * ctx ) ;
2006-03-10 19:36:35 +03:00
/*
Stage 2 of pipe_connect_b : Receive result of endpoint mapping
*/
2006-03-10 02:21:49 +03:00
static void continue_map_binding ( struct composite_context * ctx )
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
struct pipe_connect_state * s = talloc_get_type ( c - > private_data ,
struct pipe_connect_state ) ;
c - > status = dcerpc_epm_map_binding_recv ( ctx ) ;
2006-03-10 23:08:15 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2006-03-10 02:21:49 +03:00
DEBUG ( 2 , ( " Mapped to DCERPC endpoint %s \n " , s - > binding - > endpoint ) ) ;
continue_connect ( c , s ) ;
}
2006-03-10 19:36:35 +03:00
/*
Stage 2 of pipe_connect_b : Continue connection after endpoint is known
*/
2006-03-10 02:21:49 +03:00
static void continue_connect ( struct composite_context * c , struct pipe_connect_state * s )
{
struct dcerpc_pipe_connect pc ;
/* potential exits to another stage by sending an async request */
struct composite_context * ncacn_np_smb2_req ;
struct composite_context * ncacn_np_smb_req ;
struct composite_context * ncacn_ip_tcp_req ;
struct composite_context * ncacn_unix_req ;
struct composite_context * ncalrpc_req ;
/* dcerpc pipe connect input parameters */
pc . pipe = s - > pipe ;
pc . binding = s - > binding ;
pc . interface = s - > table ;
pc . creds = s - > credentials ;
2008-01-03 00:00:58 +03:00
pc . resolve_ctx = lp_resolve_context ( s - > lp_ctx ) ;
2006-10-24 11:56:59 +04:00
2006-03-10 19:36:35 +03:00
/* connect dcerpc pipe depending on required transport */
2006-03-10 02:21:49 +03:00
switch ( s - > binding - > transport ) {
case NCACN_NP :
if ( pc . binding - > flags & DCERPC_SMB2 ) {
/* new varient of SMB a.k.a. SMB2 */
2008-01-03 00:00:58 +03:00
ncacn_np_smb2_req = dcerpc_pipe_connect_ncacn_np_smb2_send ( c , & pc , s - > lp_ctx ) ;
2006-03-10 02:21:49 +03:00
composite_continue ( c , ncacn_np_smb2_req , continue_pipe_connect_ncacn_np_smb2 , c ) ;
return ;
} else {
/* good old ordinary SMB */
2008-01-03 00:00:58 +03:00
ncacn_np_smb_req = dcerpc_pipe_connect_ncacn_np_smb_send ( c , & pc , s - > lp_ctx ) ;
2006-03-10 02:21:49 +03:00
composite_continue ( c , ncacn_np_smb_req , continue_pipe_connect_ncacn_np_smb , c ) ;
return ;
}
break ;
case NCACN_IP_TCP :
ncacn_ip_tcp_req = dcerpc_pipe_connect_ncacn_ip_tcp_send ( c , & pc ) ;
composite_continue ( c , ncacn_ip_tcp_req , continue_pipe_connect_ncacn_ip_tcp , c ) ;
return ;
case NCACN_UNIX_STREAM :
ncacn_unix_req = dcerpc_pipe_connect_ncacn_unix_stream_send ( c , & pc ) ;
composite_continue ( c , ncacn_unix_req , continue_pipe_connect_ncacn_unix , c ) ;
return ;
case NCALRPC :
2008-01-03 00:00:58 +03:00
ncalrpc_req = dcerpc_pipe_connect_ncalrpc_send ( c , & pc , s - > lp_ctx ) ;
2006-03-10 02:21:49 +03:00
composite_continue ( c , ncalrpc_req , continue_pipe_connect_ncalrpc , c ) ;
return ;
default :
2006-03-10 19:36:35 +03:00
/* looks like a transport we don't support now */
2006-03-10 02:21:49 +03:00
composite_error ( c , NT_STATUS_NOT_SUPPORTED ) ;
}
}
2006-03-10 19:36:35 +03:00
/*
Stage 3 of pipe_connect_b : Receive result of pipe connect request on
named pipe on smb2
*/
2006-03-10 02:21:49 +03:00
static void continue_pipe_connect_ncacn_np_smb2 ( struct composite_context * ctx )
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
struct pipe_connect_state * s = talloc_get_type ( c - > private_data ,
struct pipe_connect_state ) ;
c - > status = dcerpc_pipe_connect_ncacn_np_smb2_recv ( ctx ) ;
if ( ! composite_is_ok ( c ) ) return ;
continue_pipe_connect ( c , s ) ;
}
2006-03-10 19:36:35 +03:00
/*
Stage 3 of pipe_connect_b : Receive result of pipe connect request on
named pipe on smb
*/
2006-03-10 02:21:49 +03:00
static void continue_pipe_connect_ncacn_np_smb ( struct composite_context * ctx )
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
struct pipe_connect_state * s = talloc_get_type ( c - > private_data ,
struct pipe_connect_state ) ;
c - > status = dcerpc_pipe_connect_ncacn_np_smb_recv ( ctx ) ;
if ( ! composite_is_ok ( c ) ) return ;
continue_pipe_connect ( c , s ) ;
}
2006-03-10 19:36:35 +03:00
/*
Stage 3 of pipe_connect_b : Receive result of pipe connect request on tcp / ip
*/
2006-03-10 02:21:49 +03:00
static void continue_pipe_connect_ncacn_ip_tcp ( struct composite_context * ctx )
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
struct pipe_connect_state * s = talloc_get_type ( c - > private_data ,
struct pipe_connect_state ) ;
c - > status = dcerpc_pipe_connect_ncacn_ip_tcp_recv ( ctx ) ;
if ( ! composite_is_ok ( c ) ) return ;
continue_pipe_connect ( c , s ) ;
}
2006-03-10 19:36:35 +03:00
/*
Stage 3 of pipe_connect_b : Receive result of pipe connect request on unix socket
*/
2006-03-10 02:21:49 +03:00
static void continue_pipe_connect_ncacn_unix ( struct composite_context * ctx )
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
struct pipe_connect_state * s = talloc_get_type ( c - > private_data ,
struct pipe_connect_state ) ;
c - > status = dcerpc_pipe_connect_ncacn_unix_stream_recv ( ctx ) ;
if ( ! composite_is_ok ( c ) ) return ;
continue_pipe_connect ( c , s ) ;
}
2006-03-10 19:36:35 +03:00
/*
Stage 3 of pipe_connect_b : Receive result of pipe connect request on local rpc
*/
2006-03-10 02:21:49 +03:00
static void continue_pipe_connect_ncalrpc ( struct composite_context * ctx )
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
struct pipe_connect_state * s = talloc_get_type ( c - > private_data ,
struct pipe_connect_state ) ;
c - > status = dcerpc_pipe_connect_ncalrpc_recv ( ctx ) ;
if ( ! composite_is_ok ( c ) ) return ;
continue_pipe_connect ( c , s ) ;
}
2006-03-10 19:36:35 +03:00
/*
Stage 4 of pipe_connect_b : Start an authentication on connected dcerpc pipe
depending on credentials and binding flags passed .
*/
2006-03-10 02:21:49 +03:00
static void continue_pipe_connect ( struct composite_context * c , struct pipe_connect_state * s )
{
struct composite_context * auth_bind_req ;
s - > pipe - > binding = s - > binding ;
if ( ! talloc_reference ( s - > pipe , s - > binding ) ) {
composite_error ( c , NT_STATUS_NO_MEMORY ) ;
return ;
}
auth_bind_req = dcerpc_pipe_auth_send ( s - > pipe , s - > binding , s - > table ,
2007-12-07 04:37:04 +03:00
s - > credentials , s - > lp_ctx ) ;
2006-03-10 02:21:49 +03:00
composite_continue ( c , auth_bind_req , continue_pipe_auth , c ) ;
}
2006-03-10 19:36:35 +03:00
/*
Stage 5 of pipe_connect_b : Receive result of pipe authentication request
and say if all went ok
*/
2006-03-10 02:21:49 +03:00
static void continue_pipe_auth ( struct composite_context * ctx )
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
2006-05-04 14:03:41 +04:00
struct pipe_connect_state * s = talloc_get_type ( c - > private_data , struct pipe_connect_state ) ;
2006-03-10 02:21:49 +03:00
2006-05-07 23:55:14 +04:00
c - > status = dcerpc_pipe_auth_recv ( ctx , s , & s - > pipe ) ;
2006-03-10 02:21:49 +03:00
if ( ! composite_is_ok ( c ) ) return ;
composite_done ( c ) ;
}
2006-09-01 14:33:55 +04:00
/*
handle timeouts of a dcerpc connect
*/
static void dcerpc_connect_timeout_handler ( struct event_context * ev , struct timed_event * te ,
struct timeval t , void * private )
{
struct composite_context * c = talloc_get_type ( private , struct composite_context ) ;
composite_error ( c , NT_STATUS_IO_TIMEOUT ) ;
}
2006-03-10 19:36:35 +03:00
/*
start a request to open a rpc connection to a rpc pipe , using
specified binding structure to determine the endpoint and options
*/
2006-03-10 02:21:49 +03:00
struct composite_context * dcerpc_pipe_connect_b_send ( TALLOC_CTX * parent_ctx ,
struct dcerpc_binding * binding ,
2007-08-20 00:46:45 +04:00
const struct ndr_interface_table * table ,
2006-03-10 02:21:49 +03:00
struct cli_credentials * credentials ,
2007-12-07 04:37:04 +03:00
struct event_context * ev ,
struct loadparm_context * lp_ctx )
2006-03-10 02:21:49 +03:00
{
struct composite_context * c ;
struct pipe_connect_state * s ;
2006-07-30 22:24:07 +04:00
struct event_context * new_ev = NULL ;
if ( ev = = NULL ) {
new_ev = event_context_init ( parent_ctx ) ;
if ( new_ev = = NULL ) return NULL ;
ev = new_ev ;
}
2006-03-10 02:21:49 +03:00
/* composite context allocation and setup */
2006-07-30 22:24:07 +04:00
c = composite_create ( parent_ctx , ev ) ;
if ( c = = NULL ) {
talloc_free ( new_ev ) ;
return NULL ;
}
talloc_steal ( c , new_ev ) ;
2006-03-10 02:21:49 +03:00
s = talloc_zero ( c , struct pipe_connect_state ) ;
if ( composite_nomem ( s , c ) ) return c ;
c - > private_data = s ;
/* initialise dcerpc pipe structure */
2008-01-02 07:05:13 +03:00
s - > pipe = dcerpc_pipe_init ( c , ev , lp_iconv_convenience ( lp_ctx ) ) ;
2006-03-10 02:21:49 +03:00
if ( composite_nomem ( s - > pipe , c ) ) return c ;
2006-03-10 19:36:35 +03:00
/* store parameters in state structure */
2006-03-10 02:21:49 +03:00
s - > binding = binding ;
s - > table = table ;
s - > credentials = credentials ;
2007-12-07 04:37:04 +03:00
s - > lp_ctx = lp_ctx ;
2006-09-01 14:33:55 +04:00
event_add_timed ( c - > event_ctx , c ,
timeval_current_ofs ( DCERPC_REQUEST_TIMEOUT , 0 ) ,
dcerpc_connect_timeout_handler , c ) ;
2006-03-10 02:21:49 +03:00
switch ( s - > binding - > transport ) {
2007-08-29 06:01:56 +04:00
case NCA_UNKNOWN : {
struct composite_context * binding_req ;
binding_req = dcerpc_epm_map_binding_send ( c , s - > binding , s - > table ,
2007-12-07 04:37:04 +03:00
s - > pipe - > conn - > event_ctx ,
s - > lp_ctx ) ;
2007-08-29 06:01:56 +04:00
composite_continue ( c , binding_req , continue_map_binding , c ) ;
return c ;
}
2006-03-10 02:21:49 +03:00
case NCACN_NP :
case NCACN_IP_TCP :
case NCALRPC :
if ( ! s - > binding - > endpoint ) {
2006-09-01 14:33:55 +04:00
struct composite_context * binding_req ;
2006-03-10 02:21:49 +03:00
binding_req = dcerpc_epm_map_binding_send ( c , s - > binding , s - > table ,
2007-12-07 04:37:04 +03:00
s - > pipe - > conn - > event_ctx ,
s - > lp_ctx ) ;
2006-03-10 02:21:49 +03:00
composite_continue ( c , binding_req , continue_map_binding , c ) ;
return c ;
}
default :
break ;
}
continue_connect ( c , s ) ;
return c ;
}
2006-03-10 19:36:35 +03:00
/*
receive result of a request to open a rpc connection to a rpc pipe
*/
2006-03-10 02:21:49 +03:00
NTSTATUS dcerpc_pipe_connect_b_recv ( struct composite_context * c , TALLOC_CTX * mem_ctx ,
struct dcerpc_pipe * * p )
{
NTSTATUS status ;
struct pipe_connect_state * s ;
status = composite_wait ( c ) ;
2006-10-13 17:01:48 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
s = talloc_get_type ( c - > private_data , struct pipe_connect_state ) ;
talloc_steal ( mem_ctx , s - > pipe ) ;
* p = s - > pipe ;
}
2006-03-10 02:21:49 +03:00
talloc_free ( c ) ;
return status ;
}
/*
open a rpc connection to a rpc pipe , using the specified
binding structure to determine the endpoint and options - sync version
*/
NTSTATUS dcerpc_pipe_connect_b ( TALLOC_CTX * parent_ctx ,
struct dcerpc_pipe * * pp ,
struct dcerpc_binding * binding ,
2007-08-20 00:46:45 +04:00
const struct ndr_interface_table * table ,
2006-03-10 02:21:49 +03:00
struct cli_credentials * credentials ,
2007-12-07 04:37:04 +03:00
struct event_context * ev ,
struct loadparm_context * lp_ctx )
2006-03-10 02:21:49 +03:00
{
struct composite_context * c ;
2006-05-04 14:03:41 +04:00
c = dcerpc_pipe_connect_b_send ( parent_ctx , binding , table ,
2007-12-07 04:37:04 +03:00
credentials , ev , lp_ctx ) ;
2006-03-10 02:21:49 +03:00
return dcerpc_pipe_connect_b_recv ( c , parent_ctx , pp ) ;
}
struct pipe_conn_state {
struct dcerpc_pipe * pipe ;
} ;
static void continue_pipe_connect_b ( struct composite_context * ctx ) ;
2006-03-10 19:36:35 +03:00
/*
Initiate rpc connection to a rpc pipe , using the specified string
binding to determine the endpoint and options .
The string is to be parsed to a binding structure first .
*/
2006-03-10 02:21:49 +03:00
struct composite_context * dcerpc_pipe_connect_send ( TALLOC_CTX * parent_ctx ,
const char * binding ,
2007-08-20 00:46:45 +04:00
const struct ndr_interface_table * table ,
2006-03-10 02:21:49 +03:00
struct cli_credentials * credentials ,
2007-12-07 04:37:04 +03:00
struct event_context * ev , struct loadparm_context * lp_ctx )
2006-03-10 02:21:49 +03:00
{
struct composite_context * c ;
struct pipe_conn_state * s ;
struct dcerpc_binding * b ;
struct composite_context * pipe_conn_req ;
2006-07-30 22:24:07 +04:00
struct event_context * new_ev = NULL ;
if ( ev = = NULL ) {
new_ev = event_context_init ( parent_ctx ) ;
if ( new_ev = = NULL ) return NULL ;
ev = new_ev ;
}
2006-03-10 02:21:49 +03:00
2006-03-10 19:36:35 +03:00
/* composite context allocation and setup */
2006-07-30 22:24:07 +04:00
c = composite_create ( parent_ctx , ev ) ;
if ( c = = NULL ) {
talloc_free ( new_ev ) ;
return NULL ;
}
talloc_steal ( c , new_ev ) ;
2006-03-10 02:21:49 +03:00
s = talloc_zero ( c , struct pipe_conn_state ) ;
if ( composite_nomem ( s , c ) ) return c ;
c - > private_data = s ;
2006-03-10 19:36:35 +03:00
/* parse binding string to the structure */
2006-07-30 22:24:07 +04:00
c - > status = dcerpc_parse_binding ( c , binding , & b ) ;
if ( ! NT_STATUS_IS_OK ( c - > status ) ) {
2006-03-10 02:21:49 +03:00
DEBUG ( 0 , ( " Failed to parse dcerpc binding '%s' \n " , binding ) ) ;
2006-07-30 22:24:07 +04:00
composite_error ( c , c - > status ) ;
2006-03-10 02:21:49 +03:00
return c ;
}
DEBUG ( 3 , ( " Using binding %s \n " , dcerpc_binding_string ( c , b ) ) ) ;
2006-03-10 19:36:35 +03:00
/*
start connecting to a rpc pipe after binding structure
is established
*/
2006-05-04 14:03:41 +04:00
pipe_conn_req = dcerpc_pipe_connect_b_send ( c , b , table ,
2007-12-07 04:37:04 +03:00
credentials , ev , lp_ctx ) ;
2006-03-10 02:21:49 +03:00
composite_continue ( c , pipe_conn_req , continue_pipe_connect_b , c ) ;
return c ;
}
2006-03-10 19:36:35 +03:00
/*
Stage 2 of pipe_connect : Receive result of actual pipe connect request
and say if we ' re done ok
*/
2006-03-10 02:21:49 +03:00
static void continue_pipe_connect_b ( struct composite_context * ctx )
{
struct composite_context * c = talloc_get_type ( ctx - > async . private_data ,
struct composite_context ) ;
struct pipe_conn_state * s = talloc_get_type ( c - > private_data ,
struct pipe_conn_state ) ;
c - > status = dcerpc_pipe_connect_b_recv ( ctx , c , & s - > pipe ) ;
2006-05-04 14:03:41 +04:00
talloc_steal ( s , s - > pipe ) ;
2006-03-10 02:21:49 +03:00
if ( ! composite_is_ok ( c ) ) return ;
composite_done ( c ) ;
}
2006-03-10 19:36:35 +03:00
/*
Receive result of pipe connect ( using binding string ) request
and return connected pipe structure .
*/
2006-03-10 02:21:49 +03:00
NTSTATUS dcerpc_pipe_connect_recv ( struct composite_context * c ,
TALLOC_CTX * mem_ctx ,
struct dcerpc_pipe * * pp )
{
NTSTATUS status ;
struct pipe_conn_state * s ;
status = composite_wait ( c ) ;
2007-04-25 16:36:12 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
s = talloc_get_type ( c - > private_data , struct pipe_conn_state ) ;
* pp = talloc_steal ( mem_ctx , s - > pipe ) ;
}
2006-03-10 02:21:49 +03:00
talloc_free ( c ) ;
return status ;
}
/*
2006-03-10 19:36:35 +03:00
Open a rpc connection to a rpc pipe , using the specified string
2006-03-10 02:21:49 +03:00
binding to determine the endpoint and options - sync version
*/
NTSTATUS dcerpc_pipe_connect ( TALLOC_CTX * parent_ctx ,
struct dcerpc_pipe * * pp ,
const char * binding ,
2007-08-20 00:46:45 +04:00
const struct ndr_interface_table * table ,
2006-03-10 02:21:49 +03:00
struct cli_credentials * credentials ,
2007-12-07 04:37:04 +03:00
struct event_context * ev ,
struct loadparm_context * lp_ctx )
2006-03-10 02:21:49 +03:00
{
struct composite_context * c ;
2006-10-13 17:01:48 +04:00
c = dcerpc_pipe_connect_send ( parent_ctx , binding ,
2007-12-07 04:37:04 +03:00
table , credentials , ev , lp_ctx ) ;
2006-03-10 02:21:49 +03:00
return dcerpc_pipe_connect_recv ( c , parent_ctx , pp ) ;
}