2003-11-26 03:36:17 +00:00
/*
Unix SMB / CIFS implementation .
dcerpc utility functions
Copyright ( C ) Andrew Tridgell 2003
2004-10-18 15:18:05 +00:00
Copyright ( C ) Jelmer Vernooij 2004
2003-11-26 03:36:17 +00: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
the Free Software Foundation ; either version 2 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 , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
2004-11-01 22:48:25 +00:00
# include "system/network.h"
2004-11-01 10:30:34 +00:00
# include "librpc/gen_ndr/ndr_epmapper.h"
2004-10-24 16:31:00 +00:00
2003-11-27 07:28:46 +00:00
/*
find the pipe name for a local IDL interface
*/
2004-05-25 16:24:13 +00:00
const char * idl_pipe_name ( const char * uuid , uint32_t if_version )
2003-11-27 07:28:46 +00:00
{
2005-01-09 08:34:05 +00:00
const struct dcerpc_interface_list * l ;
for ( l = librpc_dcerpc_pipes ( ) ; l ; l = l - > next ) {
2004-11-16 21:07:08 +00:00
if ( strcasecmp ( l - > table - > uuid , uuid ) = = 0 & &
l - > table - > if_version = = if_version ) {
return l - > table - > name ;
2003-11-27 07:28:46 +00:00
}
}
return " UNKNOWN " ;
}
/*
find the number of calls defined by local IDL
*/
2004-05-25 16:24:13 +00:00
int idl_num_calls ( const char * uuid , uint32_t if_version )
2003-11-27 07:28:46 +00:00
{
2005-01-09 08:34:05 +00:00
const struct dcerpc_interface_list * l ;
for ( l = librpc_dcerpc_pipes ( ) ; l ; l = l - > next ) {
2004-11-16 21:07:08 +00:00
if ( strcasecmp ( l - > table - > uuid , uuid ) = = 0 & &
l - > table - > if_version = = if_version ) {
return l - > table - > num_calls ;
2003-11-27 07:28:46 +00:00
}
}
return - 1 ;
}
2003-11-28 08:51:09 +00:00
/*
find a dcerpc interface by name
*/
const struct dcerpc_interface_table * idl_iface_by_name ( const char * name )
{
2005-01-09 08:34:05 +00:00
const struct dcerpc_interface_list * l ;
for ( l = librpc_dcerpc_pipes ( ) ; l ; l = l - > next ) {
2004-11-16 21:07:08 +00:00
if ( strcasecmp ( l - > table - > name , name ) = = 0 ) {
return l - > table ;
2003-11-28 08:51:09 +00:00
}
}
return NULL ;
}
2003-12-14 01:09:10 +00:00
2003-12-15 03:29:55 +00:00
/*
find a dcerpc interface by uuid
*/
const struct dcerpc_interface_table * idl_iface_by_uuid ( const char * uuid )
{
2005-01-09 08:34:05 +00:00
const struct dcerpc_interface_list * l ;
for ( l = librpc_dcerpc_pipes ( ) ; l ; l = l - > next ) {
2004-11-16 21:07:08 +00:00
if ( strcasecmp ( l - > table - > uuid , uuid ) = = 0 ) {
return l - > table ;
2003-12-15 03:29:55 +00:00
}
}
return NULL ;
}
2003-12-14 01:09:10 +00:00
/*
push a dcerpc_packet into a blob , potentially with auth info
*/
NTSTATUS dcerpc_push_auth ( DATA_BLOB * blob , TALLOC_CTX * mem_ctx ,
struct dcerpc_packet * pkt ,
2003-12-17 02:06:44 +00:00
struct dcerpc_auth * auth_info )
2003-12-14 01:09:10 +00:00
{
NTSTATUS status ;
struct ndr_push * ndr ;
ndr = ndr_push_init_ctx ( mem_ctx ) ;
if ( ! ndr ) {
return NT_STATUS_NO_MEMORY ;
}
2003-12-17 02:06:44 +00:00
if ( ! ( pkt - > drep [ 0 ] & DCERPC_DREP_LE ) ) {
2003-12-16 09:02:58 +00:00
ndr - > flags | = LIBNDR_FLAG_BIGENDIAN ;
}
2004-11-08 02:12:15 +00:00
if ( pkt - > pfc_flags & DCERPC_PFC_FLAG_ORPC ) {
ndr - > flags | = LIBNDR_FLAG_OBJECT_PRESENT ;
}
2003-12-14 01:09:10 +00:00
if ( auth_info ) {
pkt - > auth_length = auth_info - > credentials . length ;
} else {
pkt - > auth_length = 0 ;
}
status = ndr_push_dcerpc_packet ( ndr , NDR_SCALARS | NDR_BUFFERS , pkt ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( auth_info ) {
status = ndr_push_dcerpc_auth ( ndr , NDR_SCALARS | NDR_BUFFERS , auth_info ) ;
}
* blob = ndr_push_blob ( ndr ) ;
/* fill in the frag length */
2003-12-16 09:02:58 +00:00
dcerpc_set_frag_length ( blob , blob - > length ) ;
2003-12-14 01:09:10 +00:00
return NT_STATUS_OK ;
}
2003-12-15 03:29:55 +00:00
2004-10-21 12:47:02 +00:00
# define MAX_PROTSEQ 10
2003-12-15 03:29:55 +00:00
2003-12-16 10:57:17 +00:00
static const struct {
const char * name ;
enum dcerpc_transport_t transport ;
2004-10-21 12:47:02 +00:00
int num_protocols ;
2005-01-05 02:01:19 +00:00
enum epm_protocol protseq [ MAX_PROTSEQ ] ;
2004-10-21 12:47:02 +00:00
} transports [ ] = {
{ " ncacn_np " , NCACN_NP , 3 ,
2004-10-24 13:00:51 +00:00
{ EPM_PROTOCOL_NCACN , EPM_PROTOCOL_SMB , EPM_PROTOCOL_NETBIOS } } ,
2004-10-21 12:47:02 +00:00
{ " ncacn_ip_tcp " , NCACN_IP_TCP , 3 ,
2004-10-24 13:00:51 +00:00
{ EPM_PROTOCOL_NCACN , EPM_PROTOCOL_TCP , EPM_PROTOCOL_IP } } ,
2004-10-24 13:22:58 +00:00
{ " ncacn_http " , NCACN_HTTP , 3 ,
{ EPM_PROTOCOL_NCACN , EPM_PROTOCOL_HTTP , EPM_PROTOCOL_IP } } ,
2004-10-21 12:47:02 +00:00
{ " ncadg_ip_udp " , NCACN_IP_UDP , 3 ,
2004-10-24 13:00:51 +00:00
{ EPM_PROTOCOL_NCADG , EPM_PROTOCOL_UDP , EPM_PROTOCOL_IP } } ,
2004-10-21 19:54:38 +00:00
{ " ncalrpc " , NCALRPC , 2 ,
{ EPM_PROTOCOL_NCALRPC , EPM_PROTOCOL_PIPE } } ,
2004-10-21 12:47:02 +00:00
{ " ncacn_unix_stream " , NCACN_UNIX_STREAM , 2 ,
{ EPM_PROTOCOL_NCACN , EPM_PROTOCOL_UNIX_DS } } ,
{ " ncadg_unix_dgram " , NCADG_UNIX_DGRAM , 2 ,
{ EPM_PROTOCOL_NCADG , EPM_PROTOCOL_UNIX_DS } } ,
{ " ncacn_at_dsp " , NCACN_AT_DSP , 3 ,
{ EPM_PROTOCOL_NCACN , EPM_PROTOCOL_APPLETALK , EPM_PROTOCOL_DSP } } ,
{ " ncadg_at_ddp " , NCADG_AT_DDP , 3 ,
{ EPM_PROTOCOL_NCADG , EPM_PROTOCOL_APPLETALK , EPM_PROTOCOL_DDP } } ,
{ " ncacn_vns_ssp " , NCACN_VNS_SPP , 3 ,
{ EPM_PROTOCOL_NCACN , EPM_PROTOCOL_STREETTALK , EPM_PROTOCOL_VINES_SPP } } ,
{ " ncacn_vns_ipc " , NCACN_VNS_IPC , 3 ,
{ EPM_PROTOCOL_NCACN , EPM_PROTOCOL_STREETTALK , EPM_PROTOCOL_VINES_IPC } , } ,
2004-10-31 18:35:47 +00:00
{ " ncadg_ipx " , NCADG_IPX , 2 ,
{ EPM_PROTOCOL_NCADG , EPM_PROTOCOL_IPX } ,
} ,
{ " ncacn_spx " , NCACN_SPX , 2 ,
{ EPM_PROTOCOL_NCACN , EPM_PROTOCOL_SPX } ,
} ,
2003-12-16 10:57:17 +00:00
} ;
static const struct {
const char * name ;
2004-05-25 16:24:13 +00:00
uint32_t flag ;
2003-12-16 10:57:17 +00:00
} ncacn_options [ ] = {
{ " sign " , DCERPC_SIGN } ,
{ " seal " , DCERPC_SEAL } ,
2004-09-25 07:25:51 +00:00
{ " connect " , DCERPC_CONNECT } ,
2003-12-16 10:57:17 +00:00
{ " validate " , DCERPC_DEBUG_VALIDATE_BOTH } ,
2004-02-03 14:56:07 +00:00
{ " print " , DCERPC_DEBUG_PRINT_BOTH } ,
2004-09-02 10:45:58 +00:00
{ " padcheck " , DCERPC_DEBUG_PAD_CHECK } ,
2003-12-16 10:57:17 +00:00
{ " bigendian " , DCERPC_PUSH_BIGENDIAN }
} ;
2004-10-21 19:54:38 +00:00
2003-12-16 10:57:17 +00:00
/*
form a binding string from a binding structure
*/
const char * dcerpc_binding_string ( TALLOC_CTX * mem_ctx , const struct dcerpc_binding * b )
{
2004-11-01 13:12:09 +00:00
char * s = talloc_strdup ( mem_ctx , " " ) ;
2003-12-16 10:57:17 +00:00
int i ;
const char * t_name = NULL ;
2004-10-21 12:47:02 +00:00
for ( i = 0 ; i < ARRAY_SIZE ( transports ) ; i + + ) {
if ( transports [ i ] . transport = = b - > transport ) {
t_name = transports [ i ] . name ;
2003-12-16 10:57:17 +00:00
}
}
if ( ! t_name ) {
return NULL ;
}
2004-11-25 20:03:46 +00:00
if ( ! GUID_all_zero ( & b - > object ) ) {
2004-11-01 13:12:09 +00:00
s = talloc_asprintf ( s , " %s@ " ,
GUID_string ( mem_ctx , & b - > object ) ) ;
2004-10-18 11:43:26 +00:00
}
2004-10-21 21:02:51 +00:00
s = talloc_asprintf_append ( s , " %s: " , t_name ) ;
2003-12-16 10:57:17 +00:00
if ( ! s ) return NULL ;
2004-10-21 21:02:51 +00:00
if ( b - > host ) {
s = talloc_asprintf_append ( s , " %s " , b - > host ) ;
}
2004-10-24 22:46:47 +00:00
if ( ! b - > endpoint & & ! b - > options & & ! b - > flags ) {
2004-10-21 19:54:38 +00:00
return s ;
}
s = talloc_asprintf_append ( s , " [ " ) ;
2004-10-24 22:46:47 +00:00
if ( b - > endpoint ) {
s = talloc_asprintf_append ( s , " %s " , b - > endpoint ) ;
}
2003-12-16 10:57:17 +00:00
/* this is a *really* inefficent way of dealing with strings,
but this is rarely called and the strings are always short ,
so I don ' t care */
2003-12-17 21:37:34 +00:00
for ( i = 0 ; b - > options & & b - > options [ i ] ; i + + ) {
2004-10-24 22:46:47 +00:00
s = talloc_asprintf_append ( s , " ,%s " , b - > options [ i ] ) ;
2003-12-16 10:57:17 +00:00
if ( ! s ) return NULL ;
}
2004-10-25 10:21:41 +00:00
2003-12-16 10:57:17 +00:00
for ( i = 0 ; i < ARRAY_SIZE ( ncacn_options ) ; i + + ) {
if ( b - > flags & ncacn_options [ i ] . flag ) {
2004-10-24 22:46:47 +00:00
s = talloc_asprintf_append ( s , " ,%s " , ncacn_options [ i ] . name ) ;
2003-12-16 10:57:17 +00:00
if ( ! s ) return NULL ;
}
}
2004-10-21 19:54:38 +00:00
s = talloc_asprintf_append ( s , " ] " ) ;
2003-12-16 10:57:17 +00:00
return s ;
}
2003-12-15 03:29:55 +00:00
/*
parse a binding string into a dcerpc_binding structure
*/
NTSTATUS dcerpc_parse_binding ( TALLOC_CTX * mem_ctx , const char * s , struct dcerpc_binding * b )
{
2004-10-18 11:43:26 +00:00
char * options , * type ;
2003-12-15 03:29:55 +00:00
char * p ;
int i , j , comma_count ;
2004-10-18 11:43:26 +00:00
p = strchr ( s , ' @ ' ) ;
if ( p & & PTR_DIFF ( p , s ) = = 36 ) { /* 36 is the length of a UUID */
NTSTATUS status ;
2004-10-21 21:57:30 +00:00
status = GUID_from_string ( s , & b - > object ) ;
2004-10-18 11:43:26 +00:00
if ( NT_STATUS_IS_ERR ( status ) ) {
DEBUG ( 0 , ( " Failed parsing UUID \n " ) ) ;
return status ;
}
s = p + 1 ;
} else {
2004-10-21 21:57:30 +00:00
ZERO_STRUCT ( b - > object ) ;
2003-12-15 03:29:55 +00:00
}
2004-10-22 10:52:57 +00:00
b - > object_version = 0 ;
2003-12-15 03:29:55 +00:00
p = strchr ( s , ' : ' ) ;
if ( ! p ) {
2004-10-18 11:43:26 +00:00
return NT_STATUS_INVALID_PARAMETER ;
2003-12-15 03:29:55 +00:00
}
2004-10-18 11:43:26 +00:00
type = talloc_strndup ( mem_ctx , s , PTR_DIFF ( p , s ) ) ;
if ( ! type ) {
2003-12-15 03:29:55 +00:00
return NT_STATUS_NO_MEMORY ;
}
2004-10-21 12:47:02 +00:00
for ( i = 0 ; i < ARRAY_SIZE ( transports ) ; i + + ) {
if ( strcasecmp ( type , transports [ i ] . name ) = = 0 ) {
b - > transport = transports [ i ] . transport ;
2003-12-15 03:29:55 +00:00
break ;
}
}
2004-10-21 12:47:02 +00:00
if ( i = = ARRAY_SIZE ( transports ) ) {
2004-10-18 11:43:26 +00:00
DEBUG ( 0 , ( " Unknown dcerpc transport '%s' \n " , type ) ) ;
2003-12-15 03:29:55 +00:00
return NT_STATUS_INVALID_PARAMETER ;
}
2004-10-18 11:43:26 +00:00
s = p + 1 ;
p = strchr ( s , ' [ ' ) ;
if ( p ) {
b - > host = talloc_strndup ( mem_ctx , s , PTR_DIFF ( p , s ) ) ;
options = talloc_strdup ( mem_ctx , p + 1 ) ;
if ( options [ strlen ( options ) - 1 ] ! = ' ] ' ) {
return NT_STATUS_INVALID_PARAMETER ;
}
options [ strlen ( options ) - 1 ] = 0 ;
} else {
b - > host = talloc_strdup ( mem_ctx , s ) ;
options = NULL ;
}
if ( ! b - > host ) {
return NT_STATUS_NO_MEMORY ;
}
2003-12-15 03:29:55 +00:00
b - > options = NULL ;
b - > flags = 0 ;
2004-10-24 22:46:47 +00:00
b - > endpoint = NULL ;
2003-12-15 03:29:55 +00:00
2004-10-18 11:43:26 +00:00
if ( ! options ) {
2003-12-15 03:29:55 +00:00
return NT_STATUS_OK ;
}
2004-10-18 11:43:26 +00:00
comma_count = count_chars ( options , ' , ' ) ;
2004-10-24 22:46:47 +00:00
2003-12-15 03:29:55 +00:00
b - > options = talloc_array_p ( mem_ctx , const char * , comma_count + 2 ) ;
if ( ! b - > options ) {
return NT_STATUS_NO_MEMORY ;
}
2004-10-18 11:43:26 +00:00
for ( i = 0 ; ( p = strchr ( options , ' , ' ) ) ; i + + ) {
b - > options [ i ] = talloc_strndup ( mem_ctx , options , PTR_DIFF ( p , options ) ) ;
2003-12-15 03:29:55 +00:00
if ( ! b - > options [ i ] ) {
return NT_STATUS_NO_MEMORY ;
}
2004-10-18 11:43:26 +00:00
options = p + 1 ;
2003-12-15 03:29:55 +00:00
}
2004-10-18 11:43:26 +00:00
b - > options [ i ] = options ;
2003-12-15 03:29:55 +00:00
b - > options [ i + 1 ] = NULL ;
/* some options are pre-parsed for convenience */
for ( i = 0 ; b - > options [ i ] ; i + + ) {
2003-12-16 10:57:17 +00:00
for ( j = 0 ; j < ARRAY_SIZE ( ncacn_options ) ; j + + ) {
if ( strcasecmp ( ncacn_options [ j ] . name , b - > options [ i ] ) = = 0 ) {
2003-12-16 10:15:21 +00:00
int k ;
2003-12-16 10:57:17 +00:00
b - > flags | = ncacn_options [ j ] . flag ;
2003-12-16 10:15:21 +00:00
for ( k = i ; b - > options [ k ] ; k + + ) {
b - > options [ k ] = b - > options [ k + 1 ] ;
}
2003-12-19 04:26:26 +00:00
i - - ;
2003-12-15 03:29:55 +00:00
break ;
}
}
}
2004-10-24 22:46:47 +00:00
2004-10-25 10:21:41 +00:00
if ( b - > options [ 0 ] ) {
/* Endpoint is first option */
b - > endpoint = b - > options [ 0 ] ;
if ( strlen ( b - > endpoint ) = = 0 ) b - > endpoint = NULL ;
for ( i = 0 ; b - > options [ i ] ; i + + ) {
b - > options [ i ] = b - > options [ i + 1 ] ;
}
}
2004-10-24 22:46:47 +00:00
if ( b - > options [ 0 ] = = NULL )
b - > options = NULL ;
2003-12-15 03:29:55 +00:00
return NT_STATUS_OK ;
}
2004-10-25 11:28:09 +00:00
const char * dcerpc_floor_get_rhs_data ( TALLOC_CTX * mem_ctx , struct epm_floor * floor )
2004-10-21 21:02:51 +00:00
{
switch ( floor - > lhs . protocol ) {
case EPM_PROTOCOL_TCP :
if ( floor - > rhs . tcp . port = = 0 ) return NULL ;
return talloc_asprintf ( mem_ctx , " %d " , floor - > rhs . tcp . port ) ;
case EPM_PROTOCOL_UDP :
if ( floor - > rhs . udp . port = = 0 ) return NULL ;
return talloc_asprintf ( mem_ctx , " %d " , floor - > rhs . udp . port ) ;
case EPM_PROTOCOL_HTTP :
if ( floor - > rhs . http . port = = 0 ) return NULL ;
return talloc_asprintf ( mem_ctx , " %d " , floor - > rhs . http . port ) ;
case EPM_PROTOCOL_IP :
if ( floor - > rhs . ip . address = = 0 ) {
return NULL ;
}
{
2004-11-01 22:48:25 +00:00
struct ipv4_addr in ;
2004-11-02 03:58:27 +00:00
in . addr = htonl ( floor - > rhs . ip . address ) ;
2004-11-01 22:48:25 +00:00
return talloc_strdup ( mem_ctx , sys_inet_ntoa ( in ) ) ;
2004-10-21 21:02:51 +00:00
}
case EPM_PROTOCOL_NCACN :
return NULL ;
case EPM_PROTOCOL_NCADG :
return NULL ;
case EPM_PROTOCOL_SMB :
2004-10-24 22:46:47 +00:00
if ( strlen ( floor - > rhs . smb . unc ) = = 0 ) return NULL ;
2004-10-21 21:02:51 +00:00
return talloc_strdup ( mem_ctx , floor - > rhs . smb . unc ) ;
case EPM_PROTOCOL_PIPE :
2004-10-24 22:46:47 +00:00
if ( strlen ( floor - > rhs . pipe . path ) = = 0 ) return NULL ;
2004-10-21 21:02:51 +00:00
return talloc_strdup ( mem_ctx , floor - > rhs . pipe . path ) ;
case EPM_PROTOCOL_NETBIOS :
2004-10-24 22:46:47 +00:00
if ( strlen ( floor - > rhs . netbios . name ) = = 0 ) return NULL ;
2004-10-21 21:02:51 +00:00
return talloc_strdup ( mem_ctx , floor - > rhs . netbios . name ) ;
case EPM_PROTOCOL_NCALRPC :
return NULL ;
case EPM_PROTOCOL_VINES_SPP :
return talloc_asprintf ( mem_ctx , " %d " , floor - > rhs . vines_spp . port ) ;
case EPM_PROTOCOL_VINES_IPC :
return talloc_asprintf ( mem_ctx , " %d " , floor - > rhs . vines_ipc . port ) ;
case EPM_PROTOCOL_STREETTALK :
return talloc_strdup ( mem_ctx , floor - > rhs . streettalk . streettalk ) ;
case EPM_PROTOCOL_UNIX_DS :
2004-10-24 22:46:47 +00:00
if ( strlen ( floor - > rhs . unix_ds . path ) = = 0 ) return NULL ;
2004-10-21 21:02:51 +00:00
return talloc_strdup ( mem_ctx , floor - > rhs . unix_ds . path ) ;
case EPM_PROTOCOL_NULL :
return NULL ;
2005-01-05 02:01:19 +00:00
default :
DEBUG ( 0 , ( " Unsupported lhs protocol %d \n " , floor - > lhs . protocol ) ) ;
break ;
2004-10-21 21:02:51 +00:00
}
return NULL ;
}
2004-10-25 11:28:09 +00:00
static NTSTATUS dcerpc_floor_set_rhs_data ( TALLOC_CTX * mem_ctx , struct epm_floor * floor , const char * data )
2004-10-21 19:54:38 +00:00
{
switch ( floor - > lhs . protocol ) {
case EPM_PROTOCOL_TCP :
floor - > rhs . tcp . port = atoi ( data ) ;
return NT_STATUS_OK ;
case EPM_PROTOCOL_UDP :
floor - > rhs . udp . port = atoi ( data ) ;
return NT_STATUS_OK ;
case EPM_PROTOCOL_HTTP :
floor - > rhs . http . port = atoi ( data ) ;
return NT_STATUS_OK ;
case EPM_PROTOCOL_IP :
if ( strlen ( data ) > 0 ) {
2004-10-27 03:50:52 +00:00
floor - > rhs . ip . address = ntohl ( interpret_addr ( data ) ) ;
2004-10-27 01:30:59 +00:00
} else {
floor - > rhs . ip . address = 0 ;
2004-10-21 19:54:38 +00:00
}
return NT_STATUS_OK ;
case EPM_PROTOCOL_NCACN :
floor - > rhs . ncacn . minor_version = 0 ;
return NT_STATUS_OK ;
case EPM_PROTOCOL_NCADG :
floor - > rhs . ncadg . minor_version = 0 ;
return NT_STATUS_OK ;
case EPM_PROTOCOL_SMB :
floor - > rhs . smb . unc = talloc_strdup ( mem_ctx , data ) ;
if ( ! floor - > rhs . smb . unc ) {
return NT_STATUS_NO_MEMORY ;
}
return NT_STATUS_OK ;
case EPM_PROTOCOL_PIPE :
floor - > rhs . pipe . path = talloc_strdup ( mem_ctx , data ) ;
if ( ! floor - > rhs . pipe . path ) {
return NT_STATUS_NO_MEMORY ;
}
return NT_STATUS_OK ;
case EPM_PROTOCOL_NETBIOS :
floor - > rhs . netbios . name = talloc_strdup ( mem_ctx , data ) ;
if ( ! floor - > rhs . netbios . name ) {
return NT_STATUS_NO_MEMORY ;
}
return NT_STATUS_OK ;
case EPM_PROTOCOL_NCALRPC :
return NT_STATUS_OK ;
case EPM_PROTOCOL_VINES_SPP :
floor - > rhs . vines_spp . port = atoi ( data ) ;
return NT_STATUS_OK ;
case EPM_PROTOCOL_VINES_IPC :
floor - > rhs . vines_ipc . port = atoi ( data ) ;
return NT_STATUS_OK ;
case EPM_PROTOCOL_STREETTALK :
floor - > rhs . streettalk . streettalk = talloc_strdup ( mem_ctx , data ) ;
if ( ! floor - > rhs . streettalk . streettalk ) {
return NT_STATUS_NO_MEMORY ;
}
return NT_STATUS_OK ;
case EPM_PROTOCOL_UNIX_DS :
floor - > rhs . unix_ds . path = talloc_strdup ( mem_ctx , data ) ;
if ( ! floor - > rhs . unix_ds . path ) {
return NT_STATUS_NO_MEMORY ;
}
return NT_STATUS_OK ;
case EPM_PROTOCOL_NULL :
return NT_STATUS_OK ;
2005-01-05 02:01:19 +00:00
default :
DEBUG ( 0 , ( " Unsupported lhs protocol %d \n " , floor - > lhs . protocol ) ) ;
break ;
2004-10-21 19:54:38 +00:00
}
return NT_STATUS_NOT_SUPPORTED ;
}
2004-11-07 19:28:18 +00:00
enum dcerpc_transport_t dcerpc_transport_by_endpoint_protocol ( int prot )
{
int i ;
/* Find a transport that has 'prot' as 4th protocol */
for ( i = 0 ; i < ARRAY_SIZE ( transports ) ; i + + ) {
if ( transports [ i ] . num_protocols > = 2 & &
transports [ i ] . protseq [ 1 ] = = prot ) {
return transports [ i ] . transport ;
}
}
/* Unknown transport */
return - 1 ;
}
2004-10-24 13:00:51 +00:00
enum dcerpc_transport_t dcerpc_transport_by_tower ( struct epm_tower * tower )
2004-10-21 21:02:51 +00:00
{
int i ;
/* Find a transport that matches this tower */
for ( i = 0 ; i < ARRAY_SIZE ( transports ) ; i + + ) {
int j ;
if ( transports [ i ] . num_protocols ! = tower - > num_floors - 2 ) {
continue ;
}
2004-10-24 13:00:51 +00:00
2004-10-21 21:02:51 +00:00
for ( j = 0 ; j < transports [ i ] . num_protocols ; j + + ) {
if ( transports [ i ] . protseq [ j ] ! = tower - > floors [ j + 2 ] . lhs . protocol ) {
break ;
}
}
if ( j = = transports [ i ] . num_protocols ) {
2004-10-24 13:00:51 +00:00
return transports [ i ] . transport ;
2004-10-21 21:02:51 +00:00
}
}
2004-10-24 13:00:51 +00:00
/* Unknown transport */
return - 1 ;
}
NTSTATUS dcerpc_binding_from_tower ( TALLOC_CTX * mem_ctx , struct epm_tower * tower , struct dcerpc_binding * binding )
{
ZERO_STRUCT ( binding - > object ) ;
binding - > options = NULL ;
binding - > host = NULL ;
binding - > flags = 0 ;
binding - > transport = dcerpc_transport_by_tower ( tower ) ;
2004-10-21 21:02:51 +00:00
if ( binding - > transport = = - 1 ) {
return NT_STATUS_NOT_SUPPORTED ;
}
if ( tower - > num_floors < 1 ) {
return NT_STATUS_OK ;
}
/* Set object uuid */
2004-10-21 21:57:30 +00:00
binding - > object = tower - > floors [ 0 ] . lhs . info . uuid . uuid ;
2004-10-22 10:52:57 +00:00
binding - > object_version = tower - > floors [ 0 ] . lhs . info . uuid . version ;
2004-10-21 21:02:51 +00:00
/* Ignore floor 1, it contains the NDR version info */
2004-10-24 22:46:47 +00:00
binding - > options = NULL ;
2004-10-21 21:02:51 +00:00
/* Set endpoint */
2004-10-24 13:00:51 +00:00
if ( tower - > num_floors > = 4 ) {
2004-10-25 11:28:09 +00:00
binding - > endpoint = dcerpc_floor_get_rhs_data ( mem_ctx , & tower - > floors [ 3 ] ) ;
2004-10-21 21:02:51 +00:00
} else {
2004-10-24 22:46:47 +00:00
binding - > endpoint = NULL ;
2004-10-21 21:02:51 +00:00
}
/* Set network address */
2004-10-24 13:00:51 +00:00
if ( tower - > num_floors > = 5 ) {
2004-10-25 11:28:09 +00:00
binding - > host = dcerpc_floor_get_rhs_data ( mem_ctx , & tower - > floors [ 4 ] ) ;
2004-10-21 21:02:51 +00:00
}
return NT_STATUS_OK ;
}
2004-10-21 19:54:38 +00:00
2004-10-22 10:52:57 +00:00
NTSTATUS dcerpc_binding_build_tower ( TALLOC_CTX * mem_ctx , struct dcerpc_binding * binding , struct epm_tower * tower )
2004-10-21 19:54:38 +00:00
{
2005-01-05 02:01:19 +00:00
const enum epm_protocol * protseq = NULL ;
2004-10-21 19:54:38 +00:00
int num_protocols = - 1 , i ;
NTSTATUS status ;
/* Find transport */
for ( i = 0 ; i < ARRAY_SIZE ( transports ) ; i + + ) {
if ( transports [ i ] . transport = = binding - > transport ) {
protseq = transports [ i ] . protseq ;
num_protocols = transports [ i ] . num_protocols ;
break ;
}
}
if ( num_protocols = = - 1 ) {
DEBUG ( 0 , ( " Unable to find transport with id '%d' \n " , binding - > transport ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
2004-10-22 10:52:57 +00:00
tower - > num_floors = 2 + num_protocols ;
tower - > floors = talloc_array_p ( mem_ctx , struct epm_floor , tower - > num_floors ) ;
2004-10-21 19:54:38 +00:00
/* Floor 0 */
2004-10-22 10:52:57 +00:00
tower - > floors [ 0 ] . lhs . protocol = EPM_PROTOCOL_UUID ;
tower - > floors [ 0 ] . lhs . info . uuid . uuid = binding - > object ;
tower - > floors [ 0 ] . lhs . info . uuid . version = binding - > object_version ;
tower - > floors [ 0 ] . rhs . uuid . unknown = 0 ;
2004-10-21 19:54:38 +00:00
/* Floor 1 */
2004-10-22 10:52:57 +00:00
tower - > floors [ 1 ] . lhs . protocol = EPM_PROTOCOL_UUID ;
tower - > floors [ 1 ] . lhs . info . uuid . version = NDR_GUID_VERSION ;
tower - > floors [ 1 ] . rhs . uuid . unknown = 0 ;
status = GUID_from_string ( NDR_GUID , & tower - > floors [ 1 ] . lhs . info . uuid . uuid ) ;
2004-10-21 19:54:38 +00:00
if ( NT_STATUS_IS_ERR ( status ) ) {
return status ;
}
/* Floor 2 to num_protocols */
for ( i = 0 ; i < num_protocols ; i + + ) {
2004-10-22 10:52:57 +00:00
tower - > floors [ 2 + i ] . lhs . protocol = protseq [ i ] ;
tower - > floors [ 2 + i ] . lhs . info . lhs_data = data_blob_talloc ( mem_ctx , NULL , 0 ) ;
ZERO_STRUCT ( tower - > floors [ 2 + i ] . rhs ) ;
2004-10-25 11:28:09 +00:00
dcerpc_floor_set_rhs_data ( mem_ctx , & tower - > floors [ 2 + i ] , " " ) ;
2004-10-21 19:54:38 +00:00
}
2004-10-24 13:00:51 +00:00
/* The 4th floor contains the endpoint */
2004-10-24 22:46:47 +00:00
if ( num_protocols > = 2 & & binding - > endpoint ) {
2004-10-25 11:28:09 +00:00
status = dcerpc_floor_set_rhs_data ( mem_ctx , & tower - > floors [ 3 ] , binding - > endpoint ) ;
2004-10-21 19:54:38 +00:00
if ( NT_STATUS_IS_ERR ( status ) ) {
return status ;
}
}
2004-10-24 14:57:16 +00:00
2004-10-24 13:00:51 +00:00
/* The 5th contains the network address */
if ( num_protocols > = 3 & & binding - > host ) {
2004-10-25 11:28:09 +00:00
status = dcerpc_floor_set_rhs_data ( mem_ctx , & tower - > floors [ 4 ] , binding - > host ) ;
2004-10-21 19:54:38 +00:00
if ( NT_STATUS_IS_ERR ( status ) ) {
return status ;
}
}
return NT_STATUS_OK ;
}
2004-10-24 23:12:13 +00:00
NTSTATUS dcerpc_epm_map_binding ( TALLOC_CTX * mem_ctx , struct dcerpc_binding * binding ,
2004-10-24 22:46:47 +00:00
const char * uuid , uint_t version )
{
struct dcerpc_pipe * p ;
NTSTATUS status ;
struct epm_Map r ;
struct policy_handle handle ;
struct GUID guid ;
struct epm_twr_t twr , * twr_r ;
struct dcerpc_binding epmapper_binding ;
2004-11-04 01:25:56 +00:00
const struct dcerpc_interface_table * table = idl_iface_by_uuid ( uuid ) ;
int i ;
/* First, check if there is a default endpoint specified in the IDL */
2004-10-24 22:46:47 +00:00
2004-11-04 01:25:56 +00:00
if ( table ) {
struct dcerpc_binding default_binding ;
/* Find one of the default pipes for this interface */
for ( i = 0 ; i < table - > endpoints - > count ; i + + ) {
status = dcerpc_parse_binding ( mem_ctx , table - > endpoints - > names [ i ] , & default_binding ) ;
2004-10-24 22:46:47 +00:00
2004-11-04 01:25:56 +00:00
if ( NT_STATUS_IS_OK ( status ) & & default_binding . transport = = binding - > transport & & default_binding . endpoint ) {
binding - > endpoint = talloc_strdup ( mem_ctx , default_binding . endpoint ) ;
return NT_STATUS_OK ;
}
2004-10-24 22:46:47 +00:00
}
}
2004-11-04 01:25:56 +00:00
2004-10-24 22:46:47 +00:00
ZERO_STRUCT ( epmapper_binding ) ;
epmapper_binding . transport = binding - > transport ;
epmapper_binding . host = binding - > host ;
epmapper_binding . options = NULL ;
epmapper_binding . flags = 0 ;
epmapper_binding . endpoint = NULL ;
status = dcerpc_pipe_connect_b ( & p ,
& epmapper_binding ,
DCERPC_EPMAPPER_UUID ,
DCERPC_EPMAPPER_VERSION ,
NULL , NULL , NULL ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
ZERO_STRUCT ( handle ) ;
ZERO_STRUCT ( guid ) ;
status = GUID_from_string ( uuid , & binding - > object ) ;
if ( NT_STATUS_IS_ERR ( status ) ) {
return status ;
}
binding - > object_version = version ;
status = dcerpc_binding_build_tower ( p , binding , & twr . tower ) ;
if ( NT_STATUS_IS_ERR ( status ) ) {
return status ;
}
/* with some nice pretty paper around it of course */
r . in . object = & guid ;
r . in . map_tower = & twr ;
r . in . entry_handle = & handle ;
r . in . max_towers = 1 ;
r . out . entry_handle = & handle ;
status = dcerpc_epm_Map ( p , p , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
dcerpc_pipe_close ( p ) ;
return status ;
}
if ( r . out . result ! = 0 | | r . out . num_towers ! = 1 ) {
dcerpc_pipe_close ( p ) ;
return NT_STATUS_PORT_UNREACHABLE ;
}
twr_r = r . out . towers [ 0 ] . twr ;
if ( ! twr_r ) {
dcerpc_pipe_close ( p ) ;
return NT_STATUS_PORT_UNREACHABLE ;
}
if ( twr_r - > tower . num_floors ! = twr . tower . num_floors | |
twr_r - > tower . floors [ 3 ] . lhs . protocol ! = twr . tower . floors [ 3 ] . lhs . protocol ) {
dcerpc_pipe_close ( p ) ;
return NT_STATUS_PORT_UNREACHABLE ;
}
2004-10-25 11:28:09 +00:00
binding - > endpoint = dcerpc_floor_get_rhs_data ( mem_ctx , & twr_r - > tower . floors [ 3 ] ) ;
2004-10-24 22:46:47 +00:00
dcerpc_pipe_close ( p ) ;
return NT_STATUS_OK ;
}
2003-12-15 03:29:55 +00:00
2003-12-17 03:38:06 +00:00
/* open a rpc connection to a rpc pipe on SMB using the binding
2003-12-15 03:29:55 +00:00
structure to determine the endpoint and options */
2005-01-09 08:34:05 +00:00
static NTSTATUS dcerpc_pipe_connect_ncacn_np ( struct dcerpc_pipe * * pp ,
2003-12-15 03:29:55 +00:00
struct dcerpc_binding * binding ,
const char * pipe_uuid ,
2004-05-25 16:24:13 +00:00
uint32_t pipe_version ,
2003-12-15 03:29:55 +00:00
const char * domain ,
const char * username ,
const char * password )
{
2005-01-09 08:34:05 +00:00
struct dcerpc_pipe * p ;
2003-12-15 03:29:55 +00:00
NTSTATUS status ;
BOOL retry ;
2004-08-04 13:23:35 +00:00
struct smbcli_state * cli ;
2004-11-01 23:35:15 +00:00
const char * pipe_name = NULL ;
2005-01-09 08:34:05 +00:00
TALLOC_CTX * tmp_ctx ;
* pp = NULL ;
p = dcerpc_pipe_init ( NULL ) ;
if ( p = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
tmp_ctx = talloc_new ( p ) ;
2003-12-15 03:29:55 +00:00
2004-11-04 01:25:56 +00:00
/* Look up identifier using the epmapper */
2004-10-24 22:46:47 +00:00
if ( ! binding - > endpoint ) {
2005-01-09 08:34:05 +00:00
status = dcerpc_epm_map_binding ( tmp_ctx , binding , pipe_uuid , pipe_version ) ;
2004-11-04 01:25:56 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Failed to map DCERPC/TCP NCACN_NP pipe for '%s' - %s \n " ,
pipe_uuid , nt_errstr ( status ) ) ) ;
2005-01-09 08:34:05 +00:00
talloc_free ( p ) ;
2004-11-04 01:25:56 +00:00
return status ;
2004-11-01 23:35:15 +00:00
}
2004-11-07 12:52:53 +00:00
DEBUG ( 1 , ( " Mapped to DCERPC/NP pipe %s \n " , binding - > endpoint ) ) ;
2003-12-15 03:29:55 +00:00
}
2004-11-04 01:25:56 +00:00
pipe_name = binding - > endpoint ;
2004-10-18 16:07:08 +00:00
if ( ! strncasecmp ( pipe_name , " /pipe/ " , 6 ) | |
2005-01-09 08:34:05 +00:00
! strncasecmp ( pipe_name , " \\ pipe \\ " , 6 ) ) {
pipe_name + = 6 ;
2003-12-15 03:29:55 +00:00
}
2004-10-18 16:25:36 +00:00
if ( pipe_name [ 0 ] ! = ' \\ ' ) {
2005-01-09 08:34:05 +00:00
pipe_name = talloc_asprintf ( tmp_ctx , " \\ %s " , pipe_name ) ;
2004-10-18 16:25:36 +00:00
}
2004-10-18 15:18:05 +00:00
2004-10-30 09:23:39 +00:00
if ( ! username | | ! username [ 0 ] | |
( binding - > flags & DCERPC_SCHANNEL_ANY ) ) {
2005-01-09 08:34:05 +00:00
status = smbcli_full_connection ( p - > conn , & cli , lp_netbios_name ( ) ,
binding - > host , NULL ,
" ipc$ " , " ????? " ,
" " , " " , NULL , 0 , & retry ) ;
2004-06-06 07:14:10 +00:00
} else {
2005-01-09 08:34:05 +00:00
status = smbcli_full_connection ( p - > conn , & cli , lp_netbios_name ( ) ,
binding - > host , NULL ,
" ipc$ " , " ????? " ,
username , domain ,
password , 0 , & retry ) ;
2004-06-06 07:14:10 +00:00
}
2003-12-15 03:29:55 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2003-12-16 10:57:17 +00:00
DEBUG ( 0 , ( " Failed to connect to %s - %s \n " , binding - > host , nt_errstr ( status ) ) ) ;
2005-01-09 08:34:05 +00:00
talloc_free ( p ) ;
2003-12-15 03:29:55 +00:00
return status ;
}
2005-01-09 08:34:05 +00:00
status = dcerpc_pipe_open_smb ( p - > conn , cli - > tree , pipe_name ) ;
2003-12-15 03:29:55 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2003-12-16 10:57:17 +00:00
DEBUG ( 0 , ( " Failed to open pipe %s - %s \n " , pipe_name , nt_errstr ( status ) ) ) ;
2005-01-09 08:34:05 +00:00
talloc_free ( p ) ;
2004-11-05 06:56:39 +00:00
return status ;
}
2003-12-15 03:29:55 +00:00
2005-01-09 08:34:05 +00:00
p - > conn - > flags = binding - > flags ;
2003-12-15 03:29:55 +00:00
2004-06-07 21:30:17 +00:00
/* remember the binding string for possible secondary connections */
2005-01-09 08:34:05 +00:00
p - > conn - > binding_string = dcerpc_binding_string ( p , binding ) ;
2004-11-05 06:56:39 +00:00
2004-06-07 21:30:17 +00:00
if ( username & & username [ 0 ] & & ( binding - > flags & DCERPC_SCHANNEL_ANY ) ) {
2005-01-09 08:34:05 +00:00
status = dcerpc_bind_auth_schannel ( p , pipe_uuid , pipe_version ,
2004-06-06 07:14:10 +00:00
domain , username , password ) ;
2004-10-01 05:19:51 +00:00
} else if ( username & & username [ 0 ] & &
( binding - > flags & ( DCERPC_CONNECT | DCERPC_SIGN | DCERPC_SEAL ) ) ) {
2005-01-09 08:34:05 +00:00
status = dcerpc_bind_auth_ntlm ( p , pipe_uuid , pipe_version , domain , username , password ) ;
2003-12-15 03:29:55 +00:00
} else {
2005-01-09 08:34:05 +00:00
status = dcerpc_bind_auth_none ( p , pipe_uuid , pipe_version ) ;
2004-09-11 15:11:36 +00:00
2003-12-15 03:29:55 +00:00
}
2004-02-10 10:22:12 +00:00
2003-12-15 03:29:55 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2003-12-16 10:57:17 +00:00
DEBUG ( 0 , ( " Failed to bind to uuid %s - %s \n " , pipe_uuid , nt_errstr ( status ) ) ) ;
2005-01-09 08:34:05 +00:00
talloc_free ( p ) ;
2003-12-15 03:29:55 +00:00
return status ;
}
2005-01-09 08:34:05 +00:00
( * pp ) = p ;
talloc_free ( tmp_ctx ) ;
2003-12-15 03:29:55 +00:00
return NT_STATUS_OK ;
}
2004-10-24 14:57:16 +00:00
/* open a rpc connection to a rpc pipe on SMP using the binding
structure to determine the endpoint and options */
2005-01-09 08:34:05 +00:00
static NTSTATUS dcerpc_pipe_connect_ncalrpc ( struct dcerpc_pipe * * pp ,
struct dcerpc_binding * binding ,
const char * pipe_uuid ,
uint32_t pipe_version ,
const char * domain ,
const char * username ,
const char * password )
2004-10-24 14:57:16 +00:00
{
NTSTATUS status ;
2005-01-09 08:34:05 +00:00
struct dcerpc_pipe * p ;
TALLOC_CTX * tmp_ctx ;
( * pp ) = NULL ;
p = dcerpc_pipe_init ( NULL ) ;
if ( p = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
tmp_ctx = talloc_new ( p ) ;
2004-10-24 14:57:16 +00:00
2004-10-24 16:31:00 +00:00
/* Look up identifier using the epmapper */
2004-10-24 22:46:47 +00:00
if ( ! binding - > endpoint ) {
2005-01-09 08:34:05 +00:00
status = dcerpc_epm_map_binding ( tmp_ctx , binding , pipe_uuid , pipe_version ) ;
2004-10-24 16:31:00 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Failed to map DCERPC/TCP NCALRPC identifier for '%s' - %s \n " ,
pipe_uuid , nt_errstr ( status ) ) ) ;
2005-01-09 08:34:05 +00:00
talloc_free ( p ) ;
2004-10-24 16:31:00 +00:00
return status ;
}
2004-11-07 12:52:53 +00:00
DEBUG ( 1 , ( " Mapped to DCERPC/LRPC identifier %s \n " , binding - > endpoint ) ) ;
2004-10-24 16:31:00 +00:00
}
2005-01-09 08:34:05 +00:00
status = dcerpc_pipe_open_pipe ( p - > conn , binding - > endpoint ) ;
2004-10-24 14:57:16 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2005-01-09 08:34:05 +00:00
DEBUG ( 0 , ( " Failed to open ncalrpc pipe '%s' - %s \n " ,
binding - > endpoint , nt_errstr ( status ) ) ) ;
talloc_free ( p ) ;
2004-10-24 16:31:00 +00:00
return status ;
2005-01-09 08:34:05 +00:00
}
2004-10-24 14:57:16 +00:00
2005-01-09 08:34:05 +00:00
p - > conn - > flags = binding - > flags ;
2004-10-24 14:57:16 +00:00
/* remember the binding string for possible secondary connections */
2005-01-09 08:34:05 +00:00
p - > conn - > binding_string = dcerpc_binding_string ( p , binding ) ;
2004-10-24 14:57:16 +00:00
if ( username & & username [ 0 ] & & ( binding - > flags & DCERPC_SCHANNEL_ANY ) ) {
2005-01-09 08:34:05 +00:00
status = dcerpc_bind_auth_schannel ( p , pipe_uuid , pipe_version ,
2004-10-24 14:57:16 +00:00
domain , username , password ) ;
} else if ( username & & username [ 0 ] ) {
2005-01-09 08:34:05 +00:00
status = dcerpc_bind_auth_ntlm ( p , pipe_uuid , pipe_version , domain , username , password ) ;
2004-10-24 14:57:16 +00:00
} else {
2005-01-09 08:34:05 +00:00
status = dcerpc_bind_auth_none ( p , pipe_uuid , pipe_version ) ;
2004-10-24 14:57:16 +00:00
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
2005-01-09 08:34:05 +00:00
DEBUG ( 0 , ( " Failed to bind to uuid %s - %s \n " , pipe_uuid , nt_errstr ( status ) ) ) ;
talloc_free ( p ) ;
2004-10-24 14:57:16 +00:00
return status ;
}
2005-01-09 08:34:05 +00:00
( * pp ) = p ;
talloc_free ( tmp_ctx ) ;
return status ;
2004-10-24 14:57:16 +00:00
}
/* open a rpc connection to a rpc pipe on SMP using the binding
structure to determine the endpoint and options */
2005-01-09 08:34:05 +00:00
static NTSTATUS dcerpc_pipe_connect_ncacn_unix_stream ( struct dcerpc_pipe * * pp ,
struct dcerpc_binding * binding ,
const char * pipe_uuid ,
uint32_t pipe_version ,
const char * domain ,
const char * username ,
const char * password )
2004-10-24 14:57:16 +00:00
{
NTSTATUS status ;
2005-01-09 08:34:05 +00:00
struct dcerpc_pipe * p ;
( * pp ) = NULL ;
2004-10-24 14:57:16 +00:00
2004-10-24 22:46:47 +00:00
if ( ! binding - > endpoint ) {
2004-10-24 14:57:16 +00:00
DEBUG ( 0 , ( " Path to unix socket not specified \n " ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
2005-01-09 08:34:05 +00:00
p = dcerpc_pipe_init ( NULL ) ;
if ( p = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
status = dcerpc_pipe_open_unix_stream ( p - > conn , binding - > endpoint ) ;
2004-10-24 14:57:16 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-10-27 03:15:42 +00:00
DEBUG ( 0 , ( " Failed to open unix socket %s - %s \n " ,
binding - > endpoint , nt_errstr ( status ) ) ) ;
2005-01-09 08:34:05 +00:00
talloc_free ( p ) ;
2004-10-24 14:57:16 +00:00
return status ;
2004-10-27 03:15:42 +00:00
}
2004-10-24 14:57:16 +00:00
2005-01-09 08:34:05 +00:00
p - > conn - > flags = binding - > flags ;
2004-10-24 14:57:16 +00:00
/* remember the binding string for possible secondary connections */
2005-01-09 08:34:05 +00:00
p - > conn - > binding_string = dcerpc_binding_string ( p , binding ) ;
2004-10-24 14:57:16 +00:00
if ( username & & username [ 0 ] & & ( binding - > flags & DCERPC_SCHANNEL_ANY ) ) {
2005-01-09 08:34:05 +00:00
status = dcerpc_bind_auth_schannel ( p , pipe_uuid , pipe_version ,
2004-10-24 14:57:16 +00:00
domain , username , password ) ;
} else if ( username & & username [ 0 ] ) {
2005-01-09 08:34:05 +00:00
status = dcerpc_bind_auth_ntlm ( p , pipe_uuid , pipe_version , domain , username , password ) ;
2004-10-24 14:57:16 +00:00
} else {
2005-01-09 08:34:05 +00:00
status = dcerpc_bind_auth_none ( p , pipe_uuid , pipe_version ) ;
2004-10-24 14:57:16 +00:00
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
2005-01-09 08:34:05 +00:00
DEBUG ( 0 , ( " Failed to bind to uuid %s - %s \n " , pipe_uuid , nt_errstr ( status ) ) ) ;
talloc_free ( p ) ;
2004-10-24 14:57:16 +00:00
return status ;
}
2005-01-09 08:34:05 +00:00
( * pp ) = p ;
2004-10-24 14:57:16 +00:00
2005-01-09 08:34:05 +00:00
return status ;
2004-10-24 14:57:16 +00:00
}
2003-12-15 03:29:55 +00:00
/* open a rpc connection to a rpc pipe on SMP using the binding
structure to determine the endpoint and options */
2005-01-09 08:34:05 +00:00
static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp ( struct dcerpc_pipe * * pp ,
2003-12-15 03:29:55 +00:00
struct dcerpc_binding * binding ,
const char * pipe_uuid ,
2004-05-25 16:24:13 +00:00
uint32_t pipe_version ,
2003-12-15 03:29:55 +00:00
const char * domain ,
const char * username ,
const char * password )
{
NTSTATUS status ;
2004-05-25 16:24:13 +00:00
uint32_t port = 0 ;
2005-01-09 08:34:05 +00:00
struct dcerpc_pipe * p ;
TALLOC_CTX * tmp_ctx ;
( * pp ) = NULL ;
p = dcerpc_pipe_init ( NULL ) ;
if ( p = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
tmp_ctx = talloc_new ( p ) ;
2003-12-15 03:29:55 +00:00
2004-10-24 22:46:47 +00:00
if ( ! binding - > endpoint ) {
2005-01-09 08:34:05 +00:00
status = dcerpc_epm_map_binding ( tmp_ctx , binding ,
pipe_uuid , pipe_version ) ;
2003-12-15 03:29:55 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Failed to map DCERPC/TCP port for '%s' - %s \n " ,
pipe_uuid , nt_errstr ( status ) ) ) ;
2005-01-09 08:34:05 +00:00
talloc_free ( p ) ;
2003-12-15 03:29:55 +00:00
return status ;
}
2004-10-24 22:46:47 +00:00
DEBUG ( 1 , ( " Mapped to DCERPC/TCP port %s \n " , binding - > endpoint ) ) ;
2003-12-15 03:29:55 +00:00
}
2004-10-24 22:46:47 +00:00
port = atoi ( binding - > endpoint ) ;
2005-01-09 08:34:05 +00:00
status = dcerpc_pipe_open_tcp ( p - > conn , binding - > host , port ) ;
2003-12-15 03:29:55 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-11-17 00:31:56 +00:00
DEBUG ( 0 , ( " Failed to connect to %s:%d - %s \n " ,
binding - > host , port , nt_errstr ( status ) ) ) ;
2005-01-09 08:34:05 +00:00
talloc_free ( p ) ;
2003-12-15 03:29:55 +00:00
return status ;
}
2005-01-09 08:34:05 +00:00
p - > conn - > flags = binding - > flags ;
2003-12-15 03:29:55 +00:00
2004-06-07 21:30:17 +00:00
/* remember the binding string for possible secondary connections */
2005-01-09 08:34:05 +00:00
p - > conn - > binding_string = dcerpc_binding_string ( p , binding ) ;
2004-06-07 21:30:17 +00:00
if ( username & & username [ 0 ] & & ( binding - > flags & DCERPC_SCHANNEL_ANY ) ) {
2005-01-09 08:34:05 +00:00
status = dcerpc_bind_auth_schannel ( p , pipe_uuid , pipe_version ,
2004-06-06 07:14:10 +00:00
domain , username , password ) ;
2004-09-25 07:25:51 +00:00
} else if ( username & & username [ 0 ] ) {
2005-01-09 08:34:05 +00:00
status = dcerpc_bind_auth_ntlm ( p , pipe_uuid , pipe_version , domain , username , password ) ;
2004-06-07 21:30:17 +00:00
} else {
2005-01-09 08:34:05 +00:00
status = dcerpc_bind_auth_none ( p , pipe_uuid , pipe_version ) ;
2003-12-15 03:29:55 +00:00
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-06-06 07:14:10 +00:00
DEBUG ( 0 , ( " Failed to bind to uuid %s - %s \n " ,
pipe_uuid , nt_errstr ( status ) ) ) ;
2005-01-09 08:34:05 +00:00
talloc_free ( p ) ;
2003-12-15 03:29:55 +00:00
return status ;
}
2005-01-09 08:34:05 +00:00
( * pp ) = p ;
talloc_free ( tmp_ctx ) ;
2003-12-15 03:29:55 +00:00
return status ;
}
/* open a rpc connection to a rpc pipe, using the specified
binding structure to determine the endpoint and options */
2005-01-09 08:34:05 +00:00
NTSTATUS dcerpc_pipe_connect_b ( struct dcerpc_pipe * * pp ,
2003-12-15 03:29:55 +00:00
struct dcerpc_binding * binding ,
const char * pipe_uuid ,
2004-05-25 16:24:13 +00:00
uint32_t pipe_version ,
2003-12-15 03:29:55 +00:00
const char * domain ,
const char * username ,
const char * password )
{
NTSTATUS status = NT_STATUS_INVALID_PARAMETER ;
switch ( binding - > transport ) {
case NCACN_NP :
2005-01-09 08:34:05 +00:00
status = dcerpc_pipe_connect_ncacn_np ( pp , binding , pipe_uuid , pipe_version ,
2003-12-15 03:29:55 +00:00
domain , username , password ) ;
break ;
case NCACN_IP_TCP :
2005-01-09 08:34:05 +00:00
status = dcerpc_pipe_connect_ncacn_ip_tcp ( pp , binding , pipe_uuid , pipe_version ,
2003-12-15 03:29:55 +00:00
domain , username , password ) ;
break ;
2004-10-24 14:57:16 +00:00
case NCACN_UNIX_STREAM :
2005-01-09 08:34:05 +00:00
status = dcerpc_pipe_connect_ncacn_unix_stream ( pp , binding , pipe_uuid , pipe_version ,
domain , username , password ) ;
2004-10-24 14:57:16 +00:00
break ;
case NCALRPC :
2005-01-09 08:34:05 +00:00
status = dcerpc_pipe_connect_ncalrpc ( pp , binding , pipe_uuid , pipe_version ,
domain , username , password ) ;
2004-10-24 14:57:16 +00:00
break ;
2004-10-21 12:47:02 +00:00
default :
return NT_STATUS_NOT_SUPPORTED ;
2003-12-15 03:29:55 +00:00
}
return status ;
}
/* open a rpc connection to a rpc pipe, using the specified string
binding to determine the endpoint and options */
2005-01-09 08:34:05 +00:00
NTSTATUS dcerpc_pipe_connect ( struct dcerpc_pipe * * pp ,
2003-12-15 03:29:55 +00:00
const char * binding ,
const char * pipe_uuid ,
2004-05-25 16:24:13 +00:00
uint32_t pipe_version ,
2003-12-15 03:29:55 +00:00
const char * domain ,
const char * username ,
const char * password )
{
struct dcerpc_binding b ;
NTSTATUS status ;
2005-01-09 08:34:05 +00:00
TALLOC_CTX * tmp_ctx ;
2003-12-15 03:29:55 +00:00
2005-01-09 08:34:05 +00:00
tmp_ctx = talloc_new ( NULL ) ;
2003-12-15 03:29:55 +00:00
2005-01-09 08:34:05 +00:00
status = dcerpc_parse_binding ( tmp_ctx , binding , & b ) ;
2003-12-15 03:29:55 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2003-12-15 03:41:08 +00:00
DEBUG ( 0 , ( " Failed to parse dcerpc binding '%s' \n " , binding ) ) ;
2005-01-09 08:34:05 +00:00
talloc_free ( tmp_ctx ) ;
2003-12-15 03:29:55 +00:00
return status ;
}
2005-01-09 08:34:05 +00:00
DEBUG ( 3 , ( " Using binding %s \n " , dcerpc_binding_string ( tmp_ctx , & b ) ) ) ;
2003-12-16 10:57:17 +00:00
2005-01-09 08:34:05 +00:00
status = dcerpc_pipe_connect_b ( pp , & b , pipe_uuid , pipe_version , domain , username , password ) ;
talloc_free ( tmp_ctx ) ;
2003-12-15 03:29:55 +00:00
return status ;
}
2004-01-20 06:07:09 +00:00
/*
2004-06-06 07:14:10 +00:00
create a secondary dcerpc connection from a primary connection
2004-06-05 05:01:38 +00:00
2004-06-06 07:14:10 +00:00
if the primary is a SMB connection then the secondary connection
will be on the same SMB connection , but use a new fnum
2004-01-20 06:07:09 +00:00
*/
2004-06-06 07:14:10 +00:00
NTSTATUS dcerpc_secondary_connection ( struct dcerpc_pipe * p , struct dcerpc_pipe * * p2 ,
const char * pipe_name ,
const char * pipe_uuid ,
uint32_t pipe_version )
2004-01-20 06:07:09 +00:00
{
2004-08-04 13:23:35 +00:00
struct smbcli_tree * tree ;
2004-06-06 07:14:10 +00:00
NTSTATUS status = NT_STATUS_INVALID_PARAMETER ;
struct dcerpc_binding b ;
2004-01-20 06:07:09 +00:00
2005-01-09 08:34:05 +00:00
( * p2 ) = dcerpc_pipe_init ( p ) ;
if ( * p2 = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
switch ( p - > conn - > transport . transport ) {
2004-06-06 07:14:10 +00:00
case NCACN_NP :
2005-01-09 08:34:05 +00:00
tree = dcerpc_smb_tree ( p - > conn ) ;
2004-06-06 07:14:10 +00:00
if ( ! tree ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2005-01-09 08:34:05 +00:00
status = dcerpc_pipe_open_smb ( ( * p2 ) - > conn , tree , pipe_name ) ;
2004-06-06 07:14:10 +00:00
break ;
case NCACN_IP_TCP :
2005-01-09 08:34:05 +00:00
status = dcerpc_parse_binding ( p , p - > conn - > binding_string , & b ) ;
2004-06-06 07:14:10 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
b . flags & = ~ DCERPC_AUTH_OPTIONS ;
2005-01-09 08:34:05 +00:00
status = dcerpc_pipe_open_tcp ( ( * p2 ) - > conn , b . host , atoi ( b . endpoint ) ) ;
2004-06-06 07:14:10 +00:00
break ;
2004-10-30 11:48:08 +00:00
case NCALRPC :
2005-01-09 08:34:05 +00:00
status = dcerpc_parse_binding ( p , p - > conn - > binding_string , & b ) ;
2004-10-30 11:48:08 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
b . flags & = ~ DCERPC_AUTH_OPTIONS ;
2005-01-09 08:34:05 +00:00
status = dcerpc_pipe_open_pipe ( ( * p2 ) - > conn , b . endpoint ) ;
2004-10-30 11:48:08 +00:00
break ;
2004-10-21 12:47:02 +00:00
default :
return NT_STATUS_NOT_SUPPORTED ;
2004-01-20 06:07:09 +00:00
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
2005-01-09 08:34:05 +00:00
talloc_free ( * p2 ) ;
2004-06-06 07:14:10 +00:00
return status ;
}
2005-01-09 08:34:05 +00:00
( * p2 ) - > conn - > flags = p - > conn - > flags ;
2004-01-20 06:07:09 +00:00
status = dcerpc_bind_auth_none ( * p2 , pipe_uuid , pipe_version ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2005-01-09 08:34:05 +00:00
talloc_free ( * p2 ) ;
2004-01-20 06:07:09 +00:00
return status ;
}
return NT_STATUS_OK ;
}
2004-04-07 07:20:53 +00:00
2005-01-09 08:34:05 +00:00
NTSTATUS dcerpc_generic_session_key ( struct dcerpc_connection * c ,
2004-09-25 12:48:56 +00:00
DATA_BLOB * session_key )
2004-09-11 15:11:36 +00:00
{
/* this took quite a few CPU cycles to find ... */
2004-10-21 19:54:38 +00:00
session_key - > data = discard_const_p ( unsigned char , " SystemLibraryDTC " ) ;
2004-09-11 15:11:36 +00:00
session_key - > length = 16 ;
return NT_STATUS_OK ;
}
2004-04-07 07:20:53 +00:00
/*
2004-09-11 15:11:36 +00:00
fetch the user session key - may be default ( above ) or the SMB session key
2004-04-07 07:20:53 +00:00
*/
NTSTATUS dcerpc_fetch_session_key ( struct dcerpc_pipe * p ,
2004-05-09 12:42:18 +00:00
DATA_BLOB * session_key )
2004-04-07 07:20:53 +00:00
{
2005-01-09 08:34:05 +00:00
return p - > conn - > security_state . session_key ( p - > conn , session_key ) ;
2004-04-07 07:20:53 +00:00
}
2004-06-14 08:12:50 +00:00
/*
log a rpc packet in a format suitable for ndrdump . This is especially useful
for sealed packets , where ethereal cannot easily see the contents
this triggers on a debug level of > = 10
*/
void dcerpc_log_packet ( const struct dcerpc_interface_table * ndr ,
uint32_t opnum , uint32_t flags , DATA_BLOB * pkt )
{
const int num_examples = 20 ;
int i ;
if ( DEBUGLEVEL < 10 ) return ;
for ( i = 0 ; i < num_examples ; i + + ) {
char * name = NULL ;
asprintf ( & name , " %s/rpclog/%s-%u.%d.%s " ,
lp_lockdir ( ) , ndr - > name , opnum , i ,
( flags & NDR_IN ) ? " in " : " out " ) ;
if ( name = = NULL ) {
return ;
}
if ( ! file_exist ( name , NULL ) ) {
if ( file_save ( name , pkt - > data , pkt - > length ) ) {
DEBUG ( 10 , ( " Logged rpc packet to %s \n " , name ) ) ;
}
free ( name ) ;
break ;
}
free ( name ) ;
}
}
2005-01-09 09:38:16 +00:00
/*
create a secondary context from a primary connection
this uses dcerpc_alter_context ( ) to create a new dcerpc context_id
*/
NTSTATUS dcerpc_secondary_context ( struct dcerpc_pipe * p , struct dcerpc_pipe * * pp2 ,
uint32_t context_id ,
const char * pipe_uuid ,
uint32_t pipe_version )
{
NTSTATUS status ;
struct dcerpc_pipe * p2 ;
p2 = talloc_zero ( p , struct dcerpc_pipe ) ;
if ( p2 = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
p2 - > conn = talloc_reference ( p2 , p - > conn ) ;
p2 - > context_id = context_id ;
status = GUID_from_string ( pipe_uuid , & p2 - > syntax . uuid ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( p2 ) ;
return status ;
}
p2 - > syntax . if_version = pipe_version ;
status = GUID_from_string ( NDR_GUID , & p2 - > transfer_syntax . uuid ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( p2 ) ;
return status ;
}
p2 - > transfer_syntax . if_version = NDR_GUID_VERSION ;
status = dcerpc_alter_context ( p2 , p2 , & p2 - > syntax , & p2 - > transfer_syntax ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( p2 ) ;
return status ;
}
* pp2 = p2 ;
return status ;
}