2007-11-30 04:25:41 +03:00
/*
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
2007-03-09 02:54:57 +03:00
Copyright ( C ) Jeremy Allison 2007
2007-11-30 04:25:41 +03:00
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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2005-02-22 06:31:22 +03:00
( at your option ) any later version .
2007-11-30 04:25:41 +03:00
2005-02-22 06:31:22 +03:00
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 .
2007-11-30 04:25:41 +03:00
2005-02-22 06:31:22 +03:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-02-22 06:31:22 +03:00
*/
# include "includes.h"
2007-03-09 02:54:57 +03:00
/********************************************************************
Important point .
2007-03-12 20:55:24 +03:00
DFS paths are * always * of the form \ server \ share \ < pathname > ( the \ characters
2007-03-09 02:54:57 +03:00
are not C escaped here ) .
- but if we ' re using POSIX paths then < pathname > may contain
' / ' separators , not ' \\ ' separators . So cope with ' \\ ' or ' / '
as a separator when looking at the pathname part . . . . JRA .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-02-22 06:31:22 +03:00
2005-02-25 00:54:52 +03:00
struct client_connection {
struct client_connection * prev , * next ;
struct cli_state * cli ;
2007-11-30 04:25:41 +03:00
char * mount ;
2005-02-25 00:54:52 +03:00
} ;
/* global state....globals reek! */
2005-03-16 23:07:08 +03:00
int max_protocol = PROTOCOL_NT1 ;
2005-02-25 00:54:52 +03:00
2007-11-30 04:25:41 +03:00
static struct cm_cred_struct {
char * username ;
char * password ;
bool got_pass ;
bool use_kerberos ;
int signing_state ;
} cm_creds ;
static void cm_set_password ( const char * newpass ) ;
2005-02-25 00:54:52 +03:00
static int port ;
static int name_type = 0x20 ;
2007-10-19 04:40:25 +04:00
static bool have_ip ;
2007-10-25 01:16:54 +04:00
static struct sockaddr_storage dest_ss ;
2005-02-25 00:54:52 +03:00
static struct client_connection * connections ;
2007-12-30 09:39:52 +03:00
static bool cli_check_msdfs_proxy ( TALLOC_CTX * ctx ,
struct cli_state * cli ,
const char * sharename ,
char * * pp_newserver ,
char * * pp_newshare ,
bool force_encrypt ,
const char * username ,
const char * password ,
const char * domain ) ;
/********************************************************************
Ensure a connection is encrypted .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-05 11:23:35 +03:00
NTSTATUS cli_cm_force_encryption ( struct cli_state * c ,
2007-12-30 09:39:52 +03:00
const char * username ,
const char * password ,
const char * domain ,
const char * sharename )
{
2008-01-05 11:23:35 +03:00
NTSTATUS status = cli_force_encryption ( c ,
username ,
password ,
domain ) ;
2007-12-30 09:39:52 +03:00
2008-01-05 11:23:35 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_NOT_SUPPORTED ) ) {
2007-12-30 09:39:52 +03:00
d_printf ( " Encryption required and "
" server that doesn't support "
" UNIX extensions - failing connect \n " ) ;
2008-01-05 11:23:35 +03:00
} else if ( NT_STATUS_EQUAL ( status , NT_STATUS_UNKNOWN_REVISION ) ) {
2007-12-30 09:39:52 +03:00
d_printf ( " Encryption required and "
" can't get UNIX CIFS extensions "
" version from server. \n " ) ;
2008-01-05 11:23:35 +03:00
} else if ( NT_STATUS_EQUAL ( status , NT_STATUS_UNSUPPORTED_COMPRESSION ) ) {
2007-12-30 09:39:52 +03:00
d_printf ( " Encryption required and "
" share %s doesn't support "
" encryption. \n " , sharename ) ;
2008-01-05 11:23:35 +03:00
} else if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-12-30 09:39:52 +03:00
d_printf ( " Encryption required and "
" setup failed with error %s. \n " ,
nt_errstr ( status ) ) ;
}
2008-01-05 11:23:35 +03:00
return status ;
2007-12-30 09:39:52 +03:00
}
2005-02-25 00:54:52 +03:00
/********************************************************************
Return a connection to a server .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-11-30 04:25:41 +03:00
static struct cli_state * do_connect ( TALLOC_CTX * ctx ,
const char * server ,
const char * share ,
2007-12-30 09:39:52 +03:00
bool show_sessetup ,
bool force_encrypt )
2005-02-25 00:54:52 +03:00
{
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 ;
2007-10-25 01:16:54 +04:00
struct sockaddr_storage ss ;
2007-11-30 04:25:41 +03:00
char * servicename ;
2005-02-25 00:54:52 +03:00
char * sharename ;
2007-11-30 04:25:41 +03:00
char * newserver , * newshare ;
const char * username ;
const char * password ;
2007-06-20 21:38:42 +04:00
NTSTATUS status ;
2007-11-30 04:25:41 +03:00
2005-02-25 00:54:52 +03:00
/* make a copy so we don't modify the global string 'service' */
2007-11-30 04:25:41 +03:00
servicename = talloc_strdup ( ctx , share ) ;
if ( ! servicename ) {
return NULL ;
}
2005-02-25 00:54:52 +03:00
sharename = servicename ;
if ( * sharename = = ' \\ ' ) {
server = sharename + 2 ;
sharename = strchr_m ( server , ' \\ ' ) ;
2007-11-30 04:25:41 +03:00
if ( ! sharename ) {
return NULL ;
}
2005-02-25 00:54:52 +03:00
* sharename = 0 ;
sharename + + ;
}
server_n = server ;
2007-11-30 04:25:41 +03:00
2007-10-28 06:29:36 +03:00
zero_addr ( & ss ) ;
2005-02-25 00:54:52 +03:00
make_nmb_name ( & calling , global_myname ( ) , 0x0 ) ;
make_nmb_name ( & called , server , name_type ) ;
again :
2007-10-28 06:29:36 +03:00
zero_addr ( & ss ) ;
2007-10-25 01:16:54 +04:00
if ( have_ip )
ss = dest_ss ;
2005-02-25 00:54:52 +03:00
/* have to open a new connection */
2007-06-20 21:38:42 +04:00
if ( ! ( c = cli_initialise ( ) ) | | ( cli_set_port ( c , port ) ! = port ) ) {
2005-02-25 00:54:52 +03:00
d_printf ( " Connection to %s failed \n " , server_n ) ;
2008-01-09 05:51:55 +03:00
if ( c ) {
cli_shutdown ( c ) ;
}
2005-02-25 00:54:52 +03:00
return NULL ;
}
2007-10-25 01:16:54 +04:00
status = cli_connect ( c , server_n , & ss ) ;
2007-06-20 21:38:42 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-11-30 04:25:41 +03:00
d_printf ( " Connection to %s failed (Error %s) \n " ,
server_n ,
nt_errstr ( status ) ) ;
2008-01-09 05:51:55 +03:00
cli_shutdown ( c ) ;
2007-06-20 21:38:42 +04:00
return NULL ;
}
2005-02-25 00:54:52 +03:00
c - > protocol = max_protocol ;
2007-11-30 04:25:41 +03:00
c - > use_kerberos = cm_creds . use_kerberos ;
cli_setup_signing_state ( c , cm_creds . signing_state ) ;
2005-02-25 00:54:52 +03:00
if ( ! cli_session_request ( c , & calling , & called ) ) {
char * p ;
2007-11-30 04:25:41 +03:00
d_printf ( " session request to %s failed (%s) \n " ,
2005-02-25 00:54:52 +03:00
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 ;
}
2007-11-30 04:25:41 +03:00
if ( ! cm_creds . got_pass ) {
2005-02-25 00:54:52 +03:00
char * pass = getpass ( " Password: " ) ;
if ( pass ) {
2007-11-30 04:25:41 +03:00
cm_set_password ( pass ) ;
2005-02-25 00:54:52 +03:00
}
}
2007-11-30 04:25:41 +03:00
username = cm_creds . username ? cm_creds . username : " " ;
password = cm_creds . password ? cm_creds . password : " " ;
if ( ! NT_STATUS_IS_OK ( cli_session_setup ( c , username ,
2006-08-16 21:14:16 +04:00
password , strlen ( password ) ,
password , strlen ( password ) ,
lp_workgroup ( ) ) ) ) {
2007-11-30 04:25:41 +03:00
/* If a password was not supplied then
* try again with a null username . */
if ( password [ 0 ] | | ! username [ 0 ] | | cm_creds . use_kerberos | |
! NT_STATUS_IS_OK ( cli_session_setup ( c , " " ,
" " , 0 ,
" " , 0 ,
lp_workgroup ( ) ) ) ) {
2005-02-25 00:54:52 +03:00
d_printf ( " session setup failed: %s \n " , cli_errstr ( c ) ) ;
2007-11-30 04:25:41 +03:00
if ( NT_STATUS_V ( cli_nt_error ( c ) ) = =
2005-02-25 00:54:52 +03:00
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 ) ) ;
2007-11-30 04:25:41 +03:00
} 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 ) ) ;
2007-11-30 04:25:41 +03:00
}
2005-02-25 00:54:52 +03:00
}
DEBUG ( 4 , ( " session setup ok \n " ) ) ;
2005-05-10 02:39:20 +04:00
/* here's the fun part....to support 'msdfs proxy' shares
2007-11-30 04:25:41 +03: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 . */
2007-11-30 04:25:41 +03:00
if ( ( c - > capabilities & CAP_DFS ) & &
cli_check_msdfs_proxy ( ctx , c , sharename ,
2007-12-30 09:39:52 +03:00
& newserver , & newshare ,
force_encrypt ,
username ,
password ,
lp_workgroup ( ) ) ) {
2005-05-10 02:39:20 +04:00
cli_shutdown ( c ) ;
2007-12-30 09:39:52 +03:00
return do_connect ( ctx , newserver ,
newshare , false , force_encrypt ) ;
2005-05-10 02:39:20 +04:00
}
/* must be a normal share */
2007-11-30 04:25:41 +03:00
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 ;
}
2008-01-05 11:23:35 +03:00
if ( force_encrypt ) {
status = cli_cm_force_encryption ( c ,
2007-12-30 09:39:52 +03:00
username ,
password ,
lp_workgroup ( ) ,
2008-01-05 11:23:35 +03:00
sharename ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
cli_shutdown ( c ) ;
return NULL ;
}
2007-12-30 09:39:52 +03:00
}
2005-02-25 00:54:52 +03:00
DEBUG ( 4 , ( " tconx ok \n " ) ) ;
return c ;
}
2005-02-26 17:42:55 +03:00
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-11-30 04:25:41 +03:00
static void cli_cm_set_mntpoint ( struct cli_state * c , const char * mnt )
2005-02-26 17:42:55 +03:00
{
struct client_connection * p ;
int i ;
2007-11-30 04:25:41 +03:00
for ( p = connections , i = 0 ; p ; p = p - > next , i + + ) {
if ( strequal ( p - > cli - > desthost , c - > desthost ) & &
strequal ( p - > cli - > share , c - > share ) ) {
2005-02-26 17:42:55 +03:00
break ;
2007-11-30 04:25:41 +03:00
}
2005-02-26 17:42:55 +03:00
}
2007-11-30 04:25:41 +03:00
if ( p ) {
2007-11-16 01:19:52 +03:00
char * name = clean_name ( NULL , p - > mount ) ;
if ( ! name ) {
return ;
}
2007-11-30 04:25:41 +03:00
p - > mount = talloc_strdup ( p , name ) ;
2007-11-16 01:19:52 +03:00
TALLOC_FREE ( name ) ;
2005-02-26 17:42:55 +03:00
}
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-11-30 04:25:41 +03:00
const char * cli_cm_get_mntpoint ( struct cli_state * c )
2005-02-26 17:42:55 +03:00
{
struct client_connection * p ;
int i ;
2007-11-30 04:25:41 +03:00
for ( p = connections , i = 0 ; p ; p = p - > next , i + + ) {
if ( strequal ( p - > cli - > desthost , c - > desthost ) & &
strequal ( p - > cli - > share , c - > share ) ) {
2005-02-26 17:42:55 +03:00
break ;
2007-11-30 04:25:41 +03:00
}
2005-02-26 17:42:55 +03:00
}
2007-11-30 04:25:41 +03:00
if ( p ) {
2005-02-26 17:42:55 +03:00
return p - > mount ;
2007-11-30 04:25:41 +03:00
}
2005-02-26 17:42:55 +03:00
return NULL ;
}
2005-02-25 00:54:52 +03:00
/********************************************************************
Add a new connection to the list
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-11-30 04:25:41 +03:00
static struct cli_state * cli_cm_connect ( TALLOC_CTX * ctx ,
2007-12-07 04:16:33 +03:00
struct cli_state * referring_cli ,
const char * server ,
2007-03-12 20:55:24 +03:00
const char * share ,
2007-12-30 09:39:52 +03:00
bool show_hdr ,
bool force_encrypt )
2005-02-25 00:54:52 +03:00
{
struct client_connection * node ;
2007-11-30 00:24:54 +03:00
2007-11-30 04:25:41 +03:00
/* NB This must be the null context here... JRA. */
node = TALLOC_ZERO_ARRAY ( NULL , struct client_connection , 1 ) ;
2007-11-30 00:24:54 +03:00
if ( ! node ) {
return NULL ;
}
2007-12-30 09:39:52 +03:00
node - > cli = do_connect ( ctx , server , share , show_hdr , force_encrypt ) ;
2005-02-25 00:54:52 +03:00
if ( ! node - > cli ) {
2007-11-30 04:25:41 +03:00
TALLOC_FREE ( node ) ;
2005-02-25 00:54:52 +03:00
return NULL ;
}
DLIST_ADD ( connections , node ) ;
2007-11-30 04:25:41 +03:00
cli_cm_set_mntpoint ( node - > cli , " " ) ;
2005-02-26 17:42:55 +03:00
2007-12-07 04:16:33 +03:00
if ( referring_cli & & referring_cli - > posix_capabilities ) {
uint16 major , minor ;
uint32 caplow , caphigh ;
2007-12-07 04:17:03 +03:00
if ( cli_unix_extensions_version ( node - > cli , & major ,
2007-12-07 04:16:33 +03:00
& minor , & caplow , & caphigh ) ) {
2007-12-07 04:17:03 +03:00
cli_set_unix_extensions_capabilities ( node - > cli ,
major , minor ,
2007-12-07 04:16:33 +03:00
caplow , caphigh ) ;
}
}
2005-02-25 00:54:52 +03:00
2007-12-07 04:16:33 +03:00
return node - > cli ;
2005-02-25 00:54:52 +03:00
}
/********************************************************************
Return a connection to a server .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-11-30 04:25:41 +03:00
static struct cli_state * cli_cm_find ( const char * server , const char * share )
2005-02-25 00:54:52 +03:00
{
struct client_connection * p ;
2007-11-30 04:25:41 +03:00
for ( p = connections ; p ; p = p - > next ) {
if ( strequal ( server , p - > cli - > desthost ) & &
strequal ( share , p - > cli - > share ) ) {
2005-02-25 00:54:52 +03:00
return p - > cli ;
2007-11-30 04:25:41 +03:00
}
2005-02-25 00:54:52 +03:00
}
return NULL ;
}
/****************************************************************************
2007-11-30 04:25:41 +03:00
Open a client connection to a \ \ server \ share . Set ' s the current * cli
2005-02-25 00:54:52 +03:00
global variable as a side - effect ( but only if the connection is successful ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-11-30 04:25:41 +03:00
struct cli_state * cli_cm_open ( TALLOC_CTX * ctx ,
2007-12-07 04:16:33 +03:00
struct cli_state * referring_cli ,
2007-11-30 04:25:41 +03:00
const char * server ,
2007-03-12 20:55:24 +03:00
const char * share ,
2007-12-30 09:39:52 +03:00
bool show_hdr ,
bool force_encrypt )
2005-02-25 00:54:52 +03:00
{
struct cli_state * c ;
2007-11-30 04:25:41 +03:00
2005-02-25 00:54:52 +03:00
/* try to reuse an existing connection */
2007-11-30 04:25:41 +03:00
c = cli_cm_find ( server , share ) ;
if ( ! c ) {
2007-12-30 09:39:52 +03:00
c = cli_cm_connect ( ctx , referring_cli ,
server , share , show_hdr , force_encrypt ) ;
2007-03-12 20:55:24 +03:00
}
2005-02-25 00:54:52 +03:00
return c ;
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-11-30 04:25:41 +03:00
void cli_cm_shutdown ( void )
2005-02-25 00:54:52 +03:00
{
struct client_connection * p , * x ;
2007-11-30 04:25:41 +03:00
for ( p = connections ; p ; ) {
cli_shutdown ( p - > cli ) ;
2005-02-25 00:54:52 +03:00
x = p ;
p = p - > next ;
2007-11-30 04:25:41 +03:00
TALLOC_FREE ( x ) ;
2005-02-25 00:54:52 +03:00
}
connections = NULL ;
return ;
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void cli_cm_display ( void )
{
struct client_connection * p ;
int i ;
for ( p = connections , i = 0 ; p ; p = p - > next , i + + ) {
2007-11-30 04:25:41 +03:00
d_printf ( " %d: \t server=%s, share=%s \n " ,
2005-02-25 00:54:52 +03:00
i , p - > cli - > desthost , p - > cli - > share ) ;
}
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-11-30 04:25:41 +03:00
static void cm_set_password ( const char * newpass )
{
SAFE_FREE ( cm_creds . password ) ;
cm_creds . password = SMB_STRDUP ( newpass ) ;
if ( cm_creds . password ) {
cm_creds . got_pass = true ;
}
}
2007-12-07 04:16:33 +03:00
void cli_cm_set_credentials ( void )
2005-02-25 00:54:52 +03:00
{
2007-11-30 04:25:41 +03:00
SAFE_FREE ( cm_creds . username ) ;
2007-12-07 04:16:33 +03:00
cm_creds . username = SMB_STRDUP ( get_cmdline_auth_info_username ( ) ) ;
2007-11-30 04:25:41 +03:00
2007-12-07 04:16:33 +03:00
if ( get_cmdline_auth_info_got_pass ( ) ) {
cm_set_password ( get_cmdline_auth_info_password ( ) ) ;
2007-11-30 04:25:41 +03:00
}
2007-12-07 04:16:33 +03:00
cm_creds . use_kerberos = get_cmdline_auth_info_use_kerberos ( ) ;
cm_creds . signing_state = get_cmdline_auth_info_signing_state ( ) ;
2005-02-25 00:54:52 +03:00
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-11-30 04:25:41 +03:00
void cli_cm_set_port ( int port_number )
2005-02-25 00:54:52 +03:00
{
port = port_number ;
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-11-30 04:25:41 +03:00
void cli_cm_set_dest_name_type ( int type )
2005-02-25 00:54:52 +03:00
{
name_type = type ;
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-25 01:16:54 +04:00
void cli_cm_set_dest_ss ( struct sockaddr_storage * pss )
2005-02-25 00:54:52 +03:00
{
2007-10-25 01:16:54 +04:00
dest_ss = * pss ;
have_ip = true ;
2005-02-25 00:54:52 +03:00
}
2007-02-03 20:20:53 +03:00
/**********************************************************************
split a dfs path into the server , share name , and extrapath components
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-02-22 06:31:22 +03:00
2007-11-30 04:25:41 +03:00
static void split_dfs_path ( TALLOC_CTX * ctx ,
const char * nodepath ,
char * * pp_server ,
char * * pp_share ,
char * * pp_extrapath )
2005-02-22 06:31:22 +03:00
{
2007-02-03 20:20:53 +03:00
char * p , * q ;
2007-11-30 04:25:41 +03:00
char * path ;
2005-02-22 06:31:22 +03:00
2007-11-30 04:25:41 +03:00
* pp_server = NULL ;
* pp_share = NULL ;
* pp_extrapath = NULL ;
path = talloc_strdup ( ctx , nodepath ) ;
if ( ! path ) {
return ;
}
2005-02-22 06:31:22 +03:00
2007-03-12 20:55:24 +03:00
if ( path [ 0 ] ! = ' \\ ' ) {
2005-02-22 06:31:22 +03:00
return ;
2007-03-12 20:55:24 +03:00
}
2005-02-22 06:31:22 +03:00
2007-02-03 20:20:53 +03:00
p = strchr_m ( path + 1 , ' \\ ' ) ;
2007-03-12 20:55:24 +03:00
if ( ! p ) {
2005-02-22 06:31:22 +03:00
return ;
2007-03-12 20:55:24 +03:00
}
2005-02-22 06:31:22 +03:00
* p = ' \0 ' ;
p + + ;
2007-02-03 20:20:53 +03:00
/* Look for any extra/deep path */
q = strchr_m ( p , ' \\ ' ) ;
if ( q ! = NULL ) {
* q = ' \0 ' ;
q + + ;
2007-11-30 04:25:41 +03:00
* pp_extrapath = talloc_strdup ( ctx , q ) ;
2007-02-03 20:20:53 +03:00
} else {
2007-11-30 04:25:41 +03:00
* pp_extrapath = talloc_strdup ( ctx , " " ) ;
2007-02-03 20:20:53 +03:00
}
2007-11-30 04:25:41 +03:00
* pp_share = talloc_strdup ( ctx , p ) ;
* pp_server = talloc_strdup ( ctx , & path [ 1 ] ) ;
2005-02-22 06:31:22 +03:00
}
2005-02-23 20:29:28 +03:00
/****************************************************************************
2007-03-12 20:55:24 +03:00
Return the original path truncated at the directory component before
2007-11-30 04:25:41 +03:00
the first wildcard character . Trust the caller to provide a NULL
2005-02-23 20:29:28 +03:00
terminated string
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-11-30 04:25:41 +03:00
static char * clean_path ( TALLOC_CTX * ctx , const char * path )
2005-02-23 20:29:28 +03:00
{
2007-03-12 20:55:24 +03:00
size_t len ;
char * p1 , * p2 , * p ;
2007-11-30 04:25:41 +03:00
char * path_out ;
2007-03-12 20:55:24 +03:00
/* No absolute paths. */
while ( IS_DIRECTORY_SEP ( * path ) ) {
path + + ;
}
2007-11-30 04:25:41 +03:00
path_out = talloc_strdup ( ctx , path ) ;
if ( ! path_out ) {
return NULL ;
}
2007-03-12 20:55:24 +03:00
p1 = strchr_m ( path_out , ' * ' ) ;
p2 = strchr_m ( path_out , ' ? ' ) ;
if ( p1 | | p2 ) {
if ( p1 & & p2 ) {
p = MIN ( p1 , p2 ) ;
} else if ( ! p1 ) {
p = p2 ;
} else {
p = p1 ;
2005-02-23 20:29:28 +03:00
}
2007-03-12 20:55:24 +03:00
* p = ' \0 ' ;
/* Now go back to the start of this component. */
p1 = strrchr_m ( path_out , ' / ' ) ;
p2 = strrchr_m ( path_out , ' \\ ' ) ;
p = MAX ( p1 , p2 ) ;
if ( p ) {
2005-02-23 20:29:28 +03:00
* p = ' \0 ' ;
}
}
2007-03-12 20:55:24 +03:00
/* Strip any trailing separator */
len = strlen ( path_out ) ;
if ( ( len > 0 ) & & IS_DIRECTORY_SEP ( path_out [ len - 1 ] ) ) {
path_out [ len - 1 ] = ' \0 ' ;
}
2007-11-30 04:25:41 +03:00
return path_out ;
2005-02-23 20:29:28 +03:00
}
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-11-30 04:25:41 +03:00
static char * cli_dfs_make_full_path ( TALLOC_CTX * ctx ,
struct cli_state * cli ,
const char * dir )
2005-02-23 20:29:28 +03:00
{
2007-03-12 20:55:24 +03:00
/* Ensure the extrapath doesn't start with a separator. */
while ( IS_DIRECTORY_SEP ( * dir ) ) {
dir + + ;
2005-02-23 20:29:28 +03:00
}
2007-11-30 04:25:41 +03:00
return talloc_asprintf ( ctx , " \\ %s \\ %s \\ %s " ,
cli - > desthost , cli - > share , dir ) ;
2005-02-23 20:29:28 +03:00
}
/********************************************************************
check for dfs referral
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +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 */
2007-11-30 04:25:41 +03:00
if ( ! ( ( flgs2 & FLAGS2_32_BIT_ERROR_CODES ) & &
( flgs2 & FLAGS2_UNICODE_STRINGS ) ) )
return false ;
2005-02-23 20:29:28 +03:00
2007-11-30 04:25:41 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS ( IVAL ( cli - > inbuf , smb_rcls ) ) ) )
return true ;
2005-02-23 20:29:28 +03:00
2007-11-30 04:25:41 +03:00
return false ;
2005-02-23 20:29:28 +03:00
}
2005-02-22 06:31:22 +03:00
/********************************************************************
2007-11-30 04:25:41 +03:00
Get the dfs referral link .
2005-02-22 06:31:22 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-12-07 23:02:44 +03:00
bool cli_dfs_get_referral ( TALLOC_CTX * ctx ,
struct cli_state * cli ,
2007-11-30 04:25:41 +03:00
const char * path ,
2007-03-12 20:55:24 +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 ;
2007-12-07 23:02:44 +03:00
char * param ;
2005-02-22 06:31:22 +03:00
char * rparam = NULL , * rdata = NULL ;
char * p ;
2007-12-07 23:02:44 +03:00
char * endp ;
2005-02-22 06:31:22 +03:00
size_t pathlen = 2 * ( strlen ( path ) + 1 ) ;
uint16 num_referrals ;
2005-03-05 11:12:40 +03:00
CLIENT_DFS_REFERRAL * referrals = NULL ;
2007-12-07 23:02:44 +03:00
bool ret = false ;
2007-11-30 04:25:41 +03:00
2007-12-07 23:02:44 +03:00
* num_refs = 0 ;
* refs = NULL ;
2007-12-08 13:21:08 +03:00
param = SMB_MALLOC_ARRAY ( char , 2 + pathlen + 2 ) ;
2007-12-07 23:02:44 +03:00
if ( ! param ) {
return false ;
}
2005-02-22 06:31:22 +03:00
SSVAL ( param , 0 , 0x03 ) ; /* max referral level */
p = & param [ 2 ] ;
2007-12-07 23:02:44 +03:00
p + = clistr_push ( cli , p , path , pathlen , STR_TERMINATE ) ;
2005-02-22 06:31:22 +03:00
param_len = PTR_DIFF ( p , param ) ;
if ( ! cli_send_trans ( cli , SMBtrans2 ,
2007-12-07 23:02:44 +03:00
NULL , /* name */
- 1 , 0 , /* fid, flags */
& setup , 1 , 0 , /* setup, length, max */
param , param_len , 2 , /* param, length, max */
NULL , 0 , cli - > max_xmit /* data, length, max */
) ) {
SAFE_FREE ( param ) ;
return false ;
2005-02-22 06:31:22 +03:00
}
2007-12-07 23:02:44 +03:00
SAFE_FREE ( param ) ;
2005-02-22 06:31:22 +03:00
if ( ! cli_receive_trans ( cli , SMBtrans2 ,
& rparam , & param_len ,
& rdata , & data_len ) ) {
2007-11-30 04:25:41 +03:00
return false ;
2005-02-22 06:31:22 +03:00
}
2007-11-30 04:25:41 +03:00
2007-12-07 23:02:44 +03:00
if ( data_len < 4 ) {
goto out ;
}
2007-11-30 04:25:41 +03:00
2007-12-07 23:02:44 +03:00
endp = rdata + data_len ;
* consumed = SVAL ( rdata , 0 ) ;
num_referrals = SVAL ( rdata , 2 ) ;
if ( num_referrals ! = 0 ) {
2005-02-22 06:31:22 +03:00
uint16 ref_version ;
uint16 ref_size ;
int i ;
uint16 node_offset ;
2007-03-12 20:55:24 +03:00
2007-12-07 23:02:44 +03:00
referrals = TALLOC_ARRAY ( ctx , CLIENT_DFS_REFERRAL ,
2007-11-30 04:25:41 +03:00
num_referrals ) ;
2007-03-12 20:55:24 +03:00
2007-12-07 23:02:44 +03:00
if ( ! referrals ) {
goto out ;
}
2005-02-22 06:31:22 +03:00
/* start at the referrals array */
2007-11-30 04:25:41 +03:00
2005-02-22 06:31:22 +03:00
p = rdata + 8 ;
2007-12-07 23:02:44 +03:00
for ( i = 0 ; i < num_referrals & & p < endp ; i + + ) {
if ( p + 18 > endp ) {
goto out ;
}
ref_version = SVAL ( p , 0 ) ;
ref_size = SVAL ( p , 2 ) ;
node_offset = SVAL ( p , 16 ) ;
2007-11-30 04:25:41 +03:00
2007-12-07 23:02:44 +03:00
if ( ref_version ! = 3 ) {
2005-02-22 06:31:22 +03:00
p + = ref_size ;
continue ;
}
2007-11-30 04:25:41 +03:00
2007-12-07 23:02:44 +03:00
referrals [ i ] . proximity = SVAL ( p , 8 ) ;
referrals [ i ] . ttl = SVAL ( p , 10 ) ;
2005-02-22 06:31:22 +03:00
2007-12-07 23:02:44 +03:00
if ( p + node_offset > endp ) {
goto out ;
}
clistr_pull_talloc ( ctx , cli , & referrals [ i ] . dfspath ,
2007-12-07 23:08:55 +03:00
p + node_offset , - 1 ,
2007-11-30 04:25:41 +03:00
STR_TERMINATE | STR_UNICODE ) ;
2005-02-22 06:31:22 +03:00
2007-12-07 23:02:44 +03:00
if ( ! referrals [ i ] . dfspath ) {
goto out ;
}
2005-02-22 06:31:22 +03:00
p + = ref_size ;
}
2007-12-07 23:02:44 +03:00
if ( i < num_referrals ) {
goto out ;
}
2005-02-22 06:31:22 +03:00
}
2007-11-30 04:25:41 +03:00
2007-12-07 23:02:44 +03:00
ret = true ;
2005-02-22 06:31:22 +03:00
* num_refs = num_referrals ;
* refs = referrals ;
2007-12-07 23:02:44 +03:00
out :
2005-02-22 06:31:22 +03:00
SAFE_FREE ( rdata ) ;
SAFE_FREE ( rparam ) ;
2007-12-07 23:02:44 +03:00
return ret ;
2005-02-22 06:31:22 +03:00
}
2005-02-23 20:29:28 +03:00
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-11-30 04:25:41 +03:00
bool cli_resolve_path ( TALLOC_CTX * ctx ,
const char * mountpt ,
2007-03-12 20:55:24 +03:00
struct cli_state * rootcli ,
const char * path ,
struct cli_state * * targetcli ,
2007-11-30 04:25:41 +03:00
char * * pp_targetpath )
2005-02-23 20:29:28 +03:00
{
CLIENT_DFS_REFERRAL * refs = NULL ;
2007-12-07 23:02:44 +03:00
size_t num_refs = 0 ;
2005-02-23 20:29:28 +03:00
uint16 consumed ;
2007-11-30 04:25:41 +03:00
struct cli_state * cli_ipc = NULL ;
char * dfs_path = NULL ;
char * cleanpath = NULL ;
char * extrapath = NULL ;
2005-02-23 20:29:28 +03:00
int pathlen ;
2007-11-30 04:25:41 +03:00
char * server = NULL ;
char * share = NULL ;
struct cli_state * newcli = NULL ;
char * newpath = NULL ;
char * newmount = NULL ;
char * ppath = NULL ;
2005-02-23 20:29:28 +03:00
SMB_STRUCT_STAT sbuf ;
uint32 attributes ;
2007-11-30 04:25:41 +03:00
2007-03-09 02:54:57 +03:00
if ( ! rootcli | | ! path | | ! targetcli ) {
2007-11-30 04:25:41 +03:00
return false ;
2007-03-09 02:54:57 +03:00
}
2007-11-30 04:25:41 +03:00
2007-03-12 20:55:24 +03:00
/* Don't do anything if this is not a DFS root. */
2005-02-23 20:29:28 +03:00
2007-03-12 20:55:24 +03:00
if ( ! rootcli - > dfsroot ) {
2005-02-23 20:29:28 +03:00
* targetcli = rootcli ;
2007-11-30 04:25:41 +03:00
* pp_targetpath = talloc_strdup ( ctx , path ) ;
if ( ! * pp_targetpath ) {
return false ;
}
return true ;
2005-02-23 20:29:28 +03:00
}
2007-03-12 20:55:24 +03:00
* targetcli = NULL ;
/* Send a trans2_query_path_info to check for a referral. */
2007-11-30 04:25:41 +03:00
cleanpath = clean_path ( ctx , path ) ;
if ( ! cleanpath ) {
return false ;
}
dfs_path = cli_dfs_make_full_path ( ctx , rootcli , cleanpath ) ;
if ( ! dfs_path ) {
return false ;
}
2007-03-12 20:55:24 +03:00
2007-11-30 04:25:41 +03:00
if ( cli_qpathinfo_basic ( rootcli , dfs_path , & sbuf , & attributes ) ) {
2007-03-12 20:55:24 +03:00
/* This is an ordinary path, just return it. */
* targetcli = rootcli ;
2007-11-30 04:25:41 +03:00
* pp_targetpath = talloc_strdup ( ctx , path ) ;
if ( ! * pp_targetpath ) {
return false ;
}
2007-03-12 20:55:24 +03:00
goto done ;
}
/* Special case where client asked for a path that does not exist */
2005-05-10 16:21:02 +04:00
2007-11-30 04:25:41 +03:00
if ( cli_dfs_check_error ( rootcli , NT_STATUS_OBJECT_NAME_NOT_FOUND ) ) {
2005-05-10 16:21:02 +04:00
* targetcli = rootcli ;
2007-11-30 04:25:41 +03:00
* pp_targetpath = talloc_strdup ( ctx , path ) ;
if ( ! * pp_targetpath ) {
return false ;
}
2007-03-09 02:54:57 +03:00
goto done ;
2005-05-10 16:21:02 +04:00
}
2007-03-12 20:55:24 +03:00
/* We got an error, check for DFS referral. */
2007-11-30 04:25:41 +03:00
if ( ! cli_dfs_check_error ( rootcli , NT_STATUS_PATH_NOT_COVERED ) ) {
return false ;
2007-03-09 02:54:57 +03:00
}
2005-02-23 20:29:28 +03:00
2007-03-12 20:55:24 +03:00
/* Check for the referral. */
2005-02-23 20:29:28 +03:00
2007-12-07 04:16:33 +03:00
if ( ! ( cli_ipc = cli_cm_open ( ctx , rootcli ,
2007-12-30 09:39:52 +03:00
rootcli - > desthost ,
" IPC$ " , false ,
( rootcli - > trans_enc_state ! = NULL ) ) ) ) {
2007-11-30 04:25:41 +03:00
return false ;
2007-03-09 02:54:57 +03:00
}
2007-11-30 04:25:41 +03:00
2007-12-07 23:02:44 +03:00
if ( ! cli_dfs_get_referral ( ctx , cli_ipc , dfs_path , & refs ,
2007-11-30 04:25:41 +03:00
& num_refs , & consumed ) | | ! num_refs ) {
return false ;
2005-02-23 20:29:28 +03:00
}
2007-11-30 04:25:41 +03:00
2007-03-12 20:55:24 +03:00
/* Just store the first referral for now. */
2005-02-23 20:29:28 +03:00
2007-12-07 23:02:44 +03:00
if ( ! refs [ 0 ] . dfspath ) {
return false ;
}
2007-11-30 04:25:41 +03:00
split_dfs_path ( ctx , refs [ 0 ] . dfspath , & server , & share , & extrapath ) ;
2007-02-03 20:20:53 +03:00
2007-11-30 04:25:41 +03:00
if ( ! server | | ! share ) {
return false ;
}
2007-03-12 20:55:24 +03:00
/* Make sure to recreate the original string including any wildcards. */
2007-11-30 04:25:41 +03:00
dfs_path = cli_dfs_make_full_path ( ctx , rootcli , path ) ;
if ( ! dfs_path ) {
return false ;
}
pathlen = strlen ( dfs_path ) * 2 ;
consumed = MIN ( pathlen , consumed ) ;
* pp_targetpath = talloc_strdup ( ctx , & dfs_path [ consumed / 2 ] ) ;
if ( ! * pp_targetpath ) {
return false ;
}
2007-03-12 20:55:24 +03:00
dfs_path [ consumed / 2 ] = ' \0 ' ;
/*
2007-11-30 04:25:41 +03:00
* * pp_targetpath is now the unconsumed part of the path .
* dfs_path is now the consumed part of the path
* ( in \ server \ share \ path format ) .
2007-03-12 20:55:24 +03:00
*/
/* Open the connection to the target server & share */
2007-12-07 04:16:33 +03:00
if ( ( * targetcli = cli_cm_open ( ctx , rootcli ,
2007-12-30 09:39:52 +03:00
server ,
share ,
false ,
( rootcli - > trans_enc_state ! = NULL ) ) ) = = NULL ) {
2007-03-12 20:55:24 +03:00
d_printf ( " Unable to follow dfs referral [ \\ %s \\ %s] \n " ,
2005-02-23 20:29:28 +03:00
server , share ) ;
2007-11-30 04:25:41 +03:00
return false ;
2005-02-23 20:29:28 +03:00
}
2007-11-30 04:25:41 +03:00
if ( extrapath & & strlen ( extrapath ) > 0 ) {
* pp_targetpath = talloc_asprintf ( ctx ,
" %s%s " ,
extrapath ,
* pp_targetpath ) ;
if ( ! * pp_targetpath ) {
return false ;
}
2007-03-12 20:55:24 +03:00
}
2007-11-30 04:25:41 +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
2007-03-12 20:55:24 +03:00
ppath = dfs_path ;
if ( * ppath ! = ' \\ ' ) {
2007-11-30 04:25:41 +03:00
d_printf ( " cli_resolve_path: "
" dfs_path (%s) not in correct format. \n " ,
2007-03-12 20:55:24 +03:00
dfs_path ) ;
2007-11-30 04:25:41 +03:00
return false ;
2007-03-09 02:54:57 +03:00
}
2007-03-12 20:55:24 +03:00
ppath + + ; /* Now pointing at start of server name. */
2007-11-30 04:25:41 +03:00
2007-03-12 20:55:24 +03:00
if ( ( ppath = strchr_m ( dfs_path , ' \\ ' ) ) = = NULL ) {
2007-11-30 04:25:41 +03:00
return false ;
2007-03-09 02:54:57 +03:00
}
2007-03-12 20:55:24 +03:00
ppath + + ; /* Now pointing at start of share name. */
2007-03-09 02:54:57 +03:00
2007-03-12 20:55:24 +03:00
if ( ( ppath = strchr_m ( ppath + 1 , ' \\ ' ) ) = = NULL ) {
2007-11-30 04:25:41 +03:00
return false ;
2007-03-09 02:54:57 +03:00
}
2007-03-12 20:55:24 +03:00
ppath + + ; /* Now pointing at path component. */
2007-11-30 04:25:41 +03:00
newmount = talloc_asprintf ( ctx , " %s \\ %s " , mountpt , ppath ) ;
if ( ! newmount ) {
return false ;
}
2007-03-12 20:55:24 +03:00
2007-11-30 04:25:41 +03:00
cli_cm_set_mntpoint ( * targetcli , newmount ) ;
2005-02-26 18:03:16 +03:00
2007-11-30 04:25:41 +03:00
/* Check for another dfs referral, note that we are not
2007-03-12 20:55:24 +03:00
checking for loops here . */
2005-02-23 23:00:26 +03:00
2007-11-30 04:25:41 +03:00
if ( ! strequal ( * pp_targetpath , " \\ " ) & & ! strequal ( * pp_targetpath , " / " ) ) {
if ( cli_resolve_path ( ctx ,
newmount ,
* targetcli ,
* pp_targetpath ,
& newcli ,
& newpath ) ) {
2007-03-12 20:55:24 +03:00
/*
* When cli_resolve_path returns true here it ' s always
* returning the complete path in newpath , so we ' re done
* here .
*/
2005-02-24 22:10:28 +03:00
* targetcli = newcli ;
2007-11-30 04:25:41 +03:00
* pp_targetpath = newpath ;
return true ;
2005-02-24 22:10:28 +03:00
}
2005-02-23 23:00:26 +03:00
}
2005-02-26 18:03:16 +03:00
2007-03-09 02:54:57 +03:00
done :
2007-11-30 04:25:41 +03:00
/* If returning true ensure we return a dfs root full path. */
if ( ( * targetcli ) - > dfsroot ) {
dfs_path = talloc_strdup ( ctx , * pp_targetpath ) ;
if ( ! dfs_path ) {
return false ;
}
* pp_targetpath = cli_dfs_make_full_path ( ctx , * targetcli , dfs_path ) ;
2007-03-09 02:54:57 +03:00
}
2007-11-30 04:25:41 +03:00
return true ;
}
2005-05-10 02:39:20 +04:00
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-12-30 09:39:52 +03:00
static bool cli_check_msdfs_proxy ( TALLOC_CTX * ctx ,
2007-11-30 04:25:41 +03:00
struct cli_state * cli ,
const char * sharename ,
char * * pp_newserver ,
2007-12-30 09:39:52 +03:00
char * * pp_newshare ,
bool force_encrypt ,
const char * username ,
const char * password ,
const char * domain )
2005-05-10 02:39:20 +04:00
{
CLIENT_DFS_REFERRAL * refs = NULL ;
2007-12-07 23:02:44 +03:00
size_t num_refs = 0 ;
2005-05-10 02:39:20 +04:00
uint16 consumed ;
2007-11-30 04:25:41 +03:00
char * fullpath = NULL ;
2007-10-19 04:40:25 +04:00
bool res ;
2006-02-04 01:19:41 +03:00
uint16 cnum ;
2007-11-30 04:25:41 +03:00
char * newextrapath = NULL ;
if ( ! cli | | ! sharename ) {
return false ;
}
2005-05-10 02:39:20 +04:00
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 */
2007-11-30 04:25:41 +03:00
if ( strequal ( sharename , " IPC$ " ) ) {
return false ;
2007-03-12 20:55:24 +03:00
}
2007-11-30 04:25:41 +03:00
2005-05-10 02:39:20 +04:00
/* send a trans2_query_path_info to check for a referral */
2007-11-30 04:25:41 +03:00
fullpath = talloc_asprintf ( ctx , " \\ %s \\ %s " , cli - > desthost , sharename ) ;
if ( ! fullpath ) {
return false ;
}
2005-05-10 02:39:20 +04:00
/* check for the referral */
2006-02-04 01:19:41 +03:00
if ( ! cli_send_tconX ( cli , " IPC$ " , " IPC " , NULL , 0 ) ) {
2007-11-30 04:25:41 +03:00
return false ;
2006-02-04 01:19:41 +03:00
}
2008-01-05 11:23:35 +03:00
if ( force_encrypt ) {
NTSTATUS status = cli_cm_force_encryption ( cli ,
2007-12-30 09:39:52 +03:00
username ,
password ,
lp_workgroup ( ) ,
2008-01-05 11:23:35 +03:00
" IPC$ " ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return false ;
}
2007-12-30 09:39:52 +03:00
}
2007-12-07 23:02:44 +03:00
res = cli_dfs_get_referral ( ctx , cli , fullpath , & refs , & num_refs , & consumed ) ;
2006-02-04 01:19:41 +03:00
if ( ! cli_tdis ( cli ) ) {
2007-11-30 04:25:41 +03:00
return false ;
2006-02-04 01:19:41 +03:00
}
cli - > cnum = cnum ;
2007-03-09 02:54:57 +03:00
2007-11-30 04:25:41 +03:00
if ( ! res | | ! num_refs ) {
2007-12-07 23:02:44 +03:00
return false ;
}
if ( ! refs [ 0 ] . dfspath ) {
2007-11-30 04:25:41 +03:00
return false ;
}
split_dfs_path ( ctx , refs [ 0 ] . dfspath , pp_newserver ,
pp_newshare , & newextrapath ) ;
2008-03-06 13:27:49 +03:00
if ( ( * pp_newserver = = NULL ) | | ( * pp_newshare = = NULL ) ) {
2007-11-30 04:25:41 +03:00
return false ;
2005-05-10 02:39:20 +04:00
}
/* check that this is not a self-referral */
2007-11-30 04:25:41 +03:00
if ( strequal ( cli - > desthost , * pp_newserver ) & &
strequal ( sharename , * pp_newshare ) ) {
return false ;
2006-07-29 00:35:00 +04:00
}
2007-11-30 04:25:41 +03:00
return true ;
2005-05-10 02:39:20 +04:00
}