2005-02-22 06:31:22 +03:00
/*
Unix SMB / CIFS implementation .
client connect / disconnect routines
2005-02-25 00:54:52 +03:00
Copyright ( C ) Andrew Tridgell 1994 - 1998
2005-02-23 20:29:28 +03:00
Copyright ( C ) Gerald ( Jerry ) Carter 2004
2005-02-22 06:31:22 +03: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"
2005-02-25 00:54:52 +03:00
struct client_connection {
struct client_connection * prev , * next ;
struct cli_state * cli ;
2005-02-26 17:42:55 +03:00
pstring mount ;
2005-02-25 00:54:52 +03:00
} ;
/* global state....globals reek! */
static pstring username ;
static pstring password ;
static BOOL use_kerberos ;
static BOOL got_pass ;
static int signing_state ;
2005-03-16 23:07:08 +03:00
int max_protocol = PROTOCOL_NT1 ;
2005-02-25 00:54:52 +03:00
static int port ;
static int name_type = 0x20 ;
static BOOL have_ip ;
static struct in_addr dest_ip ;
static struct client_connection * connections ;
/********************************************************************
Return a connection to a server .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct cli_state * do_connect ( const char * server , const char * share ,
BOOL show_sessetup )
{
2006-07-11 22:01:26 +04:00
struct cli_state * c = NULL ;
2005-02-25 00:54:52 +03:00
struct nmb_name called , calling ;
const char * server_n ;
struct in_addr ip ;
pstring servicename ;
char * sharename ;
2005-05-10 02:39:20 +04:00
fstring newserver , newshare ;
2005-02-25 00:54:52 +03:00
/* make a copy so we don't modify the global string 'service' */
pstrcpy ( servicename , share ) ;
sharename = servicename ;
if ( * sharename = = ' \\ ' ) {
server = sharename + 2 ;
sharename = strchr_m ( server , ' \\ ' ) ;
if ( ! sharename ) return NULL ;
* sharename = 0 ;
sharename + + ;
}
server_n = server ;
zero_ip ( & ip ) ;
make_nmb_name ( & calling , global_myname ( ) , 0x0 ) ;
make_nmb_name ( & called , server , name_type ) ;
again :
zero_ip ( & ip ) ;
if ( have_ip )
ip = dest_ip ;
/* have to open a new connection */
2006-07-11 22:01:26 +04:00
if ( ! ( c = cli_initialise ( ) ) | | ( cli_set_port ( c , port ) ! = port ) | |
2005-02-25 00:54:52 +03:00
! cli_connect ( c , server_n , & ip ) ) {
d_printf ( " Connection to %s failed \n " , server_n ) ;
return NULL ;
}
c - > protocol = max_protocol ;
c - > use_kerberos = use_kerberos ;
cli_setup_signing_state ( c , signing_state ) ;
if ( ! cli_session_request ( c , & calling , & called ) ) {
char * p ;
d_printf ( " session request to %s failed (%s) \n " ,
called . name , cli_errstr ( c ) ) ;
cli_shutdown ( c ) ;
2006-07-11 22:01:26 +04:00
c = NULL ;
2005-02-25 00:54:52 +03:00
if ( ( p = strchr_m ( called . name , ' . ' ) ) ) {
* p = 0 ;
goto again ;
}
if ( strcmp ( called . name , " *SMBSERVER " ) ) {
make_nmb_name ( & called , " *SMBSERVER " , 0x20 ) ;
goto again ;
}
return NULL ;
}
DEBUG ( 4 , ( " session request ok \n " ) ) ;
if ( ! cli_negprot ( c ) ) {
d_printf ( " protocol negotiation failed \n " ) ;
cli_shutdown ( c ) ;
return NULL ;
}
if ( ! got_pass ) {
char * pass = getpass ( " Password: " ) ;
if ( pass ) {
pstrcpy ( password , pass ) ;
got_pass = 1 ;
}
}
if ( ! cli_session_setup ( c , username ,
password , strlen ( password ) ,
password , strlen ( password ) ,
lp_workgroup ( ) ) ) {
/* if a password was not supplied then try again with a null username */
if ( password [ 0 ] | | ! username [ 0 ] | | use_kerberos | |
! cli_session_setup ( c , " " , " " , 0 , " " , 0 , lp_workgroup ( ) ) ) {
d_printf ( " session setup failed: %s \n " , cli_errstr ( c ) ) ;
if ( NT_STATUS_V ( cli_nt_error ( c ) ) = =
NT_STATUS_V ( NT_STATUS_MORE_PROCESSING_REQUIRED ) )
d_printf ( " did you forget to run kinit? \n " ) ;
cli_shutdown ( c ) ;
return NULL ;
}
d_printf ( " Anonymous login successful \n " ) ;
}
if ( show_sessetup ) {
if ( * c - > server_domain ) {
2005-02-25 18:22:49 +03:00
DEBUG ( 0 , ( " Domain=[%s] OS=[%s] Server=[%s] \n " ,
2005-02-25 00:54:52 +03:00
c - > server_domain , c - > server_os , c - > server_type ) ) ;
} else if ( * c - > server_os | | * c - > server_type ) {
2005-02-25 18:22:49 +03:00
DEBUG ( 0 , ( " OS=[%s] Server=[%s] \n " ,
2005-02-25 00:54:52 +03:00
c - > server_os , c - > server_type ) ) ;
}
}
DEBUG ( 4 , ( " session setup ok \n " ) ) ;
2005-05-10 02:39:20 +04:00
/* here's the fun part....to support 'msdfs proxy' shares
2005-09-02 18:12:04 +04:00
( on Samba or windows ) we have to issues a TRANS_GET_DFS_REFERRAL
2005-05-10 02:39:20 +04:00
here before trying to connect to the original share .
check_dfs_proxy ( ) will fail if it is a normal share . */
2005-06-06 18:37:31 +04:00
if ( ( c - > capabilities & CAP_DFS ) & & cli_check_msdfs_proxy ( c , sharename , newserver , newshare ) ) {
2005-05-10 02:39:20 +04:00
cli_shutdown ( c ) ;
return do_connect ( newserver , newshare , False ) ;
}
/* must be a normal share */
if ( ! cli_send_tconX ( c , sharename , " ????? " , password , strlen ( password ) + 1 ) ) {
2005-02-25 00:54:52 +03:00
d_printf ( " tree connect failed: %s \n " , cli_errstr ( c ) ) ;
cli_shutdown ( c ) ;
return NULL ;
}
DEBUG ( 4 , ( " tconx ok \n " ) ) ;
return c ;
}
2005-02-26 17:42:55 +03:00
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void cli_cm_set_mntpoint ( struct cli_state * c , const char * mnt )
{
struct client_connection * p ;
int i ;
for ( p = connections , i = 0 ; p ; p = p - > next , i + + ) {
if ( strequal ( p - > cli - > desthost , c - > desthost ) & & strequal ( p - > cli - > share , c - > share ) )
break ;
}
if ( p ) {
pstrcpy ( p - > mount , mnt ) ;
dos_clean_name ( p - > mount ) ;
}
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
const char * cli_cm_get_mntpoint ( struct cli_state * c )
{
struct client_connection * p ;
int i ;
for ( p = connections , i = 0 ; p ; p = p - > next , i + + ) {
if ( strequal ( p - > cli - > desthost , c - > desthost ) & & strequal ( p - > cli - > share , c - > share ) )
break ;
}
if ( p )
return p - > mount ;
return NULL ;
}
2005-02-25 00:54:52 +03:00
/********************************************************************
Add a new connection to the list
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct cli_state * cli_cm_connect ( const char * server , const char * share ,
BOOL show_hdr )
{
struct client_connection * node ;
node = SMB_XMALLOC_P ( struct client_connection ) ;
node - > cli = do_connect ( server , share , show_hdr ) ;
if ( ! node - > cli ) {
SAFE_FREE ( node ) ;
return NULL ;
}
DLIST_ADD ( connections , node ) ;
2005-02-26 17:42:55 +03:00
cli_cm_set_mntpoint ( node - > cli , " " ) ;
2005-02-25 00:54:52 +03:00
return node - > cli ;
}
/********************************************************************
Return a connection to a server .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct cli_state * cli_cm_find ( const char * server , const char * share )
{
struct client_connection * p ;
for ( p = connections ; p ; p = p - > next ) {
if ( strequal ( server , p - > cli - > desthost ) & & strequal ( share , p - > cli - > share ) )
return p - > cli ;
}
return NULL ;
}
/****************************************************************************
open a client connection to a \ \ server \ share . Set ' s the current * cli
global variable as a side - effect ( but only if the connection is successful ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct cli_state * cli_cm_open ( const char * server , const char * share , BOOL show_hdr )
{
struct cli_state * c ;
/* try to reuse an existing connection */
c = cli_cm_find ( server , share ) ;
if ( ! c )
c = cli_cm_connect ( server , share , show_hdr ) ;
return c ;
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void cli_cm_shutdown ( void )
{
struct client_connection * p , * x ;
for ( p = connections ; p ; ) {
cli_shutdown ( p - > cli ) ;
x = p ;
p = p - > next ;
SAFE_FREE ( x ) ;
}
connections = NULL ;
return ;
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void cli_cm_display ( void )
{
struct client_connection * p ;
int i ;
for ( p = connections , i = 0 ; p ; p = p - > next , i + + ) {
d_printf ( " %d: \t server=%s, share=%s \n " ,
i , p - > cli - > desthost , p - > cli - > share ) ;
}
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void cli_cm_set_credentials ( struct user_auth_info * user )
{
pstrcpy ( username , user - > username ) ;
if ( user - > got_pass ) {
pstrcpy ( password , user - > password ) ;
got_pass = True ;
}
use_kerberos = user - > use_kerberos ;
signing_state = user - > signing_state ;
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void cli_cm_set_port ( int port_number )
{
port = port_number ;
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void cli_cm_set_dest_name_type ( int type )
{
name_type = type ;
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void cli_cm_set_dest_ip ( struct in_addr ip )
{
dest_ip = ip ;
have_ip = True ;
}
2005-02-22 06:31:22 +03:00
/********************************************************************
split a dfs path into the server and share name components
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-02-23 20:29:28 +03:00
static void split_dfs_path ( const char * nodepath , fstring server , fstring share )
2005-02-22 06:31:22 +03:00
{
char * p ;
pstring path ;
pstrcpy ( path , nodepath ) ;
if ( path [ 0 ] ! = ' \\ ' )
return ;
p = strrchr_m ( path , ' \\ ' ) ;
if ( ! p )
return ;
* p = ' \0 ' ;
p + + ;
fstrcpy ( share , p ) ;
fstrcpy ( server , & path [ 1 ] ) ;
}
2005-02-23 20:29:28 +03:00
/****************************************************************************
return the original path truncated at the first wildcard character
( also strips trailing \ ' s ) . Trust the caller to provide a NULL
terminated string
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void clean_path ( pstring clean , const char * path )
{
int len ;
char * p ;
pstring newpath ;
pstrcpy ( newpath , path ) ;
p = newpath ;
while ( p ) {
/* first check for '*' */
p = strrchr_m ( newpath , ' * ' ) ;
if ( p ) {
* p = ' \0 ' ;
p = newpath ;
continue ;
}
/* first check for '?' */
p = strrchr_m ( newpath , ' ? ' ) ;
if ( p ) {
* p = ' \0 ' ;
p = newpath ;
}
}
/* strip a trailing backslash */
len = strlen ( newpath ) ;
2006-06-15 14:48:53 +04:00
if ( ( len > 0 ) & & ( newpath [ len - 1 ] = = ' \\ ' ) )
2005-02-23 20:29:28 +03:00
newpath [ len - 1 ] = ' \0 ' ;
pstrcpy ( clean , newpath ) ;
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-05-10 02:39:20 +04:00
BOOL cli_dfs_make_full_path ( pstring path , const char * server , const char * share ,
2005-02-23 20:29:28 +03:00
const char * dir )
{
pstring servicename ;
char * sharename ;
const char * directory ;
/* make a copy so we don't modify the global string 'service' */
pstrcpy ( servicename , share ) ;
sharename = servicename ;
if ( * sharename = = ' \\ ' ) {
server = sharename + 2 ;
sharename = strchr_m ( server , ' \\ ' ) ;
if ( ! sharename )
return False ;
* sharename = 0 ;
sharename + + ;
}
directory = dir ;
if ( * directory = = ' \\ ' )
directory + + ;
pstr_sprintf ( path , " \\ %s \\ %s \\ %s " , server , sharename , directory ) ;
return True ;
}
/********************************************************************
check for dfs referral
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-05-10 16:21:02 +04:00
static BOOL cli_dfs_check_error ( struct cli_state * cli , NTSTATUS status )
2005-02-23 20:29:28 +03:00
{
uint32 flgs2 = SVAL ( cli - > inbuf , smb_flg2 ) ;
/* only deal with DS when we negotiated NT_STATUS codes and UNICODE */
if ( ! ( ( flgs2 & FLAGS2_32_BIT_ERROR_CODES ) & & ( flgs2 & FLAGS2_UNICODE_STRINGS ) ) )
return False ;
2005-05-10 16:21:02 +04:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS ( IVAL ( cli - > inbuf , smb_rcls ) ) ) )
2005-02-23 20:29:28 +03:00
return True ;
return False ;
}
2005-02-22 06:31:22 +03:00
/********************************************************************
get the dfs referral link
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL cli_dfs_get_referral ( struct cli_state * cli , const char * path ,
2005-02-23 20:29:28 +03:00
CLIENT_DFS_REFERRAL * * refs , size_t * num_refs ,
uint16 * consumed )
2005-02-22 06:31:22 +03:00
{
unsigned int data_len = 0 ;
unsigned int param_len = 0 ;
uint16 setup = TRANSACT2_GET_DFS_REFERRAL ;
char param [ sizeof ( pstring ) + 2 ] ;
pstring data ;
char * rparam = NULL , * rdata = NULL ;
char * p ;
size_t pathlen = 2 * ( strlen ( path ) + 1 ) ;
uint16 num_referrals ;
2005-03-05 11:12:40 +03:00
CLIENT_DFS_REFERRAL * referrals = NULL ;
2005-02-22 06:31:22 +03:00
memset ( param , 0 , sizeof ( param ) ) ;
SSVAL ( param , 0 , 0x03 ) ; /* max referral level */
p = & param [ 2 ] ;
p + = clistr_push ( cli , p , path , MIN ( pathlen , sizeof ( param ) - 2 ) , STR_TERMINATE ) ;
param_len = PTR_DIFF ( p , param ) ;
if ( ! cli_send_trans ( cli , SMBtrans2 ,
NULL , /* name */
- 1 , 0 , /* fid, flags */
& setup , 1 , 0 , /* setup, length, max */
param , param_len , 2 , /* param, length, max */
( char * ) & data , data_len , cli - > max_xmit /* data, length, max */
) ) {
return False ;
}
if ( ! cli_receive_trans ( cli , SMBtrans2 ,
& rparam , & param_len ,
& rdata , & data_len ) ) {
return False ;
}
2005-02-23 20:29:28 +03:00
* consumed = SVAL ( rdata , 0 ) ;
2005-02-22 06:31:22 +03:00
num_referrals = SVAL ( rdata , 2 ) ;
if ( num_referrals ! = 0 ) {
uint16 ref_version ;
uint16 ref_size ;
int i ;
uint16 node_offset ;
2005-02-23 20:29:28 +03:00
referrals = SMB_XMALLOC_ARRAY ( CLIENT_DFS_REFERRAL , num_referrals ) ;
2005-02-22 06:31:22 +03:00
/* start at the referrals array */
p = rdata + 8 ;
for ( i = 0 ; i < num_referrals ; i + + ) {
ref_version = SVAL ( p , 0 ) ;
ref_size = SVAL ( p , 2 ) ;
node_offset = SVAL ( p , 16 ) ;
if ( ref_version ! = 3 ) {
p + = ref_size ;
continue ;
}
2005-02-23 20:29:28 +03:00
referrals [ i ] . proximity = SVAL ( p , 8 ) ;
referrals [ i ] . ttl = SVAL ( p , 10 ) ;
2005-02-22 06:31:22 +03:00
2005-02-23 20:29:28 +03:00
clistr_pull ( cli , referrals [ i ] . dfspath , p + node_offset ,
sizeof ( referrals [ i ] . dfspath ) , - 1 , STR_TERMINATE | STR_UNICODE ) ;
2005-02-22 06:31:22 +03:00
p + = ref_size ;
}
}
* num_refs = num_referrals ;
* refs = referrals ;
SAFE_FREE ( rdata ) ;
SAFE_FREE ( rparam ) ;
return True ;
}
2005-02-23 20:29:28 +03:00
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-02-26 18:03:16 +03:00
BOOL cli_resolve_path ( const char * mountpt , struct cli_state * rootcli , const char * path ,
2005-02-23 20:29:28 +03:00
struct cli_state * * targetcli , pstring targetpath )
{
CLIENT_DFS_REFERRAL * refs = NULL ;
size_t num_refs ;
uint16 consumed ;
struct cli_state * cli_ipc ;
pstring fullpath , cleanpath ;
int pathlen ;
fstring server , share ;
2005-02-23 23:00:26 +03:00
struct cli_state * newcli ;
pstring newpath ;
2005-02-26 18:03:16 +03:00
pstring newmount ;
char * ppath ;
2005-02-23 20:29:28 +03:00
SMB_STRUCT_STAT sbuf ;
uint32 attributes ;
if ( ! rootcli | | ! path | | ! targetcli )
return False ;
2006-03-10 11:56:13 +03:00
* targetcli = NULL ;
2005-02-23 20:29:28 +03:00
/* send a trans2_query_path_info to check for a referral */
clean_path ( cleanpath , path ) ;
2005-05-10 02:39:20 +04:00
cli_dfs_make_full_path ( fullpath , rootcli - > desthost , rootcli - > share , cleanpath ) ;
2005-02-23 20:29:28 +03:00
/* don't bother continuing if this is not a dfs root */
2005-02-24 22:10:28 +03:00
if ( ! rootcli - > dfsroot | | cli_qpathinfo_basic ( rootcli , cleanpath , & sbuf , & attributes ) ) {
2005-02-23 20:29:28 +03:00
* targetcli = rootcli ;
pstrcpy ( targetpath , path ) ;
return True ;
}
2005-05-10 16:21:02 +04:00
/* special case where client asked for a path that does not exist */
if ( cli_dfs_check_error ( rootcli , NT_STATUS_OBJECT_NAME_NOT_FOUND ) ) {
* targetcli = rootcli ;
pstrcpy ( targetpath , path ) ;
return True ;
}
2005-02-23 20:29:28 +03:00
/* we got an error, check for DFS referral */
2005-05-10 16:21:02 +04:00
if ( ! cli_dfs_check_error ( rootcli , NT_STATUS_PATH_NOT_COVERED ) )
2005-02-23 20:29:28 +03:00
return False ;
/* check for the referral */
if ( ! ( cli_ipc = cli_cm_open ( rootcli - > desthost , " IPC$ " , False ) ) )
return False ;
if ( ! cli_dfs_get_referral ( cli_ipc , fullpath , & refs , & num_refs , & consumed )
| | ! num_refs )
{
return False ;
}
/* just store the first referral for now
Make sure to recreate the original string including any wildcards */
2005-05-10 02:39:20 +04:00
cli_dfs_make_full_path ( fullpath , rootcli - > desthost , rootcli - > share , path ) ;
2005-02-23 20:29:28 +03:00
pathlen = strlen ( fullpath ) * 2 ;
consumed = MIN ( pathlen , consumed ) ;
pstrcpy ( targetpath , & fullpath [ consumed / 2 ] ) ;
split_dfs_path ( refs [ 0 ] . dfspath , server , share ) ;
SAFE_FREE ( refs ) ;
/* open the connection to the target path */
if ( ( * targetcli = cli_cm_open ( server , share , False ) ) = = NULL ) {
d_printf ( " Unable to follow dfs referral [//%s/%s] \n " ,
server , share ) ;
return False ;
}
2005-02-26 17:42:55 +03:00
2005-02-26 18:03:16 +03:00
/* parse out the consumed mount path */
/* trim off the \server\share\ */
2005-02-23 23:00:26 +03:00
2005-02-26 18:03:16 +03:00
fullpath [ consumed / 2 ] = ' \0 ' ;
dos_clean_name ( fullpath ) ;
2006-06-19 23:07:39 +04:00
if ( ( ppath = strchr_m ( fullpath , ' \\ ' ) ) = = NULL )
return False ;
if ( ( ppath = strchr_m ( ppath + 1 , ' \\ ' ) ) = = NULL )
return False ;
if ( ( ppath = strchr_m ( ppath + 1 , ' \\ ' ) ) = = NULL )
return False ;
2005-02-26 18:03:16 +03:00
ppath + + ;
pstr_sprintf ( newmount , " %s \\ %s " , mountpt , ppath ) ;
cli_cm_set_mntpoint ( * targetcli , newmount ) ;
/* check for another dfs referral, note that we are not
2005-02-23 23:00:26 +03:00
checking for loops here */
2005-02-24 22:10:28 +03:00
if ( ! strequal ( targetpath , " \\ " ) ) {
2005-02-26 18:03:16 +03:00
if ( cli_resolve_path ( newmount , * targetcli , targetpath , & newcli , newpath ) ) {
2005-02-24 22:10:28 +03:00
* targetcli = newcli ;
pstrcpy ( targetpath , newpath ) ;
}
2005-02-23 23:00:26 +03:00
}
2005-02-26 18:03:16 +03:00
2005-02-23 20:29:28 +03:00
return True ;
}
2005-05-10 02:39:20 +04:00
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL cli_check_msdfs_proxy ( struct cli_state * cli , const char * sharename ,
fstring newserver , fstring newshare )
{
CLIENT_DFS_REFERRAL * refs = NULL ;
size_t num_refs ;
uint16 consumed ;
pstring fullpath ;
2006-02-04 01:19:41 +03:00
BOOL res ;
uint16 cnum ;
2005-05-10 02:39:20 +04:00
if ( ! cli | | ! sharename )
return False ;
2006-02-04 01:19:41 +03:00
cnum = cli - > cnum ;
2005-05-10 02:39:20 +04:00
/* special case. never check for a referral on the IPC$ share */
if ( strequal ( sharename , " IPC$ " ) )
return False ;
/* send a trans2_query_path_info to check for a referral */
pstr_sprintf ( fullpath , " \\ %s \\ %s " , cli - > desthost , sharename ) ;
/* check for the referral */
2006-02-04 01:19:41 +03:00
if ( ! cli_send_tconX ( cli , " IPC$ " , " IPC " , NULL , 0 ) ) {
2005-05-10 02:39:20 +04:00
return False ;
2006-02-04 01:19:41 +03:00
}
res = cli_dfs_get_referral ( cli , fullpath , & refs , & num_refs , & consumed ) ;
if ( ! cli_tdis ( cli ) ) {
2006-07-29 00:35:00 +04:00
SAFE_FREE ( refs ) ;
2006-02-04 01:19:41 +03:00
return False ;
}
cli - > cnum = cnum ;
if ( ! res | | ! num_refs ) {
2006-07-29 00:35:00 +04:00
SAFE_FREE ( refs ) ;
2005-05-10 02:39:20 +04:00
return False ;
}
split_dfs_path ( refs [ 0 ] . dfspath , newserver , newshare ) ;
/* check that this is not a self-referral */
2006-07-29 00:35:00 +04:00
if ( strequal ( cli - > desthost , newserver ) & & strequal ( sharename , newshare ) ) {
SAFE_FREE ( refs ) ;
2005-05-10 02:39:20 +04:00
return False ;
2006-07-29 00:35:00 +04:00
}
2005-05-10 02:39:20 +04:00
SAFE_FREE ( refs ) ;
return True ;
}