2000-04-25 18:04:06 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2000-04-25 18:04:06 +04:00
client connect / disconnect routines
Copyright ( C ) Andrew Tridgell 1994 - 1998
2003-02-24 05:55:00 +03:00
Copyright ( C ) Andrew Bartlett 2001 - 2003
2000-04-25 18:04:06 +04: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 .
*/
# define NO_SYSLOG
# include "includes.h"
2001-10-29 11:12:44 +03:00
static const struct {
2002-07-15 14:35:28 +04:00
int prot ;
const char * name ;
} prots [ ] = {
{ PROTOCOL_CORE , " PC NETWORK PROGRAM 1.0 " } ,
{ PROTOCOL_COREPLUS , " MICROSOFT NETWORKS 1.03 " } ,
{ PROTOCOL_LANMAN1 , " MICROSOFT NETWORKS 3.0 " } ,
{ PROTOCOL_LANMAN1 , " LANMAN1.0 " } ,
{ PROTOCOL_LANMAN2 , " LM1.2X002 " } ,
{ PROTOCOL_LANMAN2 , " DOS LANMAN2.1 " } ,
{ PROTOCOL_LANMAN2 , " Samba " } ,
{ PROTOCOL_NT1 , " NT LANMAN 1.0 " } ,
{ PROTOCOL_NT1 , " NT LM 0.12 " } ,
{ - 1 , NULL }
} ;
2000-04-25 18:04:06 +04:00
2001-10-11 11:42:52 +04:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
Do an old lanman2 style session setup .
2001-10-11 11:42:52 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2002-11-13 02:20:50 +03:00
static BOOL cli_session_setup_lanman2 ( struct cli_state * cli , const char * user ,
2003-02-24 05:55:00 +03:00
const char * pass , size_t passlen , const char * workgroup )
2001-10-11 11:42:52 +04:00
{
fstring pword ;
char * p ;
2002-09-25 19:19:00 +04:00
if ( passlen > sizeof ( pword ) - 1 )
2001-10-11 11:42:52 +04:00
return False ;
/* if in share level security then don't send a password now */
2002-09-25 19:19:00 +04:00
if ( ! ( cli - > sec_mode & NEGOTIATE_SECURITY_USER_LEVEL ) )
2001-10-11 11:42:52 +04:00
passlen = 0 ;
2002-07-15 14:35:28 +04:00
if ( passlen > 0 & & ( cli - > sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE ) & & passlen ! = 24 ) {
2001-10-11 11:42:52 +04:00
/* Encrypted mode needed, and non encrypted password supplied. */
passlen = 24 ;
2002-07-15 14:35:28 +04:00
SMBencrypt ( pass , cli - > secblob . data , ( uchar * ) pword ) ;
} else if ( ( cli - > sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE ) & & passlen = = 24 ) {
2001-10-11 11:42:52 +04:00
/* Encrypted mode needed, and encrypted password supplied. */
memcpy ( pword , pass , passlen ) ;
} else if ( passlen > 0 ) {
/* Plaintext mode needed, assume plaintext supplied. */
2003-03-18 14:22:52 +03:00
passlen = clistr_push ( cli , pword , pass , sizeof ( pword ) , STR_TERMINATE ) ;
2001-10-11 11:42:52 +04:00
}
/* send a session setup command */
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
set_message ( cli - > outbuf , 10 , 0 , True ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( cli - > outbuf , smb_com , SMBsesssetupX ) ;
2001-10-11 11:42:52 +04:00
cli_setup_packet ( cli ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( cli - > outbuf , smb_vwv0 , 0xFF ) ;
2001-10-11 11:42:52 +04:00
SSVAL ( cli - > outbuf , smb_vwv2 , cli - > max_xmit ) ;
SSVAL ( cli - > outbuf , smb_vwv3 , 2 ) ;
SSVAL ( cli - > outbuf , smb_vwv4 , 1 ) ;
SIVAL ( cli - > outbuf , smb_vwv5 , cli - > sesskey ) ;
SSVAL ( cli - > outbuf , smb_vwv7 , passlen ) ;
p = smb_buf ( cli - > outbuf ) ;
memcpy ( p , pword , passlen ) ;
p + = passlen ;
2002-07-15 14:35:28 +04:00
p + = clistr_push ( cli , p , user , - 1 , STR_TERMINATE | STR_UPPER ) ;
p + = clistr_push ( cli , p , workgroup , - 1 , STR_TERMINATE | STR_UPPER ) ;
p + = clistr_push ( cli , p , " Unix " , - 1 , STR_TERMINATE ) ;
p + = clistr_push ( cli , p , " Samba " , - 1 , STR_TERMINATE ) ;
2001-10-11 11:42:52 +04:00
cli_setup_bcc ( cli , p ) ;
cli_send_smb ( cli ) ;
if ( ! cli_receive_smb ( cli ) )
return False ;
show_msg ( cli - > inbuf ) ;
2002-09-25 19:19:00 +04:00
if ( cli_is_error ( cli ) )
2001-10-11 11:42:52 +04:00
return False ;
/* use the returned vuid from now on */
cli - > vuid = SVAL ( cli - > inbuf , smb_uid ) ;
fstrcpy ( cli - > user_name , user ) ;
return True ;
}
/****************************************************************************
2002-07-15 14:35:28 +04:00
Work out suitable capabilities to offer the server .
2001-10-11 11:42:52 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2001-10-11 11:42:52 +04:00
static uint32 cli_session_setup_capabilities ( struct cli_state * cli )
{
uint32 capabilities = CAP_NT_SMBS ;
2002-09-25 19:19:00 +04:00
if ( ! cli - > force_dos_errors )
2001-10-11 11:42:52 +04:00
capabilities | = CAP_STATUS32 ;
2002-09-25 19:19:00 +04:00
if ( cli - > use_level_II_oplocks )
2001-10-11 11:42:52 +04:00
capabilities | = CAP_LEVEL_II_OPLOCKS ;
2002-09-25 19:19:00 +04:00
if ( cli - > capabilities & CAP_UNICODE )
2001-10-11 11:42:52 +04:00
capabilities | = CAP_UNICODE ;
2002-11-08 21:45:38 +03:00
if ( cli - > capabilities & CAP_LARGE_FILES )
capabilities | = CAP_LARGE_FILES ;
2001-10-11 11:42:52 +04:00
return capabilities ;
}
/****************************************************************************
2002-07-15 14:35:28 +04:00
Do a NT1 guest session setup .
2001-10-11 11:42:52 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2001-10-11 11:42:52 +04:00
static BOOL cli_session_setup_guest ( struct cli_state * cli )
{
char * p ;
uint32 capabilities = cli_session_setup_capabilities ( cli ) ;
set_message ( cli - > outbuf , 13 , 0 , True ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( cli - > outbuf , smb_com , SMBsesssetupX ) ;
2001-10-11 11:42:52 +04:00
cli_setup_packet ( cli ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( cli - > outbuf , smb_vwv0 , 0xFF ) ;
2001-10-11 11:42:52 +04:00
SSVAL ( cli - > outbuf , smb_vwv2 , CLI_BUFFER_SIZE ) ;
SSVAL ( cli - > outbuf , smb_vwv3 , 2 ) ;
SSVAL ( cli - > outbuf , smb_vwv4 , cli - > pid ) ;
SIVAL ( cli - > outbuf , smb_vwv5 , cli - > sesskey ) ;
SSVAL ( cli - > outbuf , smb_vwv7 , 0 ) ;
SSVAL ( cli - > outbuf , smb_vwv8 , 0 ) ;
SIVAL ( cli - > outbuf , smb_vwv11 , capabilities ) ;
p = smb_buf ( cli - > outbuf ) ;
p + = clistr_push ( cli , p , " " , - 1 , STR_TERMINATE ) ; /* username */
p + = clistr_push ( cli , p , " " , - 1 , STR_TERMINATE ) ; /* workgroup */
p + = clistr_push ( cli , p , " Unix " , - 1 , STR_TERMINATE ) ;
p + = clistr_push ( cli , p , " Samba " , - 1 , STR_TERMINATE ) ;
cli_setup_bcc ( cli , p ) ;
cli_send_smb ( cli ) ;
if ( ! cli_receive_smb ( cli ) )
return False ;
show_msg ( cli - > inbuf ) ;
2002-09-25 19:19:00 +04:00
if ( cli_is_error ( cli ) )
2001-10-11 11:42:52 +04:00
return False ;
cli - > vuid = SVAL ( cli - > inbuf , smb_uid ) ;
p = smb_buf ( cli - > inbuf ) ;
p + = clistr_pull ( cli , cli - > server_os , p , sizeof ( fstring ) , - 1 , STR_TERMINATE ) ;
p + = clistr_pull ( cli , cli - > server_type , p , sizeof ( fstring ) , - 1 , STR_TERMINATE ) ;
p + = clistr_pull ( cli , cli - > server_domain , p , sizeof ( fstring ) , - 1 , STR_TERMINATE ) ;
fstrcpy ( cli - > user_name , " " ) ;
return True ;
}
/****************************************************************************
2002-07-15 14:35:28 +04:00
Do a NT1 plaintext session setup .
2001-10-11 11:42:52 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2002-11-13 02:20:50 +03:00
static BOOL cli_session_setup_plaintext ( struct cli_state * cli , const char * user ,
const char * pass , const char * workgroup )
2001-10-11 11:42:52 +04:00
{
uint32 capabilities = cli_session_setup_capabilities ( cli ) ;
char * p ;
2003-05-21 20:12:07 +04:00
fstring lanman ;
snprintf ( lanman , sizeof ( lanman ) , " Samba %s " , VERSION ) ;
2001-10-11 11:42:52 +04:00
set_message ( cli - > outbuf , 13 , 0 , True ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( cli - > outbuf , smb_com , SMBsesssetupX ) ;
2001-10-11 11:42:52 +04:00
cli_setup_packet ( cli ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( cli - > outbuf , smb_vwv0 , 0xFF ) ;
2001-10-11 11:42:52 +04:00
SSVAL ( cli - > outbuf , smb_vwv2 , CLI_BUFFER_SIZE ) ;
SSVAL ( cli - > outbuf , smb_vwv3 , 2 ) ;
SSVAL ( cli - > outbuf , smb_vwv4 , cli - > pid ) ;
SIVAL ( cli - > outbuf , smb_vwv5 , cli - > sesskey ) ;
SSVAL ( cli - > outbuf , smb_vwv8 , 0 ) ;
SIVAL ( cli - > outbuf , smb_vwv11 , capabilities ) ;
p = smb_buf ( cli - > outbuf ) ;
2003-05-21 20:12:07 +04:00
/* check wether to send the ASCII or UNICODE version of the password */
if ( ( capabilities & CAP_UNICODE ) = = 0 ) {
p + = clistr_push ( cli , p , pass , - 1 , STR_TERMINATE ) ; /* password */
SSVAL ( cli - > outbuf , smb_vwv7 , PTR_DIFF ( p , smb_buf ( cli - > outbuf ) ) ) ;
}
else {
p + = clistr_push ( cli , p , pass , - 1 , STR_UNICODE | STR_TERMINATE ) ; /* unicode password */
SSVAL ( cli - > outbuf , smb_vwv8 , PTR_DIFF ( p , smb_buf ( cli - > outbuf ) ) ) ;
}
2001-10-11 11:42:52 +04:00
p + = clistr_push ( cli , p , user , - 1 , STR_TERMINATE ) ; /* username */
p + = clistr_push ( cli , p , workgroup , - 1 , STR_TERMINATE ) ; /* workgroup */
p + = clistr_push ( cli , p , " Unix " , - 1 , STR_TERMINATE ) ;
2003-05-21 20:12:07 +04:00
p + = clistr_push ( cli , p , lanman , - 1 , STR_TERMINATE ) ;
2001-10-11 11:42:52 +04:00
cli_setup_bcc ( cli , p ) ;
cli_send_smb ( cli ) ;
if ( ! cli_receive_smb ( cli ) )
return False ;
show_msg ( cli - > inbuf ) ;
2002-09-25 19:19:00 +04:00
if ( cli_is_error ( cli ) )
2001-10-11 11:42:52 +04:00
return False ;
cli - > vuid = SVAL ( cli - > inbuf , smb_uid ) ;
p = smb_buf ( cli - > inbuf ) ;
p + = clistr_pull ( cli , cli - > server_os , p , sizeof ( fstring ) , - 1 , STR_TERMINATE ) ;
p + = clistr_pull ( cli , cli - > server_type , p , sizeof ( fstring ) , - 1 , STR_TERMINATE ) ;
p + = clistr_pull ( cli , cli - > server_domain , p , sizeof ( fstring ) , - 1 , STR_TERMINATE ) ;
fstrcpy ( cli - > user_name , user ) ;
return True ;
}
2003-02-24 05:55:00 +03:00
static void set_cli_session_key ( struct cli_state * cli , DATA_BLOB session_key )
{
memcpy ( cli - > user_session_key , session_key . data , MIN ( session_key . length , sizeof ( cli - > user_session_key ) ) ) ;
}
2002-09-25 19:19:00 +04:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
do a NT1 NTLM / LM encrypted session setup
@ param cli client state to create do session setup on
@ param user username
@ param pass * either * cleartext password ( passlen ! = 24 ) or LM response .
@ param ntpass NT response , implies ntpasslen > = 24 , implies pass is not clear
@ param workgroup The user ' s domain .
2002-09-25 19:19:00 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2002-11-13 02:20:50 +03:00
static BOOL cli_session_setup_nt1 ( struct cli_state * cli , const char * user ,
2003-02-24 05:55:00 +03:00
const char * pass , size_t passlen ,
const char * ntpass , size_t ntpasslen ,
2002-11-13 02:20:50 +03:00
const char * workgroup )
2001-10-11 11:42:52 +04:00
{
uint32 capabilities = cli_session_setup_capabilities ( cli ) ;
2003-02-24 05:55:00 +03:00
DATA_BLOB lm_response = data_blob ( NULL , 0 ) ;
DATA_BLOB nt_response = data_blob ( NULL , 0 ) ;
DATA_BLOB session_key = data_blob ( NULL , 0 ) ;
BOOL ret = False ;
2001-10-11 11:42:52 +04:00
char * p ;
if ( passlen ! = 24 ) {
2003-02-24 05:55:00 +03:00
if ( lp_client_ntlmv2_auth ( ) ) {
DATA_BLOB server_chal ;
2003-05-09 18:42:20 +04:00
DATA_BLOB names_blob ;
2003-02-24 05:55:00 +03:00
server_chal = data_blob ( cli - > secblob . data , MIN ( cli - > secblob . length , 8 ) ) ;
2003-05-09 18:42:20 +04:00
/* note that the 'workgroup' here is a best guess - we don't know
the server ' s domain at this point . The ' server name ' is also
dodgy . . .
*/
names_blob = NTLMv2_generate_names_blob ( cli - > called . name , workgroup ) ;
if ( ! SMBNTLMv2encrypt ( user , workgroup , pass , & server_chal ,
& names_blob ,
& lm_response , & nt_response , & session_key ) ) {
data_blob_free ( & names_blob ) ;
2003-02-24 05:55:00 +03:00
data_blob_free ( & server_chal ) ;
return False ;
}
2003-05-09 18:42:20 +04:00
data_blob_free ( & names_blob ) ;
2003-02-24 05:55:00 +03:00
data_blob_free ( & server_chal ) ;
} else {
uchar nt_hash [ 16 ] ;
E_md4hash ( pass , nt_hash ) ;
2003-06-08 16:49:31 +04:00
nt_response = data_blob ( NULL , 24 ) ;
SMBNTencrypt ( pass , cli - > secblob . data , nt_response . data ) ;
2003-02-24 05:55:00 +03:00
/* non encrypted password supplied. Ignore ntpass. */
if ( lp_client_lanman_auth ( ) ) {
lm_response = data_blob ( NULL , 24 ) ;
2003-06-08 16:49:31 +04:00
SMBencrypt ( pass , cli - > secblob . data , lm_response . data ) ;
} else {
/* LM disabled, place NT# in LM feild instead */
lm_response = data_blob ( nt_response . data , nt_response . length ) ;
2003-02-24 05:55:00 +03:00
}
session_key = data_blob ( NULL , 16 ) ;
SMBsesskeygen_ntv1 ( nt_hash , NULL , session_key . data ) ;
}
2003-03-18 15:01:47 +03:00
cli_simple_set_signing ( cli , session_key . data , nt_response ) ;
2001-10-11 11:42:52 +04:00
} else {
2002-09-25 19:19:00 +04:00
/* pre-encrypted password supplied. Only used for
security = server , can ' t do
2003-05-14 04:46:43 +04:00
signing because we don ' t have original key */
2003-02-24 05:55:00 +03:00
lm_response = data_blob ( pass , passlen ) ;
nt_response = data_blob ( ntpass , ntpasslen ) ;
2001-10-11 11:42:52 +04:00
}
/* send a session setup command */
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
set_message ( cli - > outbuf , 13 , 0 , True ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( cli - > outbuf , smb_com , SMBsesssetupX ) ;
2001-10-11 11:42:52 +04:00
cli_setup_packet ( cli ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( cli - > outbuf , smb_vwv0 , 0xFF ) ;
2001-10-11 11:42:52 +04:00
SSVAL ( cli - > outbuf , smb_vwv2 , CLI_BUFFER_SIZE ) ;
SSVAL ( cli - > outbuf , smb_vwv3 , 2 ) ;
SSVAL ( cli - > outbuf , smb_vwv4 , cli - > pid ) ;
SIVAL ( cli - > outbuf , smb_vwv5 , cli - > sesskey ) ;
2003-02-24 05:55:00 +03:00
SSVAL ( cli - > outbuf , smb_vwv7 , lm_response . length ) ;
SSVAL ( cli - > outbuf , smb_vwv8 , nt_response . length ) ;
2001-10-11 11:42:52 +04:00
SIVAL ( cli - > outbuf , smb_vwv11 , capabilities ) ;
p = smb_buf ( cli - > outbuf ) ;
2003-02-24 05:55:00 +03:00
if ( lm_response . length ) {
memcpy ( p , lm_response . data , lm_response . length ) ; p + = lm_response . length ;
}
if ( nt_response . length ) {
memcpy ( p , nt_response . data , nt_response . length ) ; p + = nt_response . length ;
}
2002-09-25 19:19:00 +04:00
p + = clistr_push ( cli , p , user , - 1 , STR_TERMINATE ) ;
p + = clistr_push ( cli , p , workgroup , - 1 , STR_TERMINATE ) ;
2001-10-11 11:42:52 +04:00
p + = clistr_push ( cli , p , " Unix " , - 1 , STR_TERMINATE ) ;
p + = clistr_push ( cli , p , " Samba " , - 1 , STR_TERMINATE ) ;
cli_setup_bcc ( cli , p ) ;
2003-02-24 05:55:00 +03:00
if ( ! cli_send_smb ( cli ) | | ! cli_receive_smb ( cli ) ) {
ret = False ;
goto end ;
}
2001-10-11 11:42:52 +04:00
2002-09-25 19:19:00 +04:00
show_msg ( cli - > inbuf ) ;
2002-07-15 14:35:28 +04:00
2003-02-24 05:55:00 +03:00
if ( cli_is_error ( cli ) ) {
ret = False ;
goto end ;
}
2002-07-15 14:35:28 +04:00
2001-10-11 11:42:52 +04:00
/* use the returned vuid from now on */
cli - > vuid = SVAL ( cli - > inbuf , smb_uid ) ;
p = smb_buf ( cli - > inbuf ) ;
p + = clistr_pull ( cli , cli - > server_os , p , sizeof ( fstring ) , - 1 , STR_TERMINATE ) ;
p + = clistr_pull ( cli , cli - > server_type , p , sizeof ( fstring ) , - 1 , STR_TERMINATE ) ;
p + = clistr_pull ( cli , cli - > server_domain , p , sizeof ( fstring ) , - 1 , STR_TERMINATE ) ;
fstrcpy ( cli - > user_name , user ) ;
2003-02-24 05:55:00 +03:00
if ( session_key . data ) {
2002-09-25 19:19:00 +04:00
/* Have plaintext orginal */
2003-02-24 05:55:00 +03:00
set_cli_session_key ( cli , session_key ) ;
2002-09-25 19:19:00 +04:00
}
2003-02-24 05:55:00 +03:00
2003-03-18 15:01:47 +03:00
ret = True ;
2003-02-24 05:55:00 +03:00
end :
data_blob_free ( & lm_response ) ;
data_blob_free ( & nt_response ) ;
data_blob_free ( & session_key ) ;
2003-03-18 15:01:47 +03:00
return ret ;
2001-10-11 11:42:52 +04:00
}
/****************************************************************************
2003-03-18 15:01:47 +03:00
Send a extended security session setup blob
2001-10-11 11:42:52 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2003-03-18 15:01:47 +03:00
static BOOL cli_session_setup_blob_send ( struct cli_state * cli , DATA_BLOB blob )
2001-10-11 11:42:52 +04:00
{
uint32 capabilities = cli_session_setup_capabilities ( cli ) ;
char * p ;
capabilities | = CAP_EXTENDED_SECURITY ;
/* send a session setup command */
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
set_message ( cli - > outbuf , 12 , 0 , True ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( cli - > outbuf , smb_com , SMBsesssetupX ) ;
2002-09-25 19:19:00 +04:00
2001-10-11 11:42:52 +04:00
cli_setup_packet ( cli ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( cli - > outbuf , smb_vwv0 , 0xFF ) ;
2001-10-11 11:42:52 +04:00
SSVAL ( cli - > outbuf , smb_vwv2 , CLI_BUFFER_SIZE ) ;
SSVAL ( cli - > outbuf , smb_vwv3 , 2 ) ;
2001-11-20 11:45:22 +03:00
SSVAL ( cli - > outbuf , smb_vwv4 , 1 ) ;
2001-10-11 11:42:52 +04:00
SIVAL ( cli - > outbuf , smb_vwv5 , 0 ) ;
2001-10-12 08:49:42 +04:00
SSVAL ( cli - > outbuf , smb_vwv7 , blob . length ) ;
2001-10-11 11:42:52 +04:00
SIVAL ( cli - > outbuf , smb_vwv10 , capabilities ) ;
p = smb_buf ( cli - > outbuf ) ;
2001-10-12 08:49:42 +04:00
memcpy ( p , blob . data , blob . length ) ;
p + = blob . length ;
2001-10-11 11:42:52 +04:00
p + = clistr_push ( cli , p , " Unix " , - 1 , STR_TERMINATE ) ;
p + = clistr_push ( cli , p , " Samba " , - 1 , STR_TERMINATE ) ;
cli_setup_bcc ( cli , p ) ;
2003-03-18 15:01:47 +03:00
return cli_send_smb ( cli ) ;
}
/****************************************************************************
Send a extended security session setup blob , returning a reply blob .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static DATA_BLOB cli_session_setup_blob_receive ( struct cli_state * cli )
{
DATA_BLOB blob2 = data_blob ( NULL , 0 ) ;
char * p ;
size_t len ;
2002-09-25 19:19:00 +04:00
2001-10-11 11:42:52 +04:00
if ( ! cli_receive_smb ( cli ) )
2001-10-12 08:49:42 +04:00
return blob2 ;
2001-10-11 11:42:52 +04:00
show_msg ( cli - > inbuf ) ;
2001-10-12 08:49:42 +04:00
if ( cli_is_error ( cli ) & & ! NT_STATUS_EQUAL ( cli_nt_error ( cli ) ,
NT_STATUS_MORE_PROCESSING_REQUIRED ) ) {
return blob2 ;
2001-10-11 11:42:52 +04:00
}
/* use the returned vuid from now on */
cli - > vuid = SVAL ( cli - > inbuf , smb_uid ) ;
p = smb_buf ( cli - > inbuf ) ;
blob2 = data_blob ( p , SVAL ( cli - > inbuf , smb_vwv3 ) ) ;
p + = blob2 . length ;
p + = clistr_pull ( cli , cli - > server_os , p , sizeof ( fstring ) , - 1 , STR_TERMINATE ) ;
2001-12-21 15:29:51 +03:00
/* w2k with kerberos doesn't properly null terminate this field */
len = smb_buflen ( cli - > inbuf ) - PTR_DIFF ( p , smb_buf ( cli - > inbuf ) ) ;
p + = clistr_pull ( cli , cli - > server_type , p , sizeof ( fstring ) , len , 0 ) ;
2001-10-11 11:42:52 +04:00
2001-10-12 08:49:42 +04:00
return blob2 ;
}
2001-10-11 11:42:52 +04:00
2003-06-26 09:26:20 +04:00
# ifdef HAVE_KRB5
2003-03-18 15:01:47 +03:00
/****************************************************************************
Send a extended security session setup blob , returning a reply blob .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static DATA_BLOB cli_session_setup_blob ( struct cli_state * cli , DATA_BLOB blob )
{
DATA_BLOB blob2 = data_blob ( NULL , 0 ) ;
if ( ! cli_session_setup_blob_send ( cli , blob ) ) {
return blob2 ;
}
return cli_session_setup_blob_receive ( cli ) ;
}
2003-02-24 05:55:00 +03:00
/****************************************************************************
Use in - memory credentials cache
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void use_in_memory_ccache ( void ) {
setenv ( KRB5_ENV_CCNAME , " MEMORY:cliconnect " , 1 ) ;
}
2001-10-12 08:49:42 +04:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
Do a spnego / kerberos encrypted session setup .
2001-10-12 08:49:42 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2002-11-13 02:20:50 +03:00
static BOOL cli_session_setup_kerberos ( struct cli_state * cli , const char * principal , const char * workgroup )
2001-10-12 08:49:42 +04:00
{
DATA_BLOB blob2 , negTokenTarg ;
2001-11-26 03:45:51 +03:00
DEBUG ( 2 , ( " Doing kerberos session setup \n " ) ) ;
2001-10-21 07:25:34 +04:00
2001-10-12 08:49:42 +04:00
/* generate the encapsulated kerberos5 ticket */
2002-09-25 19:19:00 +04:00
negTokenTarg = spnego_gen_negTokenTarg ( principal , 0 ) ;
2001-10-12 08:49:42 +04:00
if ( ! negTokenTarg . data ) return False ;
2001-10-18 14:26:06 +04:00
#if 0
file_save ( " negTokenTarg.dat " , negTokenTarg . data , negTokenTarg . length ) ;
# endif
2001-10-12 08:49:42 +04:00
blob2 = cli_session_setup_blob ( cli , negTokenTarg ) ;
/* we don't need this blob for kerberos */
2001-10-17 12:54:19 +04:00
data_blob_free ( & blob2 ) ;
2001-10-11 11:42:52 +04:00
2001-11-05 18:18:17 +03:00
data_blob_free ( & negTokenTarg ) ;
2001-10-12 08:49:42 +04:00
return ! cli_is_error ( cli ) ;
2001-10-11 11:42:52 +04:00
}
2003-06-26 09:26:20 +04:00
# endif /* HAVE_KRB5 */
2001-10-11 11:42:52 +04:00
2001-10-12 08:49:42 +04:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
Do a spnego / NTLMSSP encrypted session setup .
2001-10-12 08:49:42 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2002-11-13 02:20:50 +03:00
static BOOL cli_session_setup_ntlmssp ( struct cli_state * cli , const char * user ,
const char * pass , const char * workgroup )
2001-10-12 08:49:42 +04:00
{
2003-02-24 05:55:00 +03:00
struct ntlmssp_client_state * ntlmssp_state ;
NTSTATUS nt_status ;
int turn = 1 ;
DATA_BLOB msg1 ;
DATA_BLOB blob ;
DATA_BLOB blob_in = data_blob ( NULL , 0 ) ;
DATA_BLOB blob_out ;
2001-10-12 08:49:42 +04:00
2003-03-18 15:01:47 +03:00
cli_temp_set_signing ( cli ) ;
2003-02-24 05:55:00 +03:00
if ( ! NT_STATUS_IS_OK ( nt_status = ntlmssp_client_start ( & ntlmssp_state ) ) ) {
2001-10-12 08:49:42 +04:00
return False ;
2003-02-24 05:55:00 +03:00
}
2001-10-12 08:49:42 +04:00
2003-02-24 05:55:00 +03:00
if ( ! NT_STATUS_IS_OK ( nt_status = ntlmssp_set_username ( ntlmssp_state , user ) ) ) {
2001-10-12 08:49:42 +04:00
return False ;
}
2003-02-24 05:55:00 +03:00
if ( ! NT_STATUS_IS_OK ( nt_status = ntlmssp_set_domain ( ntlmssp_state , workgroup ) ) ) {
return False ;
2002-09-25 19:19:00 +04:00
}
2003-02-24 05:55:00 +03:00
if ( ! NT_STATUS_IS_OK ( nt_status = ntlmssp_set_password ( ntlmssp_state , pass ) ) ) {
2002-09-25 19:19:00 +04:00
return False ;
}
2001-10-12 08:49:42 +04:00
2003-02-24 05:55:00 +03:00
ntlmssp_state - > use_ntlmv2 = lp_client_ntlmv2_auth ( ) ;
do {
nt_status = ntlmssp_client_update ( ntlmssp_state ,
blob_in , & blob_out ) ;
data_blob_free ( & blob_in ) ;
if ( NT_STATUS_EQUAL ( nt_status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) {
if ( turn = = 1 ) {
/* and wrap it in a SPNEGO wrapper */
msg1 = gen_negTokenInit ( OID_NTLMSSP , blob_out ) ;
} else {
/* wrap it in SPNEGO */
msg1 = spnego_gen_auth ( blob_out ) ;
}
/* now send that blob on its way */
2003-03-18 15:01:47 +03:00
if ( ! cli_session_setup_blob_send ( cli , msg1 ) ) {
return False ;
}
2003-02-24 05:55:00 +03:00
data_blob_free ( & msg1 ) ;
2003-03-18 15:01:47 +03:00
cli_ntlmssp_set_signing ( cli , ntlmssp_state ) ;
blob = cli_session_setup_blob_receive ( cli ) ;
2003-02-24 05:55:00 +03:00
nt_status = cli_nt_error ( cli ) ;
}
if ( ! blob . length ) {
if ( NT_STATUS_IS_OK ( nt_status ) ) {
nt_status = NT_STATUS_UNSUCCESSFUL ;
}
} else if ( ( turn = = 1 ) & &
NT_STATUS_EQUAL ( nt_status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) {
DATA_BLOB tmp_blob = data_blob ( NULL , 0 ) ;
/* the server might give us back two challenges */
if ( ! spnego_parse_challenge ( blob , & blob_in ,
& tmp_blob ) ) {
DEBUG ( 3 , ( " Failed to parse challenges \n " ) ) ;
nt_status = NT_STATUS_INVALID_PARAMETER ;
}
data_blob_free ( & tmp_blob ) ;
} else {
if ( ! spnego_parse_auth_response ( blob , nt_status ,
& blob_in ) ) {
DEBUG ( 3 , ( " Failed to parse auth response \n " ) ) ;
if ( NT_STATUS_IS_OK ( nt_status )
| | NT_STATUS_EQUAL ( nt_status , NT_STATUS_MORE_PROCESSING_REQUIRED ) )
nt_status = NT_STATUS_INVALID_PARAMETER ;
}
}
data_blob_free ( & blob ) ;
data_blob_free ( & blob_out ) ;
turn + + ;
} while ( NT_STATUS_EQUAL ( nt_status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) ;
2001-10-12 08:49:42 +04:00
2003-02-24 05:55:00 +03:00
if ( NT_STATUS_IS_OK ( nt_status ) ) {
set_cli_session_key ( cli , ntlmssp_state - > session_key ) ;
}
2001-10-12 08:49:42 +04:00
2003-03-18 15:01:47 +03:00
/* we have a reference conter on ntlmssp_state, if we are signing
then the state will be kept by the signing engine */
2003-02-24 05:55:00 +03:00
if ( ! NT_STATUS_IS_OK ( ntlmssp_client_end ( & ntlmssp_state ) ) ) {
2002-09-25 19:19:00 +04:00
return False ;
2003-02-24 05:55:00 +03:00
}
2002-09-25 19:19:00 +04:00
2003-02-24 05:55:00 +03:00
return ( NT_STATUS_IS_OK ( nt_status ) ) ;
2001-10-12 08:49:42 +04:00
}
/****************************************************************************
2002-07-15 14:35:28 +04:00
Do a spnego encrypted session setup .
2001-10-12 08:49:42 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2002-11-13 02:20:50 +03:00
static BOOL cli_session_setup_spnego ( struct cli_state * cli , const char * user ,
const char * pass , const char * workgroup )
2001-10-12 08:49:42 +04:00
{
2001-10-22 00:51:27 +04:00
char * principal ;
2001-10-12 08:49:42 +04:00
char * OIDs [ ASN1_MAX_OIDS ] ;
int i ;
BOOL got_kerberos_mechanism = False ;
2002-09-25 19:19:00 +04:00
DATA_BLOB blob ;
2002-07-15 14:35:28 +04:00
2001-11-26 03:45:51 +03:00
DEBUG ( 2 , ( " Doing spnego session setup (blob length=%d) \n " , cli - > secblob . length ) ) ;
2001-10-21 07:25:34 +04:00
2001-10-14 09:42:28 +04:00
/* the server might not even do spnego */
2002-09-25 19:19:00 +04:00
if ( cli - > secblob . length < = 16 ) {
2001-10-14 09:42:28 +04:00
DEBUG ( 3 , ( " server didn't supply a full spnego negprot \n " ) ) ;
goto ntlmssp ;
}
2001-10-14 10:14:11 +04:00
#if 0
file_save ( " negprot.dat " , cli - > secblob . data , cli - > secblob . length ) ;
# endif
2002-09-25 19:19:00 +04:00
/* there is 16 bytes of GUID before the real spnego packet starts */
blob = data_blob ( cli - > secblob . data + 16 , cli - > secblob . length - 16 ) ;
2001-10-12 08:49:42 +04:00
/* the server sent us the first part of the SPNEGO exchange in the negprot
reply */
2002-09-25 19:19:00 +04:00
if ( ! spnego_parse_negTokenInit ( blob , OIDs , & principal ) ) {
data_blob_free ( & blob ) ;
2001-10-12 08:49:42 +04:00
return False ;
}
2002-09-25 19:19:00 +04:00
data_blob_free ( & blob ) ;
2001-10-12 08:49:42 +04:00
/* make sure the server understands kerberos */
for ( i = 0 ; OIDs [ i ] ; i + + ) {
DEBUG ( 3 , ( " got OID=%s \n " , OIDs [ i ] ) ) ;
2001-10-21 04:11:22 +04:00
if ( strcmp ( OIDs [ i ] , OID_KERBEROS5_OLD ) = = 0 | |
strcmp ( OIDs [ i ] , OID_KERBEROS5 ) = = 0 ) {
2001-10-12 08:49:42 +04:00
got_kerberos_mechanism = True ;
}
free ( OIDs [ i ] ) ;
}
2001-10-22 00:51:27 +04:00
DEBUG ( 3 , ( " got principal=%s \n " , principal ) ) ;
2001-10-12 08:49:42 +04:00
fstrcpy ( cli - > user_name , user ) ;
2001-11-29 02:54:07 +03:00
# ifdef HAVE_KRB5
2003-02-24 05:55:00 +03:00
/* If password is set we reauthenticate to kerberos server
* and do not store results */
2001-10-12 08:49:42 +04:00
if ( got_kerberos_mechanism & & cli - > use_kerberos ) {
2003-02-24 05:55:00 +03:00
if ( * pass ) {
int ret ;
use_in_memory_ccache ( ) ;
ret = kerberos_kinit_password ( user , pass , 0 /* no time correction for now */ ) ;
if ( ret ) {
DEBUG ( 0 , ( " Kinit failed: %s \n " , error_message ( ret ) ) ) ;
return False ;
}
}
2001-10-22 00:51:27 +04:00
return cli_session_setup_kerberos ( cli , principal , workgroup ) ;
2001-10-12 08:49:42 +04:00
}
# endif
2001-10-22 00:51:27 +04:00
free ( principal ) ;
2001-10-12 08:49:42 +04:00
2001-10-14 09:42:28 +04:00
ntlmssp :
2001-10-12 08:49:42 +04:00
return cli_session_setup_ntlmssp ( cli , user , pass , workgroup ) ;
}
2000-04-25 18:04:06 +04:00
/****************************************************************************
2001-02-14 08:34:50 +03:00
Send a session setup . The username and workgroup is in UNIX character
format and must be converted to DOS codepage format before sending . If the
password is in plaintext , the same should be done .
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2000-04-25 18:04:06 +04:00
BOOL cli_session_setup ( struct cli_state * cli ,
2002-11-13 02:20:50 +03:00
const char * user ,
const char * pass , int passlen ,
const char * ntpass , int ntpasslen ,
const char * workgroup )
2000-04-25 18:04:06 +04:00
{
char * p ;
2000-12-04 07:26:22 +03:00
fstring user2 ;
/* allow for workgroups as part of the username */
fstrcpy ( user2 , user ) ;
2002-01-06 07:03:26 +03:00
if ( ( p = strchr_m ( user2 , ' \\ ' ) ) | | ( p = strchr_m ( user2 , ' / ' ) ) | |
( p = strchr_m ( user2 , * lp_winbind_separator ( ) ) ) ) {
2000-12-04 07:26:22 +03:00
* p = 0 ;
user = p + 1 ;
workgroup = user2 ;
}
2000-04-25 18:04:06 +04:00
if ( cli - > protocol < PROTOCOL_LANMAN1 )
return True ;
2001-10-11 11:42:52 +04:00
/* now work out what sort of session setup we are going to
do . I have split this into separate functions to make the
flow a bit easier to understand ( tridge ) */
2000-04-25 18:04:06 +04:00
2001-10-11 11:42:52 +04:00
/* if its an older server then we have to use the older request format */
2002-09-25 19:19:00 +04:00
2003-06-08 16:49:31 +04:00
if ( cli - > protocol < PROTOCOL_NT1 ) {
if ( ! lp_client_lanman_auth ( ) & & passlen ! = 24 & & ( * pass ) ) {
DEBUG ( 1 , ( " Server requested LM password but 'client lanman auth' "
" is disabled \n " ) ) ;
return False ;
}
if ( ( cli - > sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE ) = = 0 & &
! lp_client_plaintext_auth ( ) & & ( * pass ) ) {
DEBUG ( 1 , ( " Server requested plaintext password but 'client use plaintext auth' "
" is disabled \n " ) ) ;
return False ;
}
2002-07-15 14:35:28 +04:00
return cli_session_setup_lanman2 ( cli , user , pass , passlen , workgroup ) ;
2003-06-08 16:49:31 +04:00
}
2000-04-25 18:04:06 +04:00
2001-10-11 11:42:52 +04:00
/* if no user is supplied then we have to do an anonymous connection.
passwords are ignored */
2002-09-25 19:19:00 +04:00
if ( ! user | | ! * user )
2001-10-11 11:42:52 +04:00
return cli_session_setup_guest ( cli ) ;
2001-08-10 10:00:33 +04:00
2001-10-11 11:42:52 +04:00
/* if the server is share level then send a plaintext null
password at this point . The password is sent in the tree
connect */
2002-09-25 19:19:00 +04:00
2003-06-08 16:49:31 +04:00
if ( ( cli - > sec_mode & NEGOTIATE_SECURITY_USER_LEVEL ) = = 0 )
2001-10-11 11:42:52 +04:00
return cli_session_setup_plaintext ( cli , user , " " , workgroup ) ;
2000-04-25 18:04:06 +04:00
2002-07-15 14:35:28 +04:00
/* if the server doesn't support encryption then we have to use
plaintext . The second password is ignored */
2002-09-25 19:19:00 +04:00
2003-06-08 16:49:31 +04:00
if ( ( cli - > sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE ) = = 0 ) {
if ( ! lp_client_plaintext_auth ( ) & & ( * pass ) ) {
DEBUG ( 1 , ( " Server requested plaintext password but 'client use plaintext auth' "
" is disabled \n " ) ) ;
return False ;
}
2001-10-11 11:42:52 +04:00
return cli_session_setup_plaintext ( cli , user , pass , workgroup ) ;
2003-06-08 16:49:31 +04:00
}
2000-04-25 18:04:06 +04:00
2001-10-11 11:42:52 +04:00
/* if the server supports extended security then use SPNEGO */
2002-09-25 19:19:00 +04:00
if ( cli - > capabilities & CAP_EXTENDED_SECURITY )
2001-10-11 11:42:52 +04:00
return cli_session_setup_spnego ( cli , user , pass , workgroup ) ;
2000-04-25 18:04:06 +04:00
2001-10-11 11:42:52 +04:00
/* otherwise do a NT1 style session setup */
2002-09-25 19:19:00 +04:00
2001-10-11 11:42:52 +04:00
return cli_session_setup_nt1 ( cli , user ,
pass , passlen , ntpass , ntpasslen ,
workgroup ) ;
2000-04-25 18:04:06 +04:00
}
/****************************************************************************
Send a uloggoff .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL cli_ulogoff ( struct cli_state * cli )
{
2002-07-15 14:35:28 +04:00
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
set_message ( cli - > outbuf , 2 , 0 , True ) ;
SCVAL ( cli - > outbuf , smb_com , SMBulogoffX ) ;
cli_setup_packet ( cli ) ;
2000-04-25 18:04:06 +04:00
SSVAL ( cli - > outbuf , smb_vwv0 , 0xFF ) ;
SSVAL ( cli - > outbuf , smb_vwv2 , 0 ) ; /* no additional info */
2002-07-15 14:35:28 +04:00
cli_send_smb ( cli ) ;
if ( ! cli_receive_smb ( cli ) )
return False ;
2000-04-25 18:04:06 +04:00
2002-07-15 14:35:28 +04:00
return ! cli_is_error ( cli ) ;
2000-04-25 18:04:06 +04:00
}
/****************************************************************************
2002-07-15 14:35:28 +04:00
Send a tconX .
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL cli_send_tconX ( struct cli_state * cli ,
2001-07-04 11:15:53 +04:00
const char * share , const char * dev , const char * pass , int passlen )
2000-04-25 18:04:06 +04:00
{
2002-07-15 14:35:28 +04:00
fstring fullshare , pword ;
2000-04-25 18:04:06 +04:00
char * p ;
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
memset ( cli - > inbuf , ' \0 ' , smb_size ) ;
fstrcpy ( cli - > share , share ) ;
/* in user level security don't send a password now */
2002-07-15 14:35:28 +04:00
if ( cli - > sec_mode & NEGOTIATE_SECURITY_USER_LEVEL ) {
2000-04-25 18:04:06 +04:00
passlen = 1 ;
pass = " " ;
}
2002-07-15 14:35:28 +04:00
if ( ( cli - > sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE ) & & * pass & & passlen ! = 24 ) {
2003-06-08 16:49:31 +04:00
if ( ! lp_client_lanman_auth ( ) ) {
DEBUG ( 1 , ( " Server requested LANMAN password but 'client use lanman auth' "
" is disabled \n " ) ) ;
return False ;
}
2000-04-25 18:04:06 +04:00
/*
* Non - encrypted passwords - convert to DOS codepage before encryption .
*/
passlen = 24 ;
2002-07-15 14:35:28 +04:00
SMBencrypt ( pass , cli - > secblob . data , ( uchar * ) pword ) ;
2000-04-25 18:04:06 +04:00
} else {
2002-07-15 14:35:28 +04:00
if ( ( cli - > sec_mode & ( NEGOTIATE_SECURITY_USER_LEVEL | NEGOTIATE_SECURITY_CHALLENGE_RESPONSE ) ) = = 0 ) {
2003-06-08 16:49:31 +04:00
if ( ! lp_client_plaintext_auth ( ) & & ( * pass ) ) {
DEBUG ( 1 , ( " Server requested plaintext password but 'client use plaintext auth' "
" is disabled \n " ) ) ;
return False ;
}
2000-04-25 18:04:06 +04:00
/*
* Non - encrypted passwords - convert to DOS codepage before using .
*/
2003-03-18 14:22:52 +03:00
passlen = clistr_push ( cli , pword , pass , sizeof ( pword ) , STR_TERMINATE ) ;
2003-06-08 16:49:31 +04:00
2000-04-25 18:04:06 +04:00
} else {
memcpy ( pword , pass , passlen ) ;
}
}
2003-03-05 03:54:16 +03:00
slprintf ( fullshare , sizeof ( fullshare ) - 1 ,
" \\ \\ %s \\ %s " , cli - > desthost , share ) ;
2000-04-25 18:04:06 +04:00
2001-02-20 13:11:40 +03:00
set_message ( cli - > outbuf , 4 , 0 , True ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( cli - > outbuf , smb_com , SMBtconX ) ;
2000-04-25 18:04:06 +04:00
cli_setup_packet ( cli ) ;
SSVAL ( cli - > outbuf , smb_vwv0 , 0xFF ) ;
SSVAL ( cli - > outbuf , smb_vwv3 , passlen ) ;
p = smb_buf ( cli - > outbuf ) ;
memcpy ( p , pword , passlen ) ;
p + = passlen ;
2001-07-04 11:15:53 +04:00
p + = clistr_push ( cli , p , fullshare , - 1 , STR_TERMINATE | STR_UPPER ) ;
2001-02-20 11:09:06 +03:00
fstrcpy ( p , dev ) ; p + = strlen ( dev ) + 1 ;
2001-02-20 15:45:50 +03:00
cli_setup_bcc ( cli , p ) ;
2000-04-25 18:04:06 +04:00
cli_send_smb ( cli ) ;
if ( ! cli_receive_smb ( cli ) )
return False ;
2002-09-25 19:19:00 +04:00
if ( cli_is_error ( cli ) )
2000-04-25 18:04:06 +04:00
return False ;
2001-11-20 11:45:22 +03:00
clistr_pull ( cli , cli - > dev , smb_buf ( cli - > inbuf ) , sizeof ( fstring ) , - 1 , STR_TERMINATE | STR_ASCII ) ;
2000-04-25 18:04:06 +04:00
if ( cli - > protocol > = PROTOCOL_NT1 & &
smb_buflen ( cli - > inbuf ) = = 3 ) {
/* almost certainly win95 - enable bug fixes */
cli - > win95 = True ;
}
cli - > cnum = SVAL ( cli - > inbuf , smb_tid ) ;
return True ;
}
/****************************************************************************
2002-07-15 14:35:28 +04:00
Send a tree disconnect .
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2000-04-25 18:04:06 +04:00
BOOL cli_tdis ( struct cli_state * cli )
{
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
set_message ( cli - > outbuf , 0 , 0 , True ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( cli - > outbuf , smb_com , SMBtdis ) ;
2000-04-25 18:04:06 +04:00
SSVAL ( cli - > outbuf , smb_tid , cli - > cnum ) ;
cli_setup_packet ( cli ) ;
cli_send_smb ( cli ) ;
if ( ! cli_receive_smb ( cli ) )
return False ;
2001-09-05 15:32:59 +04:00
return ! cli_is_error ( cli ) ;
2000-04-25 18:04:06 +04:00
}
2000-09-26 09:44:42 +04:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
Send a negprot command .
2000-09-26 09:44:42 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2000-09-26 09:44:42 +04:00
void cli_negprot_send ( struct cli_state * cli )
{
char * p ;
int numprots ;
2002-09-25 19:19:00 +04:00
if ( cli - > protocol < PROTOCOL_NT1 )
2002-07-15 14:35:28 +04:00
cli - > use_spnego = False ;
2000-09-26 09:44:42 +04:00
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
/* setup the protocol strings */
2001-02-26 02:46:02 +03:00
set_message ( cli - > outbuf , 0 , 0 , True ) ;
2000-09-26 09:44:42 +04:00
p = smb_buf ( cli - > outbuf ) ;
for ( numprots = 0 ;
prots [ numprots ] . name & & prots [ numprots ] . prot < = cli - > protocol ;
numprots + + ) {
* p + + = 2 ;
2001-07-04 11:15:53 +04:00
p + = clistr_push ( cli , p , prots [ numprots ] . name , - 1 , STR_TERMINATE ) ;
2000-09-26 09:44:42 +04:00
}
2002-01-11 22:10:25 +03:00
SCVAL ( cli - > outbuf , smb_com , SMBnegprot ) ;
2001-02-26 02:46:02 +03:00
cli_setup_bcc ( cli , p ) ;
2000-09-26 09:44:42 +04:00
cli_setup_packet ( cli ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( smb_buf ( cli - > outbuf ) , 0 , 2 ) ;
2000-09-26 09:44:42 +04:00
cli_send_smb ( cli ) ;
}
2000-04-25 18:04:06 +04:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
Send a negprot command .
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2000-04-25 18:04:06 +04:00
BOOL cli_negprot ( struct cli_state * cli )
{
char * p ;
int numprots ;
int plength ;
2002-09-25 19:19:00 +04:00
if ( cli - > protocol < PROTOCOL_NT1 )
2002-07-15 14:35:28 +04:00
cli - > use_spnego = False ;
2000-04-25 18:04:06 +04:00
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
/* setup the protocol strings */
for ( plength = 0 , numprots = 0 ;
prots [ numprots ] . name & & prots [ numprots ] . prot < = cli - > protocol ;
numprots + + )
plength + = strlen ( prots [ numprots ] . name ) + 2 ;
set_message ( cli - > outbuf , 0 , plength , True ) ;
p = smb_buf ( cli - > outbuf ) ;
for ( numprots = 0 ;
prots [ numprots ] . name & & prots [ numprots ] . prot < = cli - > protocol ;
numprots + + ) {
* p + + = 2 ;
2001-07-04 11:15:53 +04:00
p + = clistr_push ( cli , p , prots [ numprots ] . name , - 1 , STR_TERMINATE ) ;
2000-04-25 18:04:06 +04:00
}
2002-01-11 22:10:25 +03:00
SCVAL ( cli - > outbuf , smb_com , SMBnegprot ) ;
2000-04-25 18:04:06 +04:00
cli_setup_packet ( cli ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( smb_buf ( cli - > outbuf ) , 0 , 2 ) ;
2000-04-25 18:04:06 +04:00
cli_send_smb ( cli ) ;
if ( ! cli_receive_smb ( cli ) )
return False ;
show_msg ( cli - > inbuf ) ;
2001-09-05 15:32:59 +04:00
if ( cli_is_error ( cli ) | |
2000-04-25 18:04:06 +04:00
( ( int ) SVAL ( cli - > inbuf , smb_vwv0 ) > = numprots ) ) {
return ( False ) ;
}
2002-07-15 14:35:28 +04:00
cli - > protocol = prots [ SVAL ( cli - > inbuf , smb_vwv0 ) ] . prot ;
2000-04-25 18:04:06 +04:00
if ( cli - > protocol > = PROTOCOL_NT1 ) {
/* NT protocol */
cli - > sec_mode = CVAL ( cli - > inbuf , smb_vwv1 ) ;
cli - > max_mux = SVAL ( cli - > inbuf , smb_vwv1 + 1 ) ;
cli - > max_xmit = IVAL ( cli - > inbuf , smb_vwv3 + 1 ) ;
cli - > sesskey = IVAL ( cli - > inbuf , smb_vwv7 + 1 ) ;
cli - > serverzone = SVALS ( cli - > inbuf , smb_vwv15 + 1 ) ;
cli - > serverzone * = 60 ;
/* this time arrives in real GMT */
cli - > servertime = interpret_long_date ( cli - > inbuf + smb_vwv11 + 1 ) ;
2001-10-11 11:42:52 +04:00
cli - > secblob = data_blob ( smb_buf ( cli - > inbuf ) , smb_buflen ( cli - > inbuf ) ) ;
2000-04-25 18:04:06 +04:00
cli - > capabilities = IVAL ( cli - > inbuf , smb_vwv9 + 1 ) ;
2000-12-21 03:30:32 +03:00
if ( cli - > capabilities & CAP_RAW_MODE ) {
2000-04-25 18:04:06 +04:00
cli - > readbraw_supported = True ;
cli - > writebraw_supported = True ;
}
2001-06-21 09:38:28 +04:00
/* work out if they sent us a workgroup */
2001-11-20 11:45:22 +03:00
if ( ! ( cli - > capabilities & CAP_EXTENDED_SECURITY ) & &
smb_buflen ( cli - > inbuf ) > 8 ) {
2001-06-21 09:38:28 +04:00
clistr_pull ( cli , cli - > server_domain ,
smb_buf ( cli - > inbuf ) + 8 , sizeof ( cli - > server_domain ) ,
2001-07-04 11:15:53 +04:00
smb_buflen ( cli - > inbuf ) - 8 , STR_UNICODE | STR_NOALIGN ) ;
2001-06-21 09:38:28 +04:00
}
2002-07-15 14:35:28 +04:00
2003-02-24 05:55:00 +03:00
if ( ( cli - > sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED ) )
cli - > sign_info . negotiated_smb_signing = True ;
if ( ( cli - > sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED ) & & cli - > sign_info . allow_smb_signing )
2002-07-15 14:35:28 +04:00
cli - > sign_info . negotiated_smb_signing = True ;
2000-04-25 18:04:06 +04:00
} else if ( cli - > protocol > = PROTOCOL_LANMAN1 ) {
2002-07-15 14:35:28 +04:00
cli - > use_spnego = False ;
2000-04-25 18:04:06 +04:00
cli - > sec_mode = SVAL ( cli - > inbuf , smb_vwv1 ) ;
cli - > max_xmit = SVAL ( cli - > inbuf , smb_vwv2 ) ;
cli - > sesskey = IVAL ( cli - > inbuf , smb_vwv6 ) ;
cli - > serverzone = SVALS ( cli - > inbuf , smb_vwv10 ) ;
cli - > serverzone * = 60 ;
/* this time is converted to GMT by make_unix_date */
cli - > servertime = make_unix_date ( cli - > inbuf + smb_vwv8 ) ;
cli - > readbraw_supported = ( ( SVAL ( cli - > inbuf , smb_vwv5 ) & 0x1 ) ! = 0 ) ;
cli - > writebraw_supported = ( ( SVAL ( cli - > inbuf , smb_vwv5 ) & 0x2 ) ! = 0 ) ;
2001-10-11 11:42:52 +04:00
cli - > secblob = data_blob ( smb_buf ( cli - > inbuf ) , smb_buflen ( cli - > inbuf ) ) ;
2000-04-25 18:04:06 +04:00
} else {
/* the old core protocol */
2002-07-15 14:35:28 +04:00
cli - > use_spnego = False ;
2000-04-25 18:04:06 +04:00
cli - > sec_mode = 0 ;
cli - > serverzone = TimeDiff ( time ( NULL ) ) ;
}
cli - > max_xmit = MIN ( cli - > max_xmit , CLI_BUFFER_SIZE ) ;
2001-02-21 06:40:20 +03:00
/* a way to force ascii SMB */
2002-09-25 19:19:00 +04:00
if ( getenv ( " CLI_FORCE_ASCII " ) )
2001-02-21 06:40:20 +03:00
cli - > capabilities & = ~ CAP_UNICODE ;
2001-02-20 11:09:06 +03:00
2000-04-25 18:04:06 +04:00
return True ;
}
/****************************************************************************
2002-07-15 14:35:28 +04:00
Send a session request . See rfc1002 . txt 4.3 and 4.3 .2 .
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2000-04-25 18:04:06 +04:00
BOOL cli_session_request ( struct cli_state * cli ,
struct nmb_name * calling , struct nmb_name * called )
{
char * p ;
int len = 4 ;
extern pstring user_socket_options ;
memcpy ( & ( cli - > calling ) , calling , sizeof ( * calling ) ) ;
memcpy ( & ( cli - > called ) , called , sizeof ( * called ) ) ;
/* put in the destination name */
p = cli - > outbuf + len ;
name_mangle ( cli - > called . name , p , cli - > called . name_type ) ;
len + = name_len ( p ) ;
/* and my name */
p = cli - > outbuf + len ;
name_mangle ( cli - > calling . name , p , cli - > calling . name_type ) ;
len + = name_len ( p ) ;
2002-09-25 19:19:00 +04:00
/* 445 doesn't have session request */
if ( cli - > port = = 445 )
return True ;
/* send a session request (RFC 1002) */
2002-07-15 14:35:28 +04:00
/* setup the packet length
The 17-bit length field in the header contains the number of
bytes which follow the header, not the full packet size.
[Yes, the length field is either 17-bits, or (per the RFCs) it is a
16-bit length field preceeded by an 8-bit flags field of which only
the low-order bit may be used. If that bit is set, then add 65536 to
the 16-bit length field. (In other words, it's a 17-bit unsigned
length field.)
...unless, of course, the transport is native TCP [port 445] in which
case the length field *might* be 24-bits wide.]
Anyway, the change is a very minor one. We were including the four bytes
of the header in the length count and, as a result, sending four bytes of
garbage at the end of the SESSION REQUEST packet.
Small fix in function cli_session_request().
(This used to be commit d08471688b65371eb3de73b03a8ffaee86659ba0)
2002-07-01 07:42:28 +04:00
* Remove four bytes from the length count , since the length
* field in the NBT Session Service header counts the number
* of bytes which follow . The cli_send_smb ( ) function knows
* about this and accounts for those four bytes .
* CRH .
*/
len - = 4 ;
2000-04-25 18:04:06 +04:00
_smb_setlen ( cli - > outbuf , len ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( cli - > outbuf , 0 , 0x81 ) ;
2000-04-25 18:04:06 +04:00
cli_send_smb ( cli ) ;
DEBUG ( 5 , ( " Sent session request \n " ) ) ;
if ( ! cli_receive_smb ( cli ) )
return False ;
if ( CVAL ( cli - > inbuf , 0 ) = = 0x84 ) {
/* C. Hoch 9/14/95 Start */
/* For information, here is the response structure.
* We do the byte - twiddling to for portability .
struct RetargetResponse {
unsigned char type ;
unsigned char flags ;
int16 length ;
int32 ip_addr ;
int16 port ;
} ;
*/
int port = ( CVAL ( cli - > inbuf , 8 ) < < 8 ) + CVAL ( cli - > inbuf , 9 ) ;
/* SESSION RETARGET */
putip ( ( char * ) & cli - > dest_ip , cli - > inbuf + 4 ) ;
cli - > fd = open_socket_out ( SOCK_STREAM , & cli - > dest_ip , port , LONG_CONNECT_TIMEOUT ) ;
if ( cli - > fd = = - 1 )
return False ;
DEBUG ( 3 , ( " Retargeted \n " ) ) ;
set_socket_options ( cli - > fd , user_socket_options ) ;
/* Try again */
{
static int depth ;
BOOL ret ;
if ( depth > 4 ) {
DEBUG ( 0 , ( " Retarget recursion - failing \n " ) ) ;
return False ;
}
depth + + ;
ret = cli_session_request ( cli , calling , called ) ;
depth - - ;
return ret ;
}
} /* C. Hoch 9/14/95 End */
if ( CVAL ( cli - > inbuf , 0 ) ! = 0x82 ) {
/* This is the wrong place to put the error... JRA. */
cli - > rap_error = CVAL ( cli - > inbuf , 4 ) ;
return False ;
}
return ( True ) ;
}
/****************************************************************************
2002-07-15 14:35:28 +04:00
Open the client sockets .
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2000-04-25 18:04:06 +04:00
BOOL cli_connect ( struct cli_state * cli , const char * host , struct in_addr * ip )
{
extern pstring user_socket_options ;
2001-12-11 08:16:48 +03:00
int name_type = 0x20 ;
char * p ;
2000-04-25 18:04:06 +04:00
2001-12-11 08:48:27 +03:00
/* reasonable default hostname */
if ( ! host ) host = " *SMBSERVER " ;
2000-04-25 18:04:06 +04:00
fstrcpy ( cli - > desthost , host ) ;
2001-12-11 08:16:48 +03:00
/* allow hostnames of the form NAME#xx and do a netbios lookup */
if ( ( p = strchr ( cli - > desthost , ' # ' ) ) ) {
name_type = strtol ( p + 1 , NULL , 16 ) ;
* p = 0 ;
}
2000-04-25 18:04:06 +04:00
2001-11-26 06:11:44 +03:00
if ( ! ip | | is_zero_ip ( * ip ) ) {
2001-12-11 08:16:48 +03:00
if ( ! resolve_name ( cli - > desthost , & cli - > dest_ip , name_type ) ) {
2000-04-25 18:04:06 +04:00
return False ;
}
if ( ip ) * ip = cli - > dest_ip ;
} else {
cli - > dest_ip = * ip ;
}
2001-06-22 19:14:45 +04:00
if ( getenv ( " LIBSMB_PROG " ) ) {
cli - > fd = sock_exec ( getenv ( " LIBSMB_PROG " ) ) ;
2001-06-25 04:46:34 +04:00
} else {
2001-08-23 02:39:39 +04:00
/* try 445 first, then 139 */
int port = cli - > port ? cli - > port : 445 ;
2001-06-22 19:14:45 +04:00
cli - > fd = open_socket_out ( SOCK_STREAM , & cli - > dest_ip ,
2001-08-23 02:39:39 +04:00
port , cli - > timeout ) ;
if ( cli - > fd = = - 1 & & cli - > port = = 0 ) {
port = 139 ;
cli - > fd = open_socket_out ( SOCK_STREAM , & cli - > dest_ip ,
port , cli - > timeout ) ;
}
2002-09-25 19:19:00 +04:00
if ( cli - > fd ! = - 1 )
cli - > port = port ;
2001-06-22 19:14:45 +04:00
}
2001-08-23 20:25:57 +04:00
if ( cli - > fd = = - 1 ) {
DEBUG ( 1 , ( " Error connecting to %s (%s) \n " ,
2002-08-17 21:00:51 +04:00
ip ? inet_ntoa ( * ip ) : host , strerror ( errno ) ) ) ;
2000-04-25 18:04:06 +04:00
return False ;
2001-08-23 20:25:57 +04:00
}
2000-04-25 18:04:06 +04:00
set_socket_options ( cli - > fd , user_socket_options ) ;
return True ;
}
/****************************************************************************
2002-07-15 14:35:28 +04:00
Initialise client credentials for authenticated pipe access .
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-12-03 10:42:18 +03:00
2002-11-13 02:20:50 +03:00
static void init_creds ( struct ntuser_creds * creds , const char * username ,
const char * domain , const char * password )
2001-12-03 10:42:18 +03:00
{
ZERO_STRUCTP ( creds ) ;
pwd_set_cleartext ( & creds - > pwd , password ) ;
fstrcpy ( creds - > user_name , username ) ;
fstrcpy ( creds - > domain , domain ) ;
if ( ! * username ) {
creds - > pwd . null_pwd = True ;
}
}
2002-07-15 14:35:28 +04:00
/**
establishes a connection right up to doing tconX , password specified .
@ param output_cli A fully initialised cli structure , non - null only on success
@ param dest_host The netbios name of the remote host
@ param dest_ip ( optional ) The the destination IP , NULL for name based lookup
@ param port ( optional ) The destination port ( 0 for default )
@ param service ( optional ) The share to make the connection to . Should be ' unqualified ' in any way .
@ param service_type The ' type ' of serivice .
@ param user Username , unix string
@ param domain User ' s domain
@ param password User ' s password , unencrypted unix string .
2002-10-17 21:10:24 +04:00
@ param retry BOOL . Did this connection fail with a retryable error ?
2002-07-15 14:35:28 +04:00
*/
2001-12-03 10:42:18 +03:00
NTSTATUS cli_full_connection ( struct cli_state * * output_cli ,
2002-07-15 14:35:28 +04:00
const char * my_name ,
const char * dest_host ,
2001-12-03 10:42:18 +03:00
struct in_addr * dest_ip , int port ,
2002-11-13 02:20:50 +03:00
const char * service , const char * service_type ,
const char * user , const char * domain ,
const char * password , int flags ,
2002-10-17 21:10:24 +04:00
BOOL * retry )
2001-12-03 10:42:18 +03:00
{
struct ntuser_creds creds ;
NTSTATUS nt_status ;
struct nmb_name calling ;
struct nmb_name called ;
struct cli_state * cli ;
struct in_addr ip ;
2002-07-15 14:35:28 +04:00
2002-10-17 21:10:24 +04:00
if ( retry )
* retry = False ;
2002-07-15 14:35:28 +04:00
if ( ! my_name )
2002-11-13 02:20:50 +03:00
my_name = global_myname ( ) ;
2001-12-31 16:06:10 +03:00
2002-03-07 01:55:45 +03:00
if ( ! ( cli = cli_initialise ( NULL ) ) )
2001-12-03 10:42:18 +03:00
return NT_STATUS_NO_MEMORY ;
2002-07-15 14:35:28 +04:00
make_nmb_name ( & calling , my_name , 0x0 ) ;
make_nmb_name ( & called , dest_host , 0x20 ) ;
2001-12-03 10:42:18 +03:00
if ( cli_set_port ( cli , port ) ! = port ) {
2002-01-20 10:13:05 +03:00
cli_shutdown ( cli ) ;
2001-12-03 10:42:18 +03:00
return NT_STATUS_UNSUCCESSFUL ;
}
2002-10-17 21:10:24 +04:00
cli_set_timeout ( cli , 10000 ) ; /* 10 seconds. */
2002-09-25 19:19:00 +04:00
if ( dest_ip )
2002-07-15 14:35:28 +04:00
ip = * dest_ip ;
2002-09-25 19:19:00 +04:00
else
2002-07-15 14:35:28 +04:00
ZERO_STRUCT ( ip ) ;
again :
2002-03-07 01:55:45 +03:00
DEBUG ( 3 , ( " Connecting to host=%s share=%s \n " , dest_host , service ) ) ;
2001-12-03 10:42:18 +03:00
2002-03-07 01:55:45 +03:00
if ( ! cli_connect ( cli , dest_host , & ip ) ) {
2002-07-15 14:35:28 +04:00
DEBUG ( 1 , ( " cli_full_connection: failed to connect to %s (%s) \n " ,
nmb_namestr ( & called ) , inet_ntoa ( ip ) ) ) ;
2002-01-20 10:13:05 +03:00
cli_shutdown ( cli ) ;
2001-12-03 10:42:18 +03:00
return NT_STATUS_UNSUCCESSFUL ;
}
2002-10-17 21:10:24 +04:00
if ( retry )
* retry = True ;
2001-12-03 10:42:18 +03:00
if ( ! cli_session_request ( cli , & calling , & called ) ) {
char * p ;
DEBUG ( 1 , ( " session request to %s failed (%s) \n " ,
called . name , cli_errstr ( cli ) ) ) ;
2002-09-25 19:19:00 +04:00
if ( ( p = strchr ( called . name , ' . ' ) ) & & ! is_ipaddress ( called . name ) ) {
2001-12-03 10:42:18 +03:00
* p = 0 ;
goto again ;
}
if ( strcmp ( called . name , " *SMBSERVER " ) ) {
make_nmb_name ( & called , " *SMBSERVER " , 0x20 ) ;
goto again ;
}
return NT_STATUS_UNSUCCESSFUL ;
}
2002-09-25 19:19:00 +04:00
if ( flags & CLI_FULL_CONNECTION_DONT_SPNEGO )
2002-07-15 14:35:28 +04:00
cli - > use_spnego = False ;
2002-09-25 19:19:00 +04:00
else if ( flags & CLI_FULL_CONNECTION_USE_KERBEROS )
2002-07-15 14:35:28 +04:00
cli - > use_kerberos = True ;
2002-03-07 01:55:45 +03:00
if ( ! cli_negprot ( cli ) ) {
2001-12-03 10:42:18 +03:00
DEBUG ( 1 , ( " failed negprot \n " ) ) ;
2002-01-11 07:50:45 +03:00
nt_status = NT_STATUS_UNSUCCESSFUL ;
2001-12-03 10:42:18 +03:00
cli_shutdown ( cli ) ;
return nt_status ;
}
2002-07-15 14:35:28 +04:00
if ( ! cli_session_setup ( cli , user , password , strlen ( password ) + 1 ,
password , strlen ( password ) + 1 ,
2002-03-07 01:55:45 +03:00
domain ) ) {
2002-08-17 21:00:51 +04:00
if ( ( flags & CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK )
& & cli_session_setup ( cli , " " , " " , 0 , " " , 0 , domain ) ) {
2002-07-15 14:35:28 +04:00
} else {
nt_status = cli_nt_error ( cli ) ;
DEBUG ( 1 , ( " failed session setup with %s \n " , nt_errstr ( nt_status ) ) ) ;
cli_shutdown ( cli ) ;
if ( NT_STATUS_IS_OK ( nt_status ) )
nt_status = NT_STATUS_UNSUCCESSFUL ;
return nt_status ;
}
2001-12-03 10:42:18 +03:00
}
2002-03-07 01:55:45 +03:00
if ( service ) {
2001-12-03 10:42:18 +03:00
if ( ! cli_send_tconX ( cli , service , service_type ,
2002-11-13 02:20:50 +03:00
password , strlen ( password ) + 1 ) ) {
2001-12-03 10:42:18 +03:00
nt_status = cli_nt_error ( cli ) ;
2003-01-04 12:01:19 +03:00
DEBUG ( 1 , ( " failed tcon_X with %s \n " , nt_errstr ( nt_status ) ) ) ;
2001-12-03 10:42:18 +03:00
cli_shutdown ( cli ) ;
2002-07-15 14:35:28 +04:00
if ( NT_STATUS_IS_OK ( nt_status ) ) {
2002-03-07 01:55:45 +03:00
nt_status = NT_STATUS_UNSUCCESSFUL ;
2002-07-15 14:35:28 +04:00
}
2001-12-03 10:42:18 +03:00
return nt_status ;
}
}
2002-07-15 14:35:28 +04:00
init_creds ( & creds , user , domain , password ) ;
2001-12-03 10:42:18 +03:00
cli_init_creds ( cli , & creds ) ;
* output_cli = cli ;
return NT_STATUS_OK ;
}
2000-04-25 18:04:06 +04:00
/****************************************************************************
Attempt a NetBIOS session request , falling back to * SMBSERVER if needed .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-11-09 02:08:59 +03:00
BOOL attempt_netbios_session_request ( struct cli_state * cli , const char * srchost , const char * desthost ,
2000-04-25 18:04:06 +04:00
struct in_addr * pdest_ip )
{
2002-07-15 14:35:28 +04:00
struct nmb_name calling , called ;
2000-04-25 18:04:06 +04:00
2002-07-15 14:35:28 +04:00
make_nmb_name ( & calling , srchost , 0x0 ) ;
2000-04-25 18:04:06 +04:00
2002-07-15 14:35:28 +04:00
/*
* If the called name is an IP address
* then use * SMBSERVER immediately .
*/
2000-04-25 18:04:06 +04:00
2002-07-15 14:35:28 +04:00
if ( is_ipaddress ( desthost ) )
make_nmb_name ( & called , " *SMBSERVER " , 0x20 ) ;
else
make_nmb_name ( & called , desthost , 0x20 ) ;
2000-04-25 18:04:06 +04:00
2002-07-15 14:35:28 +04:00
if ( ! cli_session_request ( cli , & calling , & called ) ) {
struct nmb_name smbservername ;
2000-04-25 18:04:06 +04:00
2002-07-15 14:35:28 +04:00
make_nmb_name ( & smbservername , " *SMBSERVER " , 0x20 ) ;
2000-04-25 18:04:06 +04:00
2002-07-15 14:35:28 +04:00
/*
* If the name wasn ' t * SMBSERVER then
* try with * SMBSERVER if the first name fails .
*/
2000-04-25 18:04:06 +04:00
2002-07-15 14:35:28 +04:00
if ( nmb_name_equal ( & called , & smbservername ) ) {
2000-04-25 18:04:06 +04:00
2002-07-15 14:35:28 +04:00
/*
* The name used was * SMBSERVER , don ' t bother with another name .
*/
2000-04-25 18:04:06 +04:00
2002-07-15 14:35:28 +04:00
DEBUG ( 0 , ( " attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2000-04-25 18:04:06 +04:00
with error % s . \ n " , desthost, cli_errstr(cli) ));
2002-07-15 14:35:28 +04:00
return False ;
}
2000-04-25 18:04:06 +04:00
2002-09-25 19:19:00 +04:00
/*
* We need to close the connection here but can ' t call cli_shutdown as
* will free an allocated cli struct . cli_close_connection was invented
* for this purpose . JRA . Based on work by " Kim R. Pedersen " < krp @ filanet . dk > .
*/
cli_close_connection ( cli ) ;
2000-04-25 18:04:06 +04:00
2002-07-15 14:35:28 +04:00
if ( ! cli_initialise ( cli ) | |
! cli_connect ( cli , desthost , pdest_ip ) | |
! cli_session_request ( cli , & calling , & smbservername ) ) {
DEBUG ( 0 , ( " attempt_netbios_session_request: %s rejected the session for \
2000-04-25 18:04:06 +04:00
name * SMBSERVER with error % s \ n " , desthost, cli_errstr(cli) ));
2002-07-15 14:35:28 +04:00
return False ;
}
}
2000-04-25 18:04:06 +04:00
2002-07-15 14:35:28 +04:00
return True ;
2000-04-25 18:04:06 +04:00
}
2003-04-14 08:15:24 +04:00
/****************************************************************************
Send an old style tcon .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS cli_raw_tcon ( struct cli_state * cli ,
const char * service , const char * pass , const char * dev ,
uint16 * max_xmit , uint16 * tid )
{
char * p ;
2003-06-08 16:49:31 +04:00
if ( ! lp_client_plaintext_auth ( ) & & ( * pass ) ) {
DEBUG ( 1 , ( " Server requested plaintext password but 'client use plaintext auth' "
" is disabled \n " ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
2003-04-14 08:15:24 +04:00
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
memset ( cli - > inbuf , ' \0 ' , smb_size ) ;
set_message ( cli - > outbuf , 0 , 0 , True ) ;
SCVAL ( cli - > outbuf , smb_com , SMBtcon ) ;
cli_setup_packet ( cli ) ;
p = smb_buf ( cli - > outbuf ) ;
* p + + = 4 ; p + = clistr_push ( cli , p , service , - 1 , STR_TERMINATE | STR_NOALIGN ) ;
* p + + = 4 ; p + = clistr_push ( cli , p , pass , - 1 , STR_TERMINATE | STR_NOALIGN ) ;
* p + + = 4 ; p + = clistr_push ( cli , p , dev , - 1 , STR_TERMINATE | STR_NOALIGN ) ;
cli_setup_bcc ( cli , p ) ;
cli_send_smb ( cli ) ;
if ( ! cli_receive_smb ( cli ) ) {
return NT_STATUS_UNEXPECTED_NETWORK_ERROR ;
}
if ( cli_is_error ( cli ) ) {
return cli_nt_error ( cli ) ;
}
* max_xmit = SVAL ( cli - > inbuf , smb_vwv0 ) ;
* tid = SVAL ( cli - > inbuf , smb_vwv1 ) ;
return NT_STATUS_OK ;
}
/* Return a cli_state pointing at the IPC$ share for the given server */
struct cli_state * get_ipc_connect ( char * server , struct in_addr * server_ip ,
struct user_auth_info * user_info )
{
struct cli_state * cli ;
pstring myname ;
NTSTATUS nt_status ;
get_myname ( myname ) ;
nt_status = cli_full_connection ( & cli , myname , server , server_ip , 0 , " IPC$ " , " IPC " ,
user_info - > username , lp_workgroup ( ) , user_info - > password ,
CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK , NULL ) ;
if ( NT_STATUS_IS_OK ( nt_status ) ) {
return cli ;
} else if ( is_ipaddress ( server ) ) {
/* windows 9* needs a correct NMB name for connections */
fstring remote_name ;
if ( name_status_find ( " * " , 0 , 0 , * server_ip , remote_name ) ) {
cli = get_ipc_connect ( remote_name , server_ip , user_info ) ;
if ( cli )
return cli ;
}
}
return NULL ;
}
/* Return the IP address and workgroup of a master browser on the
network . */
struct cli_state * get_ipc_connect_master_ip_bcast ( pstring workgroup , struct user_auth_info * user_info )
{
2003-06-25 21:41:05 +04:00
struct ip_service * ip_list ;
2003-04-14 08:15:24 +04:00
struct cli_state * cli ;
int i , count ;
struct in_addr server_ip ;
/* Go looking for workgroups by broadcasting on the local network */
if ( ! name_resolve_bcast ( MSBROWSE , 1 , & ip_list , & count ) ) {
return False ;
}
for ( i = 0 ; i < count ; i + + ) {
static fstring name ;
2003-06-25 21:41:05 +04:00
if ( ! name_status_find ( " * " , 0 , 0x1d , ip_list [ i ] . ip , name ) )
2003-04-14 08:15:24 +04:00
continue ;
if ( ! find_master_ip ( name , & server_ip ) )
continue ;
pstrcpy ( workgroup , name ) ;
DEBUG ( 4 , ( " found master browser %s, %s \n " ,
2003-06-25 21:41:05 +04:00
name , inet_ntoa ( ip_list [ i ] . ip ) ) ) ;
2003-04-14 08:15:24 +04:00
cli = get_ipc_connect ( inet_ntoa ( server_ip ) , & server_ip , user_info ) ;
if ( ! cli )
continue ;
return cli ;
}
return NULL ;
}