1997-10-21 13:12:41 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1997-10-21 13:12:41 +04:00
SMB client generic functions
1999-12-13 16:27:58 +03:00
Copyright ( C ) Andrew Tridgell 1994 - 1998
1997-10-21 13:12:41 +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 .
*/
1998-07-29 07:08:05 +04:00
# define NO_SYSLOG
1997-10-21 13:12:41 +04:00
# include "includes.h"
1999-12-13 16:27:58 +03:00
/*
* Change the port number used to call on
*/
1999-01-25 04:46:14 +03:00
int cli_set_port ( struct cli_state * cli , int port )
{
2001-08-25 00:11:09 +04:00
cli - > port = port ;
return port ;
1999-01-25 04:46:14 +03:00
}
1998-10-19 06:48:57 +04:00
2002-07-15 14:35:28 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Read an smb from a fd ignoring all keepalive packets . Note that the buffer
* MUST * be of size BUFFER_SIZE + SAFETY_MARGIN .
The timeout is in milliseconds
This is exactly the same as receive_smb except that it never returns
a session keepalive packet ( just as receive_smb used to do ) .
receive_smb was changed to return keepalives as the oplock processing means this call
should never go into a blocking read .
2002-07-15 14:35:28 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL client_receive_smb ( int fd , char * buffer , unsigned int timeout )
{
2002-09-25 19:19:00 +04:00
BOOL ret ;
for ( ; ; ) {
ret = receive_smb ( fd , buffer , timeout ) ;
2002-07-15 14:35:28 +04:00
2002-09-25 19:19:00 +04:00
if ( ! ret ) {
DEBUG ( 10 , ( " client_receive_smb failed \n " ) ) ;
show_msg ( buffer ) ;
return ret ;
}
/* Ignore session keepalive packets. */
if ( CVAL ( buffer , 0 ) ! = SMBkeepalive )
break ;
}
show_msg ( buffer ) ;
return ret ;
}
2002-07-15 14:35:28 +04:00
1999-10-08 02:10:29 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Recv an smb .
1999-10-08 02:10:29 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2000-04-25 18:04:06 +04:00
BOOL cli_receive_smb ( struct cli_state * cli )
1999-10-08 02:10:29 +04:00
{
2002-10-01 05:41:20 +04:00
extern int smb_read_error ;
1999-12-13 16:27:58 +03:00
BOOL ret ;
2001-11-21 14:04:49 +03:00
/* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */
2002-09-25 19:19:00 +04:00
if ( cli - > fd = = - 1 )
return False ;
2001-11-21 14:04:49 +03:00
1999-12-13 16:27:58 +03:00
again :
ret = client_receive_smb ( cli - > fd , cli - > inbuf , cli - > timeout ) ;
if ( ret ) {
/* it might be an oplock break request */
2000-01-10 16:40:27 +03:00
if ( ! ( CVAL ( cli - > inbuf , smb_flg ) & FLAG_REPLY ) & &
CVAL ( cli - > inbuf , smb_com ) = = SMBlockingX & &
1999-12-13 16:27:58 +03:00
SVAL ( cli - > inbuf , smb_vwv6 ) = = 0 & &
SVAL ( cli - > inbuf , smb_vwv7 ) = = 0 ) {
2001-06-18 12:26:15 +04:00
if ( cli - > oplock_handler ) {
int fnum = SVAL ( cli - > inbuf , smb_vwv2 ) ;
unsigned char level = CVAL ( cli - > inbuf , smb_vwv3 + 1 ) ;
if ( ! cli - > oplock_handler ( cli , fnum , level ) ) return False ;
}
1999-12-13 16:27:58 +03:00
/* try to prevent loops */
2002-01-11 22:10:25 +03:00
SCVAL ( cli - > inbuf , smb_com , 0xFF ) ;
1999-12-13 16:27:58 +03:00
goto again ;
1999-10-08 02:10:29 +04:00
}
}
2001-11-14 08:58:51 +03:00
/* If the server is not responding, note that now */
if ( ! ret ) {
close ( cli - > fd ) ;
cli - > fd = - 1 ;
2002-10-01 05:41:20 +04:00
cli - > smb_read_error = smb_read_error ;
2001-11-14 08:58:51 +03:00
}
1999-12-13 16:27:58 +03:00
return ret ;
1998-11-09 06:45:49 +03:00
}
1998-10-19 06:48:57 +04:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
Send an smb to a fd .
1998-10-19 06:48:57 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-14 07:15:36 +03:00
2000-04-25 18:04:06 +04:00
BOOL cli_send_smb ( struct cli_state * cli )
1998-10-19 06:48:57 +04:00
{
size_t len ;
size_t nwritten = 0 ;
ssize_t ret ;
2001-11-21 14:04:49 +03:00
/* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */
2002-07-15 14:35:28 +04:00
if ( cli - > fd = = - 1 )
return False ;
cli_caclulate_sign_mac ( cli ) ;
2001-11-21 14:04:49 +03:00
1999-08-19 00:10:12 +04:00
len = smb_len ( cli - > outbuf ) + 4 ;
1998-10-19 06:48:57 +04:00
while ( nwritten < len ) {
ret = write_socket ( cli - > fd , cli - > outbuf + nwritten , len - nwritten ) ;
if ( ret < = 0 ) {
2002-07-15 14:35:28 +04:00
close ( cli - > fd ) ;
cli - > fd = - 1 ;
DEBUG ( 0 , ( " Error writing %d bytes to client. %d \n " , ( int ) len , ( int ) ret ) ) ;
2000-04-11 17:55:53 +04:00
return False ;
1998-10-19 06:48:57 +04:00
}
nwritten + = ret ;
}
return True ;
}
1999-12-13 16:27:58 +03:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
Setup basics in a outgoing packet .
1999-12-13 16:27:58 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2000-04-25 18:04:06 +04:00
void cli_setup_packet ( struct cli_state * cli )
1999-12-13 16:27:58 +03:00
{
2002-07-15 14:35:28 +04:00
cli - > rap_error = 0 ;
1999-12-13 16:27:58 +03:00
SSVAL ( cli - > outbuf , smb_pid , cli - > pid ) ;
SSVAL ( cli - > outbuf , smb_uid , cli - > vuid ) ;
SSVAL ( cli - > outbuf , smb_mid , cli - > mid ) ;
if ( cli - > protocol > PROTOCOL_CORE ) {
2001-02-20 11:09:06 +03:00
uint16 flags2 ;
1999-12-13 16:27:58 +03:00
SCVAL ( cli - > outbuf , smb_flg , 0x8 ) ;
2001-02-20 11:09:06 +03:00
flags2 = FLAGS2_LONG_PATH_COMPONENTS ;
2002-09-25 19:19:00 +04:00
if ( cli - > capabilities & CAP_UNICODE )
2001-02-20 11:09:06 +03:00
flags2 | = FLAGS2_UNICODE_STRINGS ;
2002-09-25 19:19:00 +04:00
if ( cli - > capabilities & CAP_STATUS32 )
2001-08-27 12:19:43 +04:00
flags2 | = FLAGS2_32_BIT_ERROR_CODES ;
2002-09-25 19:19:00 +04:00
if ( cli - > use_spnego )
2001-10-22 10:48:35 +04:00
flags2 | = FLAGS2_EXTENDED_SECURITY ;
2002-09-25 19:19:00 +04:00
if ( cli - > sign_info . use_smb_signing
| | cli - > sign_info . temp_smb_signing )
2002-07-15 14:35:28 +04:00
flags2 | = FLAGS2_SMB_SECURITY_SIGNATURES ;
2001-02-20 11:09:06 +03:00
SSVAL ( cli - > outbuf , smb_flg2 , flags2 ) ;
1999-12-13 16:27:58 +03:00
}
1999-06-24 22:58:08 +04:00
}
2001-02-20 15:45:50 +03:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Setup the bcc length of the packet from a pointer to the end of the data .
2001-02-20 15:45:50 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2001-02-20 15:45:50 +03:00
void cli_setup_bcc ( struct cli_state * cli , void * p )
{
set_message_bcc ( cli - > outbuf , PTR_DIFF ( p , smb_buf ( cli - > outbuf ) ) ) ;
}
1999-12-13 16:27:58 +03:00
2000-07-03 08:24:31 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Initialise credentials of a client structure .
2000-07-03 08:24:31 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2000-07-03 08:24:31 +04:00
void cli_init_creds ( struct cli_state * cli , const struct ntuser_creds * usr )
{
/* copy_nt_creds(&cli->usr, usr); */
safe_strcpy ( cli - > domain , usr - > domain , sizeof ( usr - > domain ) - 1 ) ;
safe_strcpy ( cli - > user_name , usr - > user_name , sizeof ( usr - > user_name ) - 1 ) ;
memcpy ( & cli - > pwd , & usr - > pwd , sizeof ( usr - > pwd ) ) ;
cli - > ntlmssp_flags = usr - > ntlmssp_flags ;
cli - > ntlmssp_cli_flgs = usr ! = NULL ? usr - > ntlmssp_flags : 0 ;
DEBUG ( 10 , ( " cli_init_creds: user %s domain %s flgs: %x \n ntlmssp_cli_flgs:%x \n " ,
cli - > user_name , cli - > domain ,
cli - > ntlmssp_flags , cli - > ntlmssp_cli_flgs ) ) ;
}
1998-04-24 00:12:17 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Initialise a client structure .
1998-04-24 00:12:17 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2000-04-25 18:04:06 +04:00
struct cli_state * cli_initialise ( struct cli_state * cli )
1998-04-24 00:12:17 +04:00
{
2001-08-07 03:29:25 +04:00
BOOL alloced_cli = False ;
2001-10-31 04:52:34 +03:00
/* Check the effective uid - make sure we are not setuid */
if ( is_setuid_root ( ) ) {
DEBUG ( 0 , ( " libsmb based programs must *NOT* be setuid root. \n " ) ) ;
return NULL ;
}
2000-04-25 18:04:06 +04:00
if ( ! cli ) {
cli = ( struct cli_state * ) malloc ( sizeof ( * cli ) ) ;
if ( ! cli )
return NULL ;
ZERO_STRUCTP ( cli ) ;
2001-08-07 03:29:25 +04:00
alloced_cli = True ;
Makefile.in :
- added srvsvc client files
clientgen.c :
- replaced cli_error(cli, int *cls, int *err) with
cli_error(cli, uint8 cls, uint32 *err). this version detects
32 bit status messages. the DOS error "MORE_DATA", the
equivalent of the 32 bit *warning* 0x8000 0005
(STATUS_BUFFER_OVERFLOW), was being processed as an error,
terminating the cli_receive_trans() call.
cli_pipe.c :
- replaced calls that had been incorrectly modified from
32 bit warnings (0x8000 0005 - STATUS_BUFFER_OVERFLOW)
to 8 bit DOS errors (0x01 0xEA - MORE_DATA).
the use of the old version of cli_error (DOS only)
instead of the new one (DOS and 32 bit) caused the
dce/rpc client code to fail.
- replaced 2 space indentation with tab indentation in all functions.
cli_srvsvc.c :
cmd_srvsvc.c :
- added these files back in, fixing them up to use jeremy's
modified versions of the dce/rpc client functions.
parse_srv.c :
- added back in some "unused" functions required by dce/rpc
client-side code. it would be helpful if all such "unused"
functions could be added back in.
rpcclient.c :
- added "session", "file", "share", "connection" enumeration
functions back in. these are equivalent to nt's "NetXXXXXEnum"
Win32 (MSDN) functions.
- added "srvinfo" function back in. this is equivalent to
nt's NetServerGetInfo Win32 (MSDN) function.
(This used to be commit bcf39ffdcc64e049bca2d70a394a99976291e81d)
1998-10-03 01:09:23 +04:00
}
1998-04-24 02:59:19 +04:00
2002-09-25 19:19:00 +04:00
if ( cli - > initialised )
cli_close_connection ( cli ) ;
1999-10-08 02:10:29 +04:00
2000-04-25 18:04:06 +04:00
ZERO_STRUCTP ( cli ) ;
1999-12-13 16:27:58 +03:00
2000-04-25 18:04:06 +04:00
cli - > port = 0 ;
cli - > fd = - 1 ;
cli - > cnum = - 1 ;
2000-05-02 06:23:41 +04:00
cli - > pid = ( uint16 ) sys_getpid ( ) ;
2000-04-25 18:04:06 +04:00
cli - > mid = 1 ;
cli - > vuid = UID_FIELD_INVALID ;
cli - > protocol = PROTOCOL_NT1 ;
cli - > timeout = 20000 ; /* Timeout is in milliseconds. */
cli - > bufsize = CLI_BUFFER_SIZE + 4 ;
cli - > max_xmit = cli - > bufsize ;
cli - > outbuf = ( char * ) malloc ( cli - > bufsize ) ;
cli - > inbuf = ( char * ) malloc ( cli - > bufsize ) ;
2001-06-18 12:26:15 +04:00
cli - > oplock_handler = cli_oplock_ack ;
2002-09-25 19:19:00 +04:00
if ( lp_use_spnego ( ) ) {
cli - > use_spnego = True ;
}
2001-06-18 12:26:15 +04:00
2001-11-25 05:35:37 +03:00
/* Set the CLI_FORCE_DOSERR environment variable to test
client routines using DOS errors instead of STATUS32
ones . This intended only as a temporary hack . */
if ( getenv ( " CLI_FORCE_DOSERR " ) ) {
cli - > force_dos_errors = True ;
}
2002-09-25 19:19:00 +04:00
/* A way to attempt to force SMB signing */
if ( getenv ( " CLI_FORCE_SMB_SIGNING " ) )
cli - > sign_info . negotiated_smb_signing = True ;
2000-04-25 18:04:06 +04:00
if ( ! cli - > outbuf | | ! cli - > inbuf )
2001-08-06 06:18:40 +04:00
goto error ;
1997-10-26 10:32:02 +03:00
2002-01-28 03:54:37 +03:00
if ( ( cli - > mem_ctx = talloc_init_named ( " cli based talloc " ) ) = = NULL )
2001-08-06 06:18:40 +04:00
goto error ;
2000-07-27 04:47:19 +04:00
2001-08-06 06:18:40 +04:00
memset ( cli - > outbuf , 0 , cli - > bufsize ) ;
memset ( cli - > inbuf , 0 , cli - > bufsize ) ;
1997-10-26 10:32:02 +03:00
2001-05-04 11:28:41 +04:00
cli - > nt_pipe_fnum = 0 ;
2000-04-25 18:04:06 +04:00
cli - > initialised = 1 ;
2001-11-27 06:29:20 +03:00
cli - > allocated = alloced_cli ;
1997-10-26 10:32:02 +03:00
2000-04-25 18:04:06 +04:00
return cli ;
2001-08-06 06:18:40 +04:00
/* Clean up after malloc() error */
error :
2001-09-17 07:33:37 +04:00
SAFE_FREE ( cli - > inbuf ) ;
SAFE_FREE ( cli - > outbuf ) ;
2001-08-06 06:18:40 +04:00
2001-08-07 03:29:25 +04:00
if ( alloced_cli )
2001-09-17 07:33:37 +04:00
SAFE_FREE ( cli ) ;
2001-08-07 03:29:25 +04:00
2001-08-06 06:18:40 +04:00
return NULL ;
1997-10-26 10:32:02 +03:00
}
1997-10-21 13:12:41 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Close a client connection and free the memory without destroying cli itself .
1997-10-21 13:12:41 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
void cli_close_connection ( struct cli_state * cli )
1997-10-21 13:12:41 +04:00
{
2001-09-17 07:33:37 +04:00
SAFE_FREE ( cli - > outbuf ) ;
SAFE_FREE ( cli - > inbuf ) ;
2000-07-27 04:47:19 +04:00
2001-10-17 12:54:19 +04:00
data_blob_free ( & cli - > secblob ) ;
2001-10-11 11:42:52 +04:00
2002-09-25 19:19:00 +04:00
if ( cli - > mem_ctx ) {
2000-07-27 04:47:19 +04:00
talloc_destroy ( cli - > mem_ctx ) ;
2002-09-25 19:19:00 +04:00
cli - > mem_ctx = NULL ;
}
2000-07-27 04:47:19 +04:00
2000-04-25 18:04:06 +04:00
if ( cli - > fd ! = - 1 )
2001-10-11 11:42:52 +04:00
close ( cli - > fd ) ;
2002-09-25 19:19:00 +04:00
cli - > fd = - 1 ;
}
/****************************************************************************
Shutdown a client structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void cli_shutdown ( struct cli_state * cli )
{
BOOL allocated = cli - > allocated ;
cli_close_connection ( cli ) ;
2001-11-27 06:29:20 +03:00
ZERO_STRUCTP ( cli ) ;
if ( allocated ) {
free ( cli ) ;
}
1997-10-21 13:12:41 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Set socket options on a open connection .
1997-10-21 13:12:41 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2000-04-25 18:04:06 +04:00
void cli_sockopt ( struct cli_state * cli , char * options )
1997-10-21 13:12:41 +04:00
{
2000-04-25 18:04:06 +04:00
set_socket_options ( cli - > fd , options ) ;
1997-10-21 13:12:41 +04:00
}
1997-11-30 05:58:34 +03:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Set the PID to use for smb messages . Return the old pid .
1997-11-30 05:58:34 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2000-04-25 18:04:06 +04:00
uint16 cli_setpid ( struct cli_state * cli , uint16 pid )
1997-11-30 05:58:34 +03:00
{
2000-04-25 18:04:06 +04:00
uint16 ret = cli - > pid ;
cli - > pid = pid ;
return ret ;
1997-11-30 05:58:34 +03:00
}
2002-09-25 19:19:00 +04:00
/****************************************************************************
Send a keepalive packet to the server
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL cli_send_keepalive ( struct cli_state * cli )
{
if ( cli - > fd = = - 1 ) {
DEBUG ( 3 , ( " cli_send_keepalive: fd == -1 \n " ) ) ;
return False ;
}
if ( ! send_keepalive ( cli - > fd ) ) {
close ( cli - > fd ) ;
cli - > fd = - 1 ;
DEBUG ( 0 , ( " Error sending keepalive packet to client. \n " ) ) ;
return False ;
}
return True ;
}