2008-09-25 03:01:00 +04:00
/*
* traffic - analyzer VFS module . Measure the smb traffic users create
* on the net .
*
2010-03-16 17:04:51 +03:00
* Copyright ( C ) Holger Hetterich , 2008 - 2010
2008-10-01 23:50:29 +04:00
* Copyright ( C ) Jeremy Allison , 2008
2008-09-25 03:01:00 +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 3 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 , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
2011-03-23 00:34:22 +03:00
# include "smbd/smbd.h"
2011-02-13 20:20:00 +03:00
# include "../smbd/globals.h"
2009-12-14 22:43:15 +03:00
# include "../lib/crypto/crypto.h"
2010-02-02 21:36:23 +03:00
# include "vfs_smb_traffic_analyzer.h"
2010-10-12 08:27:50 +04:00
# include "../libcli/security/security.h"
2010-08-05 04:25:37 +04:00
# include "secrets.h"
2010-08-05 17:14:04 +04:00
# include "../librpc/gen_ndr/ndr_netlogon.h"
2011-03-24 16:15:54 +03:00
# include "auth.h"
2011-06-16 16:20:21 +04:00
# include "../lib/tsocket/tsocket.h"
2008-09-25 03:01:00 +04:00
/* abstraction for the send_over_network function */
2008-10-01 23:50:29 +04:00
enum sock_type { INTERNET_SOCKET = 0 , UNIX_DOMAIN_SOCKET } ;
# define LOCAL_PATHNAME " / var / tmp / stadsocket"
2008-09-25 03:01:00 +04:00
static int vfs_smb_traffic_analyzer_debug_level = DBGC_VFS ;
2008-10-01 23:50:29 +04:00
static enum sock_type smb_traffic_analyzer_connMode ( vfs_handle_struct * handle )
2008-09-25 03:01:00 +04:00
{
connection_struct * conn = handle - > conn ;
const char * Mode ;
Mode = lp_parm_const_string ( SNUM ( conn ) , " smb_traffic_analyzer " , " mode " , \
" internet_socket " ) ;
if ( strstr ( Mode , " unix_domain_socket " ) ) {
return UNIX_DOMAIN_SOCKET ;
} else {
return INTERNET_SOCKET ;
}
}
2008-10-14 01:08:49 +04:00
2008-10-01 02:13:19 +04:00
/* Connect to an internet socket */
2008-10-01 23:50:29 +04:00
static int smb_traffic_analyzer_connect_inet_socket ( vfs_handle_struct * handle ,
const char * name , uint16_t port )
2008-09-25 03:01:00 +04:00
{
2008-09-25 23:02:22 +04:00
/* Create a streaming Socket */
int sockfd = - 1 ;
struct addrinfo hints ;
struct addrinfo * ailist = NULL ;
struct addrinfo * res = NULL ;
int ret ;
2008-09-25 03:01:00 +04:00
2008-09-25 23:02:22 +04:00
ZERO_STRUCT ( hints ) ;
/* By default make sure it supports TCP. */
hints . ai_socktype = SOCK_STREAM ;
hints . ai_flags = AI_ADDRCONFIG ;
2008-10-01 23:50:29 +04:00
ret = getaddrinfo ( name ,
2008-09-25 23:02:22 +04:00
NULL ,
& hints ,
& ailist ) ;
if ( ret ) {
2008-10-01 02:13:19 +04:00
DEBUG ( 3 , ( " smb_traffic_analyzer_connect_inet_socket: "
2008-09-25 23:02:22 +04:00
" getaddrinfo failed for name %s [%s] \n " ,
2008-10-01 23:50:29 +04:00
name ,
2008-09-25 23:02:22 +04:00
gai_strerror ( ret ) ) ) ;
2008-10-01 02:13:19 +04:00
return - 1 ;
2008-09-25 23:02:22 +04:00
}
2008-09-25 03:01:00 +04:00
DEBUG ( 3 , ( " smb_traffic_analyzer: Internet socket mode. Hostname: %s, "
2008-10-01 23:50:29 +04:00
" Port: %i \n " , name , port ) ) ;
2008-09-25 03:01:00 +04:00
2008-09-25 23:02:22 +04:00
for ( res = ailist ; res ; res = res - > ai_next ) {
struct sockaddr_storage ss ;
2009-01-03 21:50:05 +03:00
NTSTATUS status ;
2008-09-25 23:02:22 +04:00
if ( ! res - > ai_addr | | res - > ai_addrlen = = 0 ) {
continue ;
}
ZERO_STRUCT ( ss ) ;
memcpy ( & ss , res - > ai_addr , res - > ai_addrlen ) ;
2009-01-03 21:50:05 +03:00
status = open_socket_out ( & ss , port , 10000 , & sockfd ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
2008-09-25 23:02:22 +04:00
break ;
}
}
if ( ailist ) {
freeaddrinfo ( ailist ) ;
}
if ( sockfd = = - 1 ) {
2008-10-01 02:13:19 +04:00
DEBUG ( 1 , ( " smb_traffic_analyzer: unable to create "
" socket, error is %s " ,
2008-09-25 23:02:22 +04:00
strerror ( errno ) ) ) ;
2008-10-01 02:13:19 +04:00
return - 1 ;
2008-09-25 03:01:00 +04:00
}
2008-09-25 23:02:22 +04:00
2008-10-01 02:13:19 +04:00
return sockfd ;
2008-09-25 03:01:00 +04:00
}
2008-10-01 02:13:19 +04:00
/* Connect to a unix domain socket */
2008-10-01 23:50:29 +04:00
static int smb_traffic_analyzer_connect_unix_socket ( vfs_handle_struct * handle ,
const char * name )
2008-09-25 03:01:00 +04:00
{
/* Create the socket to stad */
int len , sock ;
struct sockaddr_un remote ;
2008-09-25 23:02:22 +04:00
2008-10-01 02:13:19 +04:00
DEBUG ( 7 , ( " smb_traffic_analyzer_connect_unix_socket: "
2008-10-01 23:50:29 +04:00
" Unix domain socket mode. Using %s \n " ,
name ) ) ;
2008-09-25 23:02:22 +04:00
2008-09-25 03:01:00 +04:00
if ( ( sock = socket ( AF_UNIX , SOCK_STREAM , 0 ) ) = = - 1 ) {
2008-10-01 02:13:19 +04:00
DEBUG ( 1 , ( " smb_traffic_analyzer_connect_unix_socket: "
" Couldn't create socket, "
2008-09-25 03:01:00 +04:00
" make sure stad is running! \n " ) ) ;
2008-10-30 02:43:19 +03:00
return - 1 ;
2008-09-25 03:01:00 +04:00
}
remote . sun_family = AF_UNIX ;
2008-10-01 23:50:29 +04:00
strlcpy ( remote . sun_path , name ,
2008-09-25 23:02:22 +04:00
sizeof ( remote . sun_path ) ) ;
2008-09-25 03:01:00 +04:00
len = strlen ( remote . sun_path ) + sizeof ( remote . sun_family ) ;
if ( connect ( sock , ( struct sockaddr * ) & remote , len ) = = - 1 ) {
2008-10-01 02:13:19 +04:00
DEBUG ( 1 , ( " smb_traffic_analyzer_connect_unix_socket: "
" Could not connect to "
2008-09-25 03:01:00 +04:00
" socket, make sure \n stad is running! \n " ) ) ;
2008-09-25 23:02:22 +04:00
close ( sock ) ;
2008-10-01 02:13:19 +04:00
return - 1 ;
}
return sock ;
}
2010-01-24 00:45:28 +03:00
/* Private data allowing shared connection sockets. */
2008-10-01 23:50:29 +04:00
struct refcounted_sock {
struct refcounted_sock * next , * prev ;
char * name ;
uint16_t port ;
int sock ;
unsigned int ref_count ;
} ;
2009-09-22 22:01:35 +04:00
2010-02-05 00:03:53 +03:00
/**
* Encryption of a data block with AES
* TALLOC_CTX * ctx Talloc context to work on
* const char * akey 128 bit key for the encryption
* const char * str Data buffer to encrypt , \ 0 terminated
* int * len Will be set to the length of the
* resulting data block
* The caller has to take care for the memory
* allocated on the context .
*/
static char * smb_traffic_analyzer_encrypt ( TALLOC_CTX * ctx ,
const char * akey , const char * str , size_t * len )
{
int s1 , s2 , h , d ;
AES_KEY key ;
2010-03-22 17:05:33 +03:00
unsigned char filler [ 17 ] = " ................ " ;
2010-02-05 00:03:53 +03:00
char * output ;
2010-03-22 17:05:33 +03:00
unsigned char crypted [ 18 ] ;
2010-02-05 00:03:53 +03:00
if ( akey = = NULL ) return NULL ;
2011-05-06 03:19:49 +04:00
samba_AES_set_encrypt_key ( ( const unsigned char * ) akey , 128 , & key ) ;
2010-02-05 00:03:53 +03:00
s1 = strlen ( str ) / 16 ;
s2 = strlen ( str ) % 16 ;
for ( h = 0 ; h < s2 ; h + + ) * ( filler + h ) = * ( str + ( s1 * 16 ) + h ) ;
DEBUG ( 10 , ( " smb_traffic_analyzer_send_data_socket: created %s "
" as filling block. \n " , filler ) ) ;
output = talloc_array ( ctx , char , ( s1 * 16 ) + 17 ) ;
d = 0 ;
for ( h = 0 ; h < s1 ; h + + ) {
2011-05-06 03:19:49 +04:00
samba_AES_encrypt ( ( const unsigned char * ) str + ( 16 * h ) , crypted , & key ) ;
2010-02-05 00:03:53 +03:00
for ( d = 0 ; d < 16 ; d + + ) output [ d + ( 16 * h ) ] = crypted [ d ] ;
}
2011-05-06 03:19:49 +04:00
samba_AES_encrypt ( ( const unsigned char * ) str + ( 16 * h ) , filler , & key ) ;
2010-02-05 00:03:53 +03:00
for ( d = 0 ; d < 16 ; d + + ) output [ d + ( 16 * h ) ] = * ( filler + d ) ;
* len = ( s1 * 16 ) + 16 ;
return output ;
}
/**
* Create a v2 header .
* TALLLOC_CTX * ctx Talloc context to work on
* const char * state_flags State flag string
* int len length of the data block
*/
static char * smb_traffic_analyzer_create_header ( TALLOC_CTX * ctx ,
const char * state_flags , size_t data_len )
{
char * header = talloc_asprintf ( ctx , " V2.%s%017u " ,
2010-03-22 17:05:33 +03:00
state_flags , ( unsigned int ) data_len ) ;
2010-02-05 00:03:53 +03:00
DEBUG ( 10 , ( " smb_traffic_analyzer_send_data_socket: created Header: \n " ) ) ;
2010-03-17 01:02:29 +03:00
dump_data ( 10 , ( uint8_t * ) header , strlen ( header ) ) ;
2010-02-05 00:03:53 +03:00
return header ;
}
/**
* Actually send header and data over the network
* char * header Header data
* char * data Data Block
* int dlength Length of data block
* int socket
*/
static void smb_traffic_analyzer_write_data ( char * header , char * data ,
2010-03-17 01:02:29 +03:00
int dlength , int _socket )
2010-02-05 00:03:53 +03:00
{
int len = strlen ( header ) ;
2010-03-17 01:02:29 +03:00
if ( write_data ( _socket , header , len ) ! = len ) {
2010-02-05 00:03:53 +03:00
DEBUG ( 1 , ( " smb_traffic_analyzer_send_data_socket: "
" error sending the header "
" over the socket! \n " ) ) ;
}
DEBUG ( 10 , ( " smb_traffic_analyzer_write_data: sending data: \n " ) ) ;
2010-03-17 01:02:29 +03:00
dump_data ( 10 , ( uint8_t * ) data , dlength ) ;
2010-02-05 00:03:53 +03:00
2010-03-17 01:02:29 +03:00
if ( write_data ( _socket , data , dlength ) ! = dlength ) {
2010-02-05 00:03:53 +03:00
DEBUG ( 1 , ( " smb_traffic_analyzer_write_data: "
" error sending crypted data to socket! \n " ) ) ;
}
}
2010-02-06 13:36:14 +03:00
/*
* Anonymize a string if required .
* TALLOC_CTX * ctx The talloc context to work on
* const char * str The string to anonymize
* vfs_handle_struct * handle The handle struct to work on
*
* Returns a newly allocated string , either the anonymized one ,
* or a copy of const char * str . The caller has to take care for
* freeing the allocated memory .
*/
static char * smb_traffic_analyzer_anonymize ( TALLOC_CTX * ctx ,
const char * str ,
vfs_handle_struct * handle )
{
const char * total_anonymization ;
const char * anon_prefix ;
char * output ;
total_anonymization = lp_parm_const_string ( SNUM ( handle - > conn ) ,
" smb_traffic_analyzer " ,
" total_anonymization " , NULL ) ;
anon_prefix = lp_parm_const_string ( SNUM ( handle - > conn ) ,
" smb_traffic_analyzer " ,
" anonymize_prefix " , NULL ) ;
if ( anon_prefix ! = NULL ) {
if ( total_anonymization ! = NULL ) {
output = talloc_asprintf ( ctx , " %s " ,
anon_prefix ) ;
} else {
output = talloc_asprintf ( ctx , " %s%i " , anon_prefix ,
str_checksum ( str ) ) ;
}
} else {
output = talloc_asprintf ( ctx , " %s " , str ) ;
}
return output ;
}
2010-02-07 22:39:58 +03:00
/**
* The marshalling function for protocol v2 .
* TALLOC_CTX * ctx Talloc context to work on
* struct tm * tm tm struct for the timestamp
* int seconds milliseconds of the timestamp
* vfs_handle_struct * handle vfs_handle_struct
* char * username Name of the user
* int vfs_operation VFS operation identifier
* int count Number of the common data blocks
* [ . . . ] variable args data blocks taken from the individual
* VFS data structures
*
* Returns the complete data block to send . The caller has to
* take care for freeing the allocated buffer .
*/
2010-02-05 00:03:53 +03:00
static char * smb_traffic_analyzer_create_string ( TALLOC_CTX * ctx ,
struct tm * tm , int seconds , vfs_handle_struct * handle , \
2010-01-22 15:04:21 +03:00
char * username , int vfs_operation , int count , . . . )
2009-09-22 22:01:35 +04:00
{
va_list ap ;
char * arg = NULL ;
int len ;
2010-02-07 22:39:58 +03:00
char * common_data_count_str = NULL ;
2009-09-22 22:01:35 +04:00
char * timestr = NULL ;
2010-01-29 16:57:20 +03:00
char * sidstr = NULL ;
char * usersid = NULL ;
2011-06-16 16:20:21 +04:00
char * raddr = NULL ;
2010-02-07 22:39:58 +03:00
char * buf = NULL ;
char * vfs_operation_str = NULL ;
2010-05-30 20:52:17 +04:00
const char * service_name = lp_const_servicename ( handle - > conn - > params - > service ) ;
2010-02-02 21:36:23 +03:00
/*
* first create the data that is transfered with any VFS op
* These are , in the following order :
2010-02-02 22:04:40 +03:00
* ( 0 ) number of data to come [ 6 in v2 .0 ]
2010-02-02 21:36:23 +03:00
* 1. vfs_operation identifier
* 2. username
* 3. user - SID
2010-02-02 22:04:40 +03:00
* 4. affected share
2010-02-02 21:36:23 +03:00
* 5. domain
* 6. timestamp
2011-02-13 20:20:00 +03:00
* 7. IP Addresss of client
2010-02-02 21:36:23 +03:00
*/
2009-09-22 22:01:35 +04:00
2010-02-07 22:39:58 +03:00
/*
* number of common data blocks to come ,
* this is a # define in vfs_smb_traffic_anaylzer . h ,
* it ' s length is known at compile time
*/
common_data_count_str = talloc_strdup ( ctx , SMBTA_COMMON_DATA_COUNT ) ;
2010-02-02 22:04:40 +03:00
/* vfs operation identifier */
2010-02-07 22:39:58 +03:00
vfs_operation_str = talloc_asprintf ( common_data_count_str , " %i " ,
vfs_operation ) ;
2010-01-29 16:57:20 +03:00
/*
* Handle anonymization . In protocol v2 , we have to anonymize
2010-02-06 13:36:14 +03:00
* both the SID and the username . The name is already
* anonymized if needed , by the calling function .
2010-01-29 16:57:20 +03:00
*/
2010-02-07 22:39:58 +03:00
usersid = dom_sid_string ( common_data_count_str ,
2011-02-21 12:25:52 +03:00
& handle - > conn - > session_info - > security_token - > sids [ 0 ] ) ;
2010-02-07 22:39:58 +03:00
sidstr = smb_traffic_analyzer_anonymize (
common_data_count_str ,
usersid ,
handle ) ;
2011-06-16 16:20:21 +04:00
raddr = tsocket_address_inet_addr_string ( handle - > conn - > sconn - > remote_address ,
ctx ) ;
if ( raddr = = NULL ) {
return NULL ;
}
2010-02-02 22:04:40 +03:00
/* time stamp */
2010-02-07 22:39:58 +03:00
timestr = talloc_asprintf ( common_data_count_str , \
2009-09-22 22:01:35 +04:00
" %04d-%02d-%02d %02d:%02d:%02d.%03d " , \
tm - > tm_year + 1900 , \
tm - > tm_mon + 1 , \
tm - > tm_mday , \
tm - > tm_hour , \
tm - > tm_min , \
tm - > tm_sec , \
( int ) seconds ) ;
len = strlen ( timestr ) ;
2010-02-07 22:39:58 +03:00
/* create the string of common data */
buf = talloc_asprintf ( ctx ,
2011-02-13 20:20:00 +03:00
" %s%04u%s%04u%s%04u%s%04u%s%04u%s%04u%s%04u%s " ,
2010-02-07 22:39:58 +03:00
common_data_count_str ,
2010-03-22 17:05:33 +03:00
( unsigned int ) strlen ( vfs_operation_str ) ,
2010-02-07 22:39:58 +03:00
vfs_operation_str ,
2010-03-22 17:05:33 +03:00
( unsigned int ) strlen ( username ) ,
2010-02-07 22:39:58 +03:00
username ,
2010-03-22 17:05:33 +03:00
( unsigned int ) strlen ( sidstr ) ,
2010-02-07 22:39:58 +03:00
sidstr ,
2010-05-30 20:52:17 +04:00
( unsigned int ) strlen ( service_name ) ,
service_name ,
2010-03-22 17:05:33 +03:00
( unsigned int )
2011-07-18 06:58:25 +04:00
strlen ( handle - > conn - > session_info - > info - > domain_name ) ,
handle - > conn - > session_info - > info - > domain_name ,
2010-03-22 17:05:33 +03:00
( unsigned int ) strlen ( timestr ) ,
2011-02-13 20:20:00 +03:00
timestr ,
2011-06-16 16:20:21 +04:00
( unsigned int ) strlen ( raddr ) ,
raddr ) ;
2010-02-07 22:39:58 +03:00
talloc_free ( common_data_count_str ) ;
2010-02-02 22:04:40 +03:00
/* data blocks depending on the VFS function */
2009-09-22 22:01:35 +04:00
va_start ( ap , count ) ;
while ( count - - ) {
arg = va_arg ( ap , char * ) ;
2010-01-24 00:45:28 +03:00
/*
* protocol v2 sends a four byte string
* as a header to each block , including
* the numbers of bytes to come in the
* next string .
*/
2009-09-22 22:01:35 +04:00
len = strlen ( arg ) ;
buf = talloc_asprintf_append ( buf , " %04u%s " , len , arg ) ;
}
va_end ( ap ) ;
Move the creation of the header.
Since the header block of the protocol contains the number of bytes to
come, we always send the header itself unmodified.
If we compress or crypt the data we are about to send, the length of the
data to send may change. Therefore, we no longer create the header in
smb_traffic_analyzer_create_string, but shortly before we send the data.
For both cases, encryption and normal, we create our own header, and
send it before the actual data.
In case of protocol v1, we don't need to create an extra header.
Just send the data, and return from the function.
Change a debug message to say that the header for crypted data has
been created.
Add a status flags consisting of 6 bytes to the header. Their function
will be descriped in one of the next patches, which is descriping
the header in a longer comment.
When anonymization and/or encryption is used, set the flags accordingly.
2010-01-22 23:17:53 +03:00
return buf ;
2009-09-22 22:01:35 +04:00
}
2008-10-01 02:13:19 +04:00
static void smb_traffic_analyzer_send_data ( vfs_handle_struct * handle ,
2009-09-21 17:33:21 +04:00
void * data ,
2009-09-17 22:11:39 +04:00
enum vfs_id vfs_operation )
2008-10-01 02:13:19 +04:00
{
2008-10-01 23:50:29 +04:00
struct refcounted_sock * rf_sock = NULL ;
2008-10-01 03:19:37 +04:00
struct timeval tv ;
2008-10-07 04:09:48 +04:00
time_t tv_sec ;
2008-10-01 03:19:37 +04:00
struct tm * tm = NULL ;
int seconds ;
char * str = NULL ;
2008-10-14 01:08:49 +04:00
char * username = NULL ;
Move the creation of the header.
Since the header block of the protocol contains the number of bytes to
come, we always send the header itself unmodified.
If we compress or crypt the data we are about to send, the length of the
data to send may change. Therefore, we no longer create the header in
smb_traffic_analyzer_create_string, but shortly before we send the data.
For both cases, encryption and normal, we create our own header, and
send it before the actual data.
In case of protocol v1, we don't need to create an extra header.
Just send the data, and return from the function.
Change a debug message to say that the header for crypted data has
been created.
Add a status flags consisting of 6 bytes to the header. Their function
will be descriped in one of the next patches, which is descriping
the header in a longer comment.
When anonymization and/or encryption is used, set the flags accordingly.
2010-01-22 23:17:53 +03:00
char * header = NULL ;
2009-09-17 22:11:39 +04:00
const char * protocol_version = NULL ;
bool Write = false ;
2008-10-01 03:19:37 +04:00
size_t len ;
2010-03-17 01:02:29 +03:00
size_t size ;
char * akey , * output ;
2010-02-02 22:04:40 +03:00
/*
* The state flags are part of the header
* and are descripted in the protocol description
* in vfs_smb_traffic_analyzer . h . They begin at byte
* 03 of the header .
*/
Move the creation of the header.
Since the header block of the protocol contains the number of bytes to
come, we always send the header itself unmodified.
If we compress or crypt the data we are about to send, the length of the
data to send may change. Therefore, we no longer create the header in
smb_traffic_analyzer_create_string, but shortly before we send the data.
For both cases, encryption and normal, we create our own header, and
send it before the actual data.
In case of protocol v1, we don't need to create an extra header.
Just send the data, and return from the function.
Change a debug message to say that the header for crypted data has
been created.
Add a status flags consisting of 6 bytes to the header. Their function
will be descriped in one of the next patches, which is descriping
the header in a longer comment.
When anonymization and/or encryption is used, set the flags accordingly.
2010-01-22 23:17:53 +03:00
char state_flags [ 9 ] = " 000000 \0 " ;
2008-10-01 02:13:19 +04:00
2011-02-20 13:32:39 +03:00
/**
* The first byte of the state flag string represents
* the modules protocol subversion number , defined
* in smb_traffic_analyzer . h . smbtatools / smbtad are designed
* to handle not yet implemented protocol enhancements
* by ignoring them . By recognizing the SMBTA_SUBRELEASE
* smbtatools can tell the user to update the client
* software .
*/
state_flags [ 0 ] = SMBTA_SUBRELEASE ;
2008-10-01 23:50:29 +04:00
SMB_VFS_HANDLE_GET_DATA ( handle , rf_sock , struct refcounted_sock , return ) ;
2008-10-01 02:13:19 +04:00
2008-10-01 23:50:29 +04:00
if ( rf_sock = = NULL | | rf_sock - > sock = = - 1 ) {
2008-10-01 02:13:19 +04:00
DEBUG ( 1 , ( " smb_traffic_analyzer_send_data: socket is "
" closed \n " ) ) ;
2008-09-25 23:02:22 +04:00
return ;
2008-09-25 03:01:00 +04:00
}
2008-10-01 02:13:19 +04:00
2008-10-01 03:19:37 +04:00
GetTimeOfDay ( & tv ) ;
2010-08-30 21:49:35 +04:00
tv_sec = tv . tv_sec ;
2008-10-07 04:09:48 +04:00
tm = localtime ( & tv_sec ) ;
2008-10-01 03:19:37 +04:00
if ( ! tm ) {
return ;
}
seconds = ( float ) ( tv . tv_usec / 1000 ) ;
2010-01-29 16:57:20 +03:00
/*
2010-02-06 13:36:14 +03:00
* Check if anonymization is required , and if yes do this only for
* the username here , needed vor protocol version 1. In v2 we
* additionally anonymize the SID , which is done in it ' s marshalling
* function .
2010-01-29 16:57:20 +03:00
*/
2010-02-06 13:36:14 +03:00
username = smb_traffic_analyzer_anonymize ( talloc_tos ( ) ,
2011-07-15 09:55:31 +04:00
handle - > conn - > session_info - > unix_info - > sanitized_username ,
2010-02-06 13:36:14 +03:00
handle ) ;
2009-02-04 17:31:24 +03:00
2010-02-06 13:36:14 +03:00
if ( ! username ) {
return ;
}
2010-01-29 16:57:20 +03:00
protocol_version = lp_parm_const_string ( SNUM ( handle - > conn ) ,
" smb_traffic_analyzer " ,
" protocol_version " , NULL ) ;
2009-09-17 22:11:39 +04:00
2011-05-18 17:24:23 +04:00
if ( protocol_version ! = NULL & & strcmp ( protocol_version , " V1 " ) = = 0 ) {
2009-09-17 22:11:39 +04:00
2009-09-21 17:33:21 +04:00
struct rw_data * s_data = ( struct rw_data * ) data ;
2010-01-24 00:45:28 +03:00
/*
* in case of protocol v1 , ignore any vfs operations
* except read , pread , write , pwrite , and set the " Write "
* bool accordingly , send data and return .
*/
2009-09-17 22:11:39 +04:00
if ( vfs_operation > vfs_id_pwrite ) return ;
if ( vfs_operation < = vfs_id_pread ) Write = false ;
else Write = true ;
str = talloc_asprintf ( talloc_tos ( ) ,
2008-10-01 23:50:29 +04:00
" V1,%u, \" %s \" , \" %s \" , \" %c \" , \" %s \" , \" %s \" , "
" \" %04d-%02d-%02d %02d:%02d:%02d.%03d \" \n " ,
2009-09-21 17:33:21 +04:00
( unsigned int ) s_data - > len ,
2008-10-14 01:08:49 +04:00
username ,
2011-07-18 06:58:25 +04:00
handle - > conn - > session_info - > info - > domain_name ,
2008-10-01 03:19:37 +04:00
Write ? ' W ' : ' R ' ,
handle - > conn - > connectpath ,
2009-09-21 17:33:21 +04:00
s_data - > filename ,
2008-10-01 03:19:37 +04:00
tm - > tm_year + 1900 ,
tm - > tm_mon + 1 ,
tm - > tm_mday ,
tm - > tm_hour ,
tm - > tm_min ,
tm - > tm_sec ,
( int ) seconds ) ;
2010-05-24 01:18:58 +04:00
len = strlen ( str ) ;
Move the creation of the header.
Since the header block of the protocol contains the number of bytes to
come, we always send the header itself unmodified.
If we compress or crypt the data we are about to send, the length of the
data to send may change. Therefore, we no longer create the header in
smb_traffic_analyzer_create_string, but shortly before we send the data.
For both cases, encryption and normal, we create our own header, and
send it before the actual data.
In case of protocol v1, we don't need to create an extra header.
Just send the data, and return from the function.
Change a debug message to say that the header for crypted data has
been created.
Add a status flags consisting of 6 bytes to the header. Their function
will be descriped in one of the next patches, which is descriping
the header in a longer comment.
When anonymization and/or encryption is used, set the flags accordingly.
2010-01-22 23:17:53 +03:00
if ( write_data ( rf_sock - > sock , str , len ) ! = len ) {
DEBUG ( 1 , ( " smb_traffic_analyzer_send_data_socket: "
" error sending V1 protocol data to socket! \n " ) ) ;
return ;
}
2011-05-18 17:24:23 +04:00
} else {
/**
* Protocol 2 is used by default .
*/
2009-09-22 22:01:35 +04:00
switch ( vfs_operation ) {
2010-02-15 19:47:30 +03:00
case vfs_id_open : ;
str = smb_traffic_analyzer_create_string ( talloc_tos ( ) ,
tm , seconds , handle , username , vfs_id_open ,
3 , ( ( struct open_data * ) data ) - > filename ,
talloc_asprintf ( talloc_tos ( ) , " %u " ,
( ( struct open_data * ) data ) - > mode ) ,
talloc_asprintf ( talloc_tos ( ) , " %u " ,
( ( struct open_data * ) data ) - > result ) ) ;
break ;
case vfs_id_close : ;
str = smb_traffic_analyzer_create_string ( talloc_tos ( ) ,
tm , seconds , handle , username , vfs_id_close ,
2 , ( ( struct close_data * ) data ) - > filename ,
talloc_asprintf ( talloc_tos ( ) , " %u " ,
( ( struct close_data * ) data ) - > result ) ) ;
break ;
2010-01-22 01:26:54 +03:00
case vfs_id_mkdir : ;
2010-02-05 00:03:53 +03:00
str = smb_traffic_analyzer_create_string ( talloc_tos ( ) ,
tm , seconds , handle , username , vfs_id_mkdir , \
3 , ( ( struct mkdir_data * ) data ) - > path , \
2010-01-22 01:26:54 +03:00
talloc_asprintf ( talloc_tos ( ) , " %u " , \
( ( struct mkdir_data * ) data ) - > mode ) , \
talloc_asprintf ( talloc_tos ( ) , " %u " , \
( ( struct mkdir_data * ) data ) - > result ) ) ;
break ;
case vfs_id_rmdir : ;
2010-02-05 00:03:53 +03:00
str = smb_traffic_analyzer_create_string ( talloc_tos ( ) ,
tm , seconds , handle , username , vfs_id_rmdir ,
2 , ( ( struct rmdir_data * ) data ) - > path , \
2010-01-22 01:26:54 +03:00
talloc_asprintf ( talloc_tos ( ) , " %u " , \
( ( struct rmdir_data * ) data ) - > result ) ) ;
break ;
case vfs_id_rename : ;
2010-02-05 00:03:53 +03:00
str = smb_traffic_analyzer_create_string ( talloc_tos ( ) ,
tm , seconds , handle , username , vfs_id_rename ,
3 , ( ( struct rename_data * ) data ) - > src , \
2010-01-22 01:26:54 +03:00
( ( struct rename_data * ) data ) - > dst ,
talloc_asprintf ( talloc_tos ( ) , " %u " , \
( ( struct rename_data * ) data ) - > result ) ) ;
break ;
case vfs_id_chdir : ;
2010-02-05 00:03:53 +03:00
str = smb_traffic_analyzer_create_string ( talloc_tos ( ) ,
tm , seconds , handle , username , vfs_id_chdir ,
2 , ( ( struct chdir_data * ) data ) - > path , \
2010-01-22 01:26:54 +03:00
talloc_asprintf ( talloc_tos ( ) , " %u " , \
( ( struct chdir_data * ) data ) - > result ) ) ;
break ;
case vfs_id_write :
case vfs_id_pwrite :
case vfs_id_read :
case vfs_id_pread : ;
2010-02-05 00:03:53 +03:00
str = smb_traffic_analyzer_create_string ( talloc_tos ( ) ,
tm , seconds , handle , username , vfs_operation ,
2 , ( ( struct rw_data * ) data ) - > filename , \
2010-01-22 01:26:54 +03:00
talloc_asprintf ( talloc_tos ( ) , " %u " , \
2010-03-22 17:05:33 +03:00
( unsigned int )
( ( struct rw_data * ) data ) - > len ) ) ;
2010-01-22 01:26:54 +03:00
break ;
default :
DEBUG ( 1 , ( " smb_traffic_analyzer: error! "
" wrong VFS operation id detected! \n " ) ) ;
return ;
2009-09-22 22:01:35 +04:00
}
2009-09-17 22:11:39 +04:00
}
2008-10-01 03:19:37 +04:00
if ( ! str ) {
2009-09-17 22:11:39 +04:00
DEBUG ( 1 , ( " smb_traffic_analyzer_send_data: "
" unable to create string to send! \n " ) ) ;
2008-10-01 03:19:37 +04:00
return ;
}
2010-01-24 00:45:28 +03:00
/*
* If configured , optain the key and run AES encryption
* over the data .
*/
2010-01-29 23:34:27 +03:00
become_root ( ) ;
2010-03-17 01:02:29 +03:00
akey = ( char * ) secrets_fetch ( " smb_traffic_analyzer_key " , & size ) ;
2010-01-29 23:34:27 +03:00
unbecome_root ( ) ;
2009-12-14 22:43:15 +03:00
if ( akey ! = NULL ) {
Move the creation of the header.
Since the header block of the protocol contains the number of bytes to
come, we always send the header itself unmodified.
If we compress or crypt the data we are about to send, the length of the
data to send may change. Therefore, we no longer create the header in
smb_traffic_analyzer_create_string, but shortly before we send the data.
For both cases, encryption and normal, we create our own header, and
send it before the actual data.
In case of protocol v1, we don't need to create an extra header.
Just send the data, and return from the function.
Change a debug message to say that the header for crypted data has
been created.
Add a status flags consisting of 6 bytes to the header. Their function
will be descriped in one of the next patches, which is descriping
the header in a longer comment.
When anonymization and/or encryption is used, set the flags accordingly.
2010-01-22 23:17:53 +03:00
state_flags [ 2 ] = ' E ' ;
2010-01-29 23:34:27 +03:00
DEBUG ( 10 , ( " smb_traffic_analyzer_send_data_socket: a key was "
" found, encrypting data! \n " ) ) ;
2010-03-17 01:02:29 +03:00
output = smb_traffic_analyzer_encrypt ( talloc_tos ( ) ,
2010-02-05 00:03:53 +03:00
akey , str , & len ) ;
2011-03-27 22:38:52 +04:00
SAFE_FREE ( akey ) ;
2010-02-05 00:03:53 +03:00
header = smb_traffic_analyzer_create_header ( talloc_tos ( ) ,
Move the creation of the header.
Since the header block of the protocol contains the number of bytes to
come, we always send the header itself unmodified.
If we compress or crypt the data we are about to send, the length of the
data to send may change. Therefore, we no longer create the header in
smb_traffic_analyzer_create_string, but shortly before we send the data.
For both cases, encryption and normal, we create our own header, and
send it before the actual data.
In case of protocol v1, we don't need to create an extra header.
Just send the data, and return from the function.
Change a debug message to say that the header for crypted data has
been created.
Add a status flags consisting of 6 bytes to the header. Their function
will be descriped in one of the next patches, which is descriping
the header in a longer comment.
When anonymization and/or encryption is used, set the flags accordingly.
2010-01-22 23:17:53 +03:00
state_flags , len ) ;
DEBUG ( 10 , ( " smb_traffic_analyzer_send_data_socket: "
2010-01-29 23:34:27 +03:00
" header created for crypted data: %s \n " , header ) ) ;
2010-02-05 00:03:53 +03:00
smb_traffic_analyzer_write_data ( header , output , len ,
rf_sock - > sock ) ;
return ;
2009-12-14 22:43:15 +03:00
}
Move the creation of the header.
Since the header block of the protocol contains the number of bytes to
come, we always send the header itself unmodified.
If we compress or crypt the data we are about to send, the length of the
data to send may change. Therefore, we no longer create the header in
smb_traffic_analyzer_create_string, but shortly before we send the data.
For both cases, encryption and normal, we create our own header, and
send it before the actual data.
In case of protocol v1, we don't need to create an extra header.
Just send the data, and return from the function.
Change a debug message to say that the header for crypted data has
been created.
Add a status flags consisting of 6 bytes to the header. Their function
will be descriped in one of the next patches, which is descriping
the header in a longer comment.
When anonymization and/or encryption is used, set the flags accordingly.
2010-01-22 23:17:53 +03:00
len = strlen ( str ) ;
2010-02-05 00:03:53 +03:00
header = smb_traffic_analyzer_create_header ( talloc_tos ( ) ,
state_flags , len ) ;
smb_traffic_analyzer_write_data ( header , str , strlen ( str ) ,
rf_sock - > sock ) ;
2008-10-01 02:13:19 +04:00
}
2008-09-25 03:01:00 +04:00
2008-10-01 23:50:29 +04:00
static struct refcounted_sock * sock_list ;
2008-10-01 02:13:19 +04:00
static void smb_traffic_analyzer_free_data ( void * * pptr )
{
2008-10-01 23:50:29 +04:00
struct refcounted_sock * rf_sock = * ( struct refcounted_sock * * ) pptr ;
if ( rf_sock = = NULL ) {
2008-10-01 02:13:19 +04:00
return ;
}
2008-10-01 23:50:29 +04:00
rf_sock - > ref_count - - ;
if ( rf_sock - > ref_count ! = 0 ) {
return ;
}
if ( rf_sock - > sock ! = - 1 ) {
close ( rf_sock - > sock ) ;
2008-10-01 02:13:19 +04:00
}
2008-10-01 23:50:29 +04:00
DLIST_REMOVE ( sock_list , rf_sock ) ;
TALLOC_FREE ( rf_sock ) ;
2008-09-25 03:01:00 +04:00
}
2008-10-01 02:13:19 +04:00
static int smb_traffic_analyzer_connect ( struct vfs_handle_struct * handle ,
const char * service ,
const char * user )
2008-09-25 03:01:00 +04:00
{
2008-10-01 23:50:29 +04:00
connection_struct * conn = handle - > conn ;
enum sock_type st = smb_traffic_analyzer_connMode ( handle ) ;
struct refcounted_sock * rf_sock = NULL ;
const char * name = ( st = = UNIX_DOMAIN_SOCKET ) ? LOCAL_PATHNAME :
lp_parm_const_string ( SNUM ( conn ) ,
" smb_traffic_analyzer " ,
" host " , " localhost " ) ;
uint16_t port = ( st = = UNIX_DOMAIN_SOCKET ) ? 0 :
atoi ( lp_parm_const_string ( SNUM ( conn ) ,
" smb_traffic_analyzer " , " port " , " 9430 " ) ) ;
2009-12-01 02:53:04 +03:00
int ret = SMB_VFS_NEXT_CONNECT ( handle , service , user ) ;
if ( ret < 0 ) {
return ret ;
}
2008-09-25 03:01:00 +04:00
2008-10-01 23:50:29 +04:00
/* Are we already connected ? */
for ( rf_sock = sock_list ; rf_sock ; rf_sock = rf_sock - > next ) {
if ( port = = rf_sock - > port & &
( strcmp ( name , rf_sock - > name ) = = 0 ) ) {
break ;
}
2008-10-01 02:13:19 +04:00
}
2008-09-25 03:01:00 +04:00
2008-10-01 23:50:29 +04:00
/* If we're connected already, just increase the
* reference count . */
if ( rf_sock ) {
rf_sock - > ref_count + + ;
2008-10-01 02:13:19 +04:00
} else {
2008-10-01 23:50:29 +04:00
/* New connection. */
2011-06-07 05:44:43 +04:00
rf_sock = talloc_zero ( NULL , struct refcounted_sock ) ;
2008-10-01 23:50:29 +04:00
if ( rf_sock = = NULL ) {
2009-12-01 02:53:04 +03:00
SMB_VFS_NEXT_DISCONNECT ( handle ) ;
2008-10-01 23:50:29 +04:00
errno = ENOMEM ;
return - 1 ;
}
rf_sock - > name = talloc_strdup ( rf_sock , name ) ;
if ( rf_sock - > name = = NULL ) {
2009-12-01 02:53:04 +03:00
SMB_VFS_NEXT_DISCONNECT ( handle ) ;
2008-10-01 23:50:29 +04:00
TALLOC_FREE ( rf_sock ) ;
errno = ENOMEM ;
return - 1 ;
}
rf_sock - > port = port ;
rf_sock - > ref_count = 1 ;
if ( st = = UNIX_DOMAIN_SOCKET ) {
rf_sock - > sock = smb_traffic_analyzer_connect_unix_socket ( handle ,
name ) ;
} else {
rf_sock - > sock = smb_traffic_analyzer_connect_inet_socket ( handle ,
name ,
port ) ;
}
if ( rf_sock - > sock = = - 1 ) {
2009-12-01 02:53:04 +03:00
SMB_VFS_NEXT_DISCONNECT ( handle ) ;
2008-10-01 23:50:29 +04:00
TALLOC_FREE ( rf_sock ) ;
return - 1 ;
}
DLIST_ADD ( sock_list , rf_sock ) ;
2008-10-01 02:13:19 +04:00
}
2008-09-25 03:01:00 +04:00
2008-10-01 02:13:19 +04:00
/* Store the private data. */
2008-10-01 23:50:29 +04:00
SMB_VFS_HANDLE_SET_DATA ( handle , rf_sock , smb_traffic_analyzer_free_data ,
struct refcounted_sock , return - 1 ) ;
2009-12-01 02:53:04 +03:00
return 0 ;
2008-10-01 02:13:19 +04:00
}
2008-09-25 03:01:00 +04:00
2009-09-17 22:11:39 +04:00
/* VFS Functions */
2009-12-11 23:04:46 +03:00
static int smb_traffic_analyzer_chdir ( vfs_handle_struct * handle , \
const char * path )
{
struct chdir_data s_data ;
s_data . result = SMB_VFS_NEXT_CHDIR ( handle , path ) ;
s_data . path = path ;
DEBUG ( 10 , ( " smb_traffic_analyzer_chdir: CHDIR: %s \n " , path ) ) ;
smb_traffic_analyzer_send_data ( handle , & s_data , vfs_id_chdir ) ;
return s_data . result ;
}
static int smb_traffic_analyzer_rename ( vfs_handle_struct * handle , \
const struct smb_filename * smb_fname_src ,
const struct smb_filename * smb_fname_dst )
{
struct rename_data s_data ;
s_data . result = SMB_VFS_NEXT_RENAME ( handle , smb_fname_src , \
smb_fname_dst ) ;
s_data . src = smb_fname_src - > base_name ;
s_data . dst = smb_fname_dst - > base_name ;
DEBUG ( 10 , ( " smb_traffic_analyzer_rename: RENAME: %s / %s \n " ,
smb_fname_src - > base_name ,
smb_fname_dst - > base_name ) ) ;
smb_traffic_analyzer_send_data ( handle , & s_data , vfs_id_rename ) ;
return s_data . result ;
}
static int smb_traffic_analyzer_rmdir ( vfs_handle_struct * handle , \
const char * path )
{
struct rmdir_data s_data ;
s_data . result = SMB_VFS_NEXT_RMDIR ( handle , path ) ;
s_data . path = path ;
DEBUG ( 10 , ( " smb_traffic_analyzer_rmdir: RMDIR: %s \n " , path ) ) ;
smb_traffic_analyzer_send_data ( handle , & s_data , vfs_id_rmdir ) ;
return s_data . result ;
}
2009-09-17 22:11:39 +04:00
static int smb_traffic_analyzer_mkdir ( vfs_handle_struct * handle , \
const char * path , mode_t mode )
{
2009-09-21 17:33:21 +04:00
struct mkdir_data s_data ;
s_data . result = SMB_VFS_NEXT_MKDIR ( handle , path , mode ) ;
s_data . path = path ;
s_data . mode = mode ;
2009-09-17 22:11:39 +04:00
DEBUG ( 10 , ( " smb_traffic_analyzer_mkdir: MKDIR: %s \n " , path ) ) ;
smb_traffic_analyzer_send_data ( handle ,
2009-09-21 17:33:21 +04:00
& s_data ,
2009-09-17 22:11:39 +04:00
vfs_id_mkdir ) ;
2009-09-21 17:33:21 +04:00
return s_data . result ;
2009-09-17 22:11:39 +04:00
}
2008-09-25 03:01:00 +04:00
2011-03-30 00:16:10 +04:00
static ssize_t smb_traffic_analyzer_sendfile ( vfs_handle_struct * handle ,
int tofd ,
files_struct * fromfsp ,
const DATA_BLOB * hdr ,
SMB_OFF_T offset ,
size_t n )
{
struct rw_data s_data ;
s_data . len = SMB_VFS_NEXT_SENDFILE ( handle ,
tofd , fromfsp , hdr , offset , n ) ;
s_data . filename = fromfsp - > fsp_name - > base_name ;
DEBUG ( 10 , ( " smb_traffic_analyzer_sendfile: sendfile(r): %s \n " ,
fsp_str_dbg ( fromfsp ) ) ) ;
smb_traffic_analyzer_send_data ( handle ,
& s_data ,
vfs_id_read ) ;
return s_data . len ;
}
static ssize_t smb_traffic_analyzer_recvfile ( vfs_handle_struct * handle ,
int fromfd ,
files_struct * tofsp ,
SMB_OFF_T offset ,
size_t n )
{
struct rw_data s_data ;
s_data . len = SMB_VFS_NEXT_RECVFILE ( handle ,
fromfd , tofsp , offset , n ) ;
s_data . filename = tofsp - > fsp_name - > base_name ;
DEBUG ( 10 , ( " smb_traffic_analyzer_recvfile: recvfile(w): %s \n " ,
fsp_str_dbg ( tofsp ) ) ) ;
smb_traffic_analyzer_send_data ( handle ,
& s_data ,
vfs_id_write ) ;
return s_data . len ;
}
2008-09-25 03:01:00 +04:00
static ssize_t smb_traffic_analyzer_read ( vfs_handle_struct * handle , \
files_struct * fsp , void * data , size_t n )
{
2009-09-21 17:33:21 +04:00
struct rw_data s_data ;
2008-09-25 03:01:00 +04:00
2009-09-21 17:33:21 +04:00
s_data . len = SMB_VFS_NEXT_READ ( handle , fsp , data , n ) ;
s_data . filename = fsp - > fsp_name - > base_name ;
2009-07-11 05:11:32 +04:00
DEBUG ( 10 , ( " smb_traffic_analyzer_read: READ: %s \n " , fsp_str_dbg ( fsp ) ) ) ;
2008-09-25 03:01:00 +04:00
2008-10-01 02:13:19 +04:00
smb_traffic_analyzer_send_data ( handle ,
2009-09-21 17:33:21 +04:00
& s_data ,
2009-09-17 22:11:39 +04:00
vfs_id_read ) ;
2009-09-21 17:33:21 +04:00
return s_data . len ;
2008-09-25 03:01:00 +04:00
}
static ssize_t smb_traffic_analyzer_pread ( vfs_handle_struct * handle , \
files_struct * fsp , void * data , size_t n , SMB_OFF_T offset )
{
2009-09-21 17:33:21 +04:00
struct rw_data s_data ;
2008-09-25 03:01:00 +04:00
2009-09-21 17:33:21 +04:00
s_data . len = SMB_VFS_NEXT_PREAD ( handle , fsp , data , n , offset ) ;
s_data . filename = fsp - > fsp_name - > base_name ;
2009-07-11 05:11:32 +04:00
DEBUG ( 10 , ( " smb_traffic_analyzer_pread: PREAD: %s \n " ,
fsp_str_dbg ( fsp ) ) ) ;
2008-09-25 03:01:00 +04:00
2008-10-01 02:13:19 +04:00
smb_traffic_analyzer_send_data ( handle ,
2009-09-21 17:33:21 +04:00
& s_data ,
2009-09-17 22:11:39 +04:00
vfs_id_pread ) ;
2008-09-25 03:01:00 +04:00
2009-09-21 17:33:21 +04:00
return s_data . len ;
2008-09-25 03:01:00 +04:00
}
static ssize_t smb_traffic_analyzer_write ( vfs_handle_struct * handle , \
files_struct * fsp , const void * data , size_t n )
{
2009-09-21 17:33:21 +04:00
struct rw_data s_data ;
2008-09-25 03:01:00 +04:00
2009-09-21 17:33:21 +04:00
s_data . len = SMB_VFS_NEXT_WRITE ( handle , fsp , data , n ) ;
s_data . filename = fsp - > fsp_name - > base_name ;
2009-07-11 05:11:32 +04:00
DEBUG ( 10 , ( " smb_traffic_analyzer_write: WRITE: %s \n " ,
fsp_str_dbg ( fsp ) ) ) ;
2008-09-25 03:01:00 +04:00
2008-10-01 02:13:19 +04:00
smb_traffic_analyzer_send_data ( handle ,
2009-09-21 17:33:21 +04:00
& s_data ,
2009-09-17 22:11:39 +04:00
vfs_id_write ) ;
2009-09-21 17:33:21 +04:00
return s_data . len ;
2008-09-25 03:01:00 +04:00
}
static ssize_t smb_traffic_analyzer_pwrite ( vfs_handle_struct * handle , \
files_struct * fsp , const void * data , size_t n , SMB_OFF_T offset )
{
2009-09-21 17:33:21 +04:00
struct rw_data s_data ;
2008-09-25 03:01:00 +04:00
2009-09-21 17:33:21 +04:00
s_data . len = SMB_VFS_NEXT_PWRITE ( handle , fsp , data , n , offset ) ;
s_data . filename = fsp - > fsp_name - > base_name ;
DEBUG ( 10 , ( " smb_traffic_analyzer_pwrite: PWRITE: %s \n " , \
fsp_str_dbg ( fsp ) ) ) ;
2008-09-25 03:01:00 +04:00
2008-10-01 02:13:19 +04:00
smb_traffic_analyzer_send_data ( handle ,
2009-09-21 17:33:21 +04:00
& s_data ,
2009-09-17 22:11:39 +04:00
vfs_id_pwrite ) ;
2009-09-21 17:33:21 +04:00
return s_data . len ;
2008-09-25 03:01:00 +04:00
}
2008-10-01 02:13:19 +04:00
2010-02-15 19:47:30 +03:00
static int smb_traffic_analyzer_open ( vfs_handle_struct * handle , \
struct smb_filename * smb_fname , files_struct * fsp , \
int flags , mode_t mode )
{
struct open_data s_data ;
s_data . result = SMB_VFS_NEXT_OPEN ( handle , smb_fname , fsp ,
flags , mode ) ;
DEBUG ( 10 , ( " smb_traffic_analyzer_open: OPEN: %s \n " ,
fsp_str_dbg ( fsp ) ) ) ;
s_data . filename = fsp - > fsp_name - > base_name ;
2010-03-22 17:05:33 +03:00
s_data . mode = mode ;
2010-02-15 19:47:30 +03:00
smb_traffic_analyzer_send_data ( handle ,
& s_data ,
vfs_id_open ) ;
return s_data . result ;
}
static int smb_traffic_analyzer_close ( vfs_handle_struct * handle , \
files_struct * fsp )
{
struct close_data s_data ;
s_data . result = SMB_VFS_NEXT_CLOSE ( handle , fsp ) ;
DEBUG ( 10 , ( " smb_traffic_analyzer_close: CLOSE: %s \n " ,
fsp_str_dbg ( fsp ) ) ) ;
s_data . filename = fsp - > fsp_name - > base_name ;
smb_traffic_analyzer_send_data ( handle ,
& s_data ,
vfs_id_close ) ;
return s_data . result ;
}
2009-07-24 04:28:58 +04:00
static struct vfs_fn_pointers vfs_smb_traffic_analyzer_fns = {
. connect_fn = smb_traffic_analyzer_connect ,
. vfs_read = smb_traffic_analyzer_read ,
. pread = smb_traffic_analyzer_pread ,
. write = smb_traffic_analyzer_write ,
. pwrite = smb_traffic_analyzer_pwrite ,
2009-12-11 23:04:46 +03:00
. mkdir = smb_traffic_analyzer_mkdir ,
. rename = smb_traffic_analyzer_rename ,
2010-02-15 19:47:30 +03:00
. chdir = smb_traffic_analyzer_chdir ,
2011-04-21 00:55:25 +04:00
. open_fn = smb_traffic_analyzer_open ,
2010-03-22 17:05:33 +03:00
. rmdir = smb_traffic_analyzer_rmdir ,
2011-03-30 00:16:10 +04:00
. close_fn = smb_traffic_analyzer_close ,
. sendfile = smb_traffic_analyzer_sendfile ,
. recvfile = smb_traffic_analyzer_recvfile
2008-10-01 02:13:19 +04:00
} ;
/* Module initialization */
NTSTATUS vfs_smb_traffic_analyzer_init ( void )
{
2009-07-24 04:28:58 +04:00
NTSTATUS ret = smb_register_vfs ( SMB_VFS_INTERFACE_VERSION ,
" smb_traffic_analyzer " ,
& vfs_smb_traffic_analyzer_fns ) ;
2008-10-01 02:13:19 +04:00
if ( ! NT_STATUS_IS_OK ( ret ) ) {
return ret ;
}
vfs_smb_traffic_analyzer_debug_level =
debug_add_class ( " smb_traffic_analyzer " ) ;
if ( vfs_smb_traffic_analyzer_debug_level = = - 1 ) {
vfs_smb_traffic_analyzer_debug_level = DBGC_VFS ;
DEBUG ( 1 , ( " smb_traffic_analyzer_init: Couldn't register custom "
" debugging class! \n " ) ) ;
} else {
DEBUG ( 3 , ( " smb_traffic_analyzer_init: Debug class number of "
" 'smb_traffic_analyzer': %d \n " , \
vfs_smb_traffic_analyzer_debug_level ) ) ;
}
return ret ;
}