s3-vfs: Use the system. namespace for fake ACLs
[kai/samba.git] / source3 / modules / vfs_smb_traffic_analyzer.c
index 63fda40256ff6c5a1c2e8a46bd5d201b57bf442d..c728e7d5e954618a12e614c9552ccd4bc475f1a8 100644 (file)
@@ -2,7 +2,7 @@
  * traffic-analyzer VFS module. Measure the smb traffic users create
  * on the net.
  *
- * Copyright (C) Holger Hetterich, 2008
+ * Copyright (C) Holger Hetterich, 2008-2010
  * Copyright (C) Jeremy Allison, 2008
  *
  * This program is free software; you can redistribute it and/or modify
  */
 
 #include "includes.h"
+#include "smbd/smbd.h"
+#include "../smbd/globals.h"
 #include "../lib/crypto/crypto.h"
+#include "vfs_smb_traffic_analyzer.h"
+#include "../libcli/security/security.h"
+#include "secrets.h"
+#include "../librpc/gen_ndr/ndr_netlogon.h"
+#include "auth.h"
+#include "../lib/tsocket/tsocket.h"
 
 /* abstraction for the send_over_network function */
 enum sock_type {INTERNET_SOCKET = 0, UNIX_DOMAIN_SOCKET};
 
 #define LOCAL_PATHNAME "/var/tmp/stadsocket"
 
-
-/**
- * Protocol version 2.0 description
- *
- * The following table shows the exact assembly of the 2.0 protocol.
- *
- * -->Header<--
- * The protocol header is always send first, and contains various
- * information about the data block to come.
- * The header is always of fixed length, and will be send unencrypted.
- *
- * Byte Number/Bytes   Description
- * 00-02               Contains always the string "V2."
- * 03                  This byte contains a possible subrelease number of the
- *                     protocol. This enables the receiver to make a version
- *                     check to ensure the compatibility and allows us to
- *                     release 2.x versions of the protocol with bugfixes or
- *                     enhancements.
- * 04                  Usually, this byte contains the character '0'. If the
- *                     VFS module is configured for anonymization, this is
- *                     set to 'A'. This information can be useful for the
- *                     receiver.
- * 05                  Usually, this byte contains the character '0'. If the
- *                     VFS module is configured for encryption of the data,
- *                     this byte is set to 'E'.
- * 06-09               These bytes contain the character '0' by default, and
- *                     are reserved for possible future extensions. They have
- *                     no function in 2.0.
- * 10-27               17 bytes containing a string representation of the
- *                     number of bytes to come in the following data block.
- *                     It is right aligned and filled from the left with '0'.
- * 
- * -->Data Block<--
- * The data block is send immediately after the header was send. It's length
- * is exactly what was given in bytes 11-28 from in the header.
- *
- * The data block may be send encrypted.
- * 
- * To make the data block easy for the receiver to read, it is divided into
- * several sub-blocks, each with it's own header of four byte length. In each
- * of the sub-headers, a string representation of the length of this block is
- * to be found.
- *
- * Thus the formal structure is very simple:
- *
- * [HEADER]data[HEADER]data[HEADER]data[END]
- *
- * whereas [END] is exactly at the position given in bytes 11-28 of the
- * header.
- *
- * Some data the VFS module is capturing is of use for any VFS operation.
- * Therefore, there is a "common set" of data, that will be send with any
- * data block. The following provides a list of this data.
- * - the VFS function identifier (see VFS function ifentifier table below).
- * - a timestamp to the millisecond.
- * - the username (as text) who runs the VFS operation.
- * - the SID of the user who run the VFS operation.
- * - the domain under which the VFS operation has happened.
- *
- */
-
-/** 
- * VFS Functions identifier table. In protocol version 2, every vfs
- * function is given a unique id.
- */
-enum vfs_id {
-       /*
-        * care for the order here, required for compatibility
-        * with protocol version 1.
-        */
-        vfs_id_read,
-        vfs_id_pread,
-        vfs_id_write,
-        vfs_id_pwrite,
-       /* end of protocol version 1 identifiers. */
-       vfs_id_mkdir,
-       vfs_id_rmdir,
-       vfs_id_rename,
-       vfs_id_chdir
-};
-
-/*
- * Specific data sets for the VFS functions.
- * A compatible receiver has to have the exact same dataset.
- */
-struct mkdir_data {
-       const char *path;
-       mode_t mode;
-       int result;
-};
-
-struct rmdir_data {
-       const char *path;
-       int result;
-};
-
-struct rename_data {
-       const char *src;
-       const char *dst;
-       int result;
-};
-
-struct chdir_data {
-       const char *path;
-       int result;
-};
-       
-/* rw_data used for read/write/pread/pwrite */
-struct rw_data {
-       char *filename;
-       size_t len;
-};
-
 static int vfs_smb_traffic_analyzer_debug_level = DBGC_VFS;
 
 static enum sock_type smb_traffic_analyzer_connMode(vfs_handle_struct *handle)
@@ -262,38 +156,200 @@ struct refcounted_sock {
 };
 
 
-/* The marshaller for the protocol version 2. */
-static char *smb_traffic_analyzer_create_string( struct tm *tm, \
-       int seconds, vfs_handle_struct *handle, \
+/**
+ * Encryption of a data block with AES
+ * TALLOC_CTX *ctx     Talloc context to work on
+ * const char *akey    128bit 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;
+       AES_KEY key;
+       unsigned char filler[17]= "................";
+       char *output;
+       if (akey == NULL) return NULL;
+       samba_AES_set_encrypt_key((const unsigned char *) akey, 128, &key);
+       s1 = strlen(str) / 16;
+       s2 = strlen(str) % 16;
+       memcpy(filler, str + (s1*16), s2);
+       DEBUG(10, ("smb_traffic_analyzer_send_data_socket: created %s"
+               " as filling block.\n", filler));
+
+       *len = ((s1 + 1)*16);
+       output = talloc_array(ctx, char, *len);
+       for (h = 0; h < s1; h++) {
+               samba_AES_encrypt((unsigned char *) str+(16*h), output+16*h,
+                       &key);
+       }
+       samba_AES_encrypt(filler, (const unsigned char *)(output+(16*h)), &key);
+       *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",
+                                       state_flags, (unsigned int) data_len);
+       DEBUG(10, ("smb_traffic_analyzer_send_data_socket: created Header:\n"));
+       dump_data(10, (uint8_t *)header, strlen(header));
+       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,
+                       int dlength, int _socket)
+{
+               int len = strlen(header);
+               if (write_data( _socket, header, len) != len) {
+                       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"));
+               dump_data( 10, (uint8_t *)data, dlength);
+
+                if (write_data( _socket, data, dlength) != dlength) {
+                        DEBUG(1, ("smb_traffic_analyzer_write_data: "
+                                "error sending crypted data to socket!\n"));
+                }
+}
+
+
+/*
+ * 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;
+}
+
+
+/**
+ * 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.
+ */
+static char *smb_traffic_analyzer_create_string( TALLOC_CTX *ctx,
+       struct tm *tm, int seconds, vfs_handle_struct *handle, \
        char *username, int vfs_operation, int count, ... )
 {
        
        va_list ap;
        char *arg = NULL;
        int len;
-       char *header = NULL;
-       char *buf = NULL;
+       char *common_data_count_str = NULL;
        char *timestr = NULL;
-       char *opstr = NULL;
-       char *userSID = NULL;
-
-       /* first create the data that is transfered with any VFS op */
-       opstr = talloc_asprintf(talloc_tos(), "%i", vfs_operation);
-       len = strlen(opstr);
-       buf = talloc_asprintf(talloc_tos(), "%04u%s", len, opstr);
-       len = strlen( username );
-       buf = talloc_asprintf_append(buf, "%04u%s", len, username);
-       userSID = dom_sid_string( talloc_tos(),
-               &handle->conn->server_info->ptok->user_sids[0]);
-       len = strlen( userSID );
-       buf = talloc_asprintf_append(buf, "%04u%s", len, userSID);
-       len = strlen( handle->conn->connectpath );
-       buf = talloc_asprintf_append( buf, "%04u%s", len, \
-               handle->conn->connectpath );
-       len = strlen( pdb_get_domain(handle->conn->server_info->sam_account) );
-       buf = talloc_asprintf_append( buf, "%04u%s", len, \
-               pdb_get_domain(handle->conn->server_info->sam_account) );
-       timestr = talloc_asprintf(talloc_tos(), \
+       char *sidstr = NULL;
+       char *usersid = NULL;
+       char *raddr = NULL;
+       char *buf = NULL;
+       char *vfs_operation_str = NULL;
+       const char *service_name = lp_const_servicename(handle->conn->params->service);
+
+       /*
+        * first create the data that is transfered with any VFS op
+        * These are, in the following order:
+        *(0) number of data to come [6 in v2.0]
+        * 1.vfs_operation identifier
+        * 2.username
+        * 3.user-SID
+        * 4.affected share
+        * 5.domain
+        * 6.timestamp
+        * 7.IP Addresss of client
+        */
+
+       /*
+        * 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);
+       /* vfs operation identifier */
+       vfs_operation_str = talloc_asprintf( common_data_count_str, "%i",
+                                                       vfs_operation);
+       /*
+        * Handle anonymization. In protocol v2, we have to anonymize
+        * both the SID and the username. The name is already
+        * anonymized if needed, by the calling function.
+        */
+       usersid = dom_sid_string( common_data_count_str,
+               &handle->conn->session_info->security_token->sids[0]);
+
+       sidstr = smb_traffic_analyzer_anonymize(
+               common_data_count_str,
+               usersid,
+               handle);
+
+       raddr = tsocket_address_inet_addr_string(handle->conn->sconn->remote_address,
+                                                ctx);
+       if (raddr == NULL) {
+               return NULL;
+       }
+
+       /* time stamp */
+       timestr = talloc_asprintf( common_data_count_str, \
                "%04d-%02d-%02d %02d:%02d:%02d.%03d", \
                tm->tm_year+1900, \
                tm->tm_mon+1, \
@@ -303,8 +359,29 @@ static char *smb_traffic_analyzer_create_string( struct tm *tm, \
                tm->tm_sec, \
                (int)seconds);
        len = strlen( timestr );
-       buf = talloc_asprintf_append( buf, "%04u%s", len, timestr);
-       
+       /* create the string of common data */
+       buf = talloc_asprintf(ctx,
+               "%s%04u%s%04u%s%04u%s%04u%s%04u%s%04u%s%04u%s",
+               common_data_count_str,
+               (unsigned int) strlen(vfs_operation_str),
+               vfs_operation_str,
+               (unsigned int) strlen(username),
+               username,
+               (unsigned int) strlen(sidstr),
+               sidstr,
+               (unsigned int) strlen(service_name),
+               service_name,
+               (unsigned int)
+               strlen(handle->conn->session_info->info->domain_name),
+               handle->conn->session_info->info->domain_name,
+               (unsigned int) strlen(timestr),
+               timestr,
+               (unsigned int) strlen(raddr),
+               raddr);
+
+       talloc_free(common_data_count_str);
+
+       /* data blocks depending on the VFS function */ 
        va_start( ap, count );
        while ( count-- ) {
                arg = va_arg( ap, char * );
@@ -333,13 +410,31 @@ static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
        char *str = NULL;
        char *username = NULL;
        char *header = NULL;
-       const char *anon_prefix = NULL;
-       const char *total_anonymization = NULL;
        const char *protocol_version = NULL;
        bool Write = false;
        size_t len;
+       size_t size;
+       char *akey, *output;
+
+       /*
+        * 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.
+        */
        char state_flags[9] = "000000\0";
 
+       /**
+        * 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;
+
        SMB_VFS_HANDLE_GET_DATA(handle, rf_sock, struct refcounted_sock, return);
 
        if (rf_sock == NULL || rf_sock->sock == -1) {
@@ -349,45 +444,33 @@ static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
        }
 
        GetTimeOfDay(&tv);
-       tv_sec = convert_timespec_to_time_t(convert_timeval_to_timespec(tv));
+       tv_sec = tv.tv_sec;
        tm = localtime(&tv_sec);
        if (!tm) {
                return;
        }
        seconds=(float) (tv.tv_usec / 1000);
 
-       /* check if anonymization is required */
-       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) {
-               state_flags[1] = 'A';
-               if (total_anonymization!=NULL) {
-                       username = talloc_asprintf(talloc_tos(),
-                               "%s",
-                               anon_prefix);
-               } else {
-                       username = talloc_asprintf(talloc_tos(),
-                               "%s%i",
-                               anon_prefix,
-                               str_checksum(
-                                       handle->conn->server_info->sanitized_username ) ); 
-               }
-
-       } else {
-               username = handle->conn->server_info->sanitized_username;
-       }
+       /*
+        * 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.
+        */
+       username = smb_traffic_analyzer_anonymize( talloc_tos(),
+                       handle->conn->session_info->unix_info->sanitized_username,
+                       handle);
 
        if (!username) {
                return;
        }
+
        protocol_version = lp_parm_const_string(SNUM(handle->conn),
-               "smb_traffic_analyzer",
-               "protocol_version", NULL );
+                                       "smb_traffic_analyzer",
+                                       "protocol_version", NULL );
+
 
-       if ( protocol_version == NULL || strcmp( protocol_version,"V1") == 0) {
+       if (protocol_version != NULL && strcmp(protocol_version,"V1") == 0) {
 
                struct rw_data *s_data = (struct rw_data *) data;
 
@@ -406,7 +489,7 @@ static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
                        "\"%04d-%02d-%02d %02d:%02d:%02d.%03d\"\n",
                        (unsigned int) s_data->len,
                        username,
-                       pdb_get_domain(handle->conn->server_info->sam_account),
+                       handle->conn->session_info->info->domain_name,
                        Write ? 'W' : 'R',
                        handle->conn->connectpath,
                        s_data->filename,
@@ -417,43 +500,63 @@ static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
                        tm->tm_min,
                        tm->tm_sec,
                        (int)seconds);
+               len = strlen(str);
                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;
                }
 
-       } else if ( strcmp( protocol_version, "V2") == 0) {
+       } else {
+               /**
+                * Protocol 2 is used by default.
+                */
 
                switch( vfs_operation ) {
+               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;
                case vfs_id_mkdir: ;
-                       str = smb_traffic_analyzer_create_string( tm, \
-                               seconds, handle, username, vfs_id_mkdir, 3,\
-                               ((struct mkdir_data *) data)->path, \
+                       str = smb_traffic_analyzer_create_string( talloc_tos(),
+                               tm, seconds, handle, username, vfs_id_mkdir, \
+                               3, ((struct mkdir_data *) data)->path, \
                                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: ;
-                       str = smb_traffic_analyzer_create_string( tm, \
-                               seconds, handle, username, vfs_id_rmdir, 2,\
-                               ((struct rmdir_data *) data)->path, \
+                       str = smb_traffic_analyzer_create_string( talloc_tos(),
+                               tm, seconds, handle, username, vfs_id_rmdir,
+                               2, ((struct rmdir_data *) data)->path, \
                                talloc_asprintf( talloc_tos(), "%u", \
                                ((struct rmdir_data *) data)->result ));
                        break;
                case vfs_id_rename: ;
-                       str = smb_traffic_analyzer_create_string( tm, \
-                               seconds, handle, username, vfs_id_rename, 3,\
-                               ((struct rename_data *) data)->src, \
+                       str = smb_traffic_analyzer_create_string( talloc_tos(),
+                               tm, seconds, handle, username, vfs_id_rename,
+                               3, ((struct rename_data *) data)->src, \
                                ((struct rename_data *) data)->dst,
                                talloc_asprintf(talloc_tos(), "%u", \
                                ((struct rename_data *) data)->result));
                        break;
                case vfs_id_chdir: ;
-                       str = smb_traffic_analyzer_create_string( tm, \
-                               seconds, handle, username, vfs_id_chdir, 2,\
-                               ((struct chdir_data *) data)->path, \
+                       str = smb_traffic_analyzer_create_string( talloc_tos(),
+                               tm, seconds, handle, username, vfs_id_chdir,
+                               2, ((struct chdir_data *) data)->path, \
                                talloc_asprintf(talloc_tos(), "%u", \
                                ((struct chdir_data *) data)->result));
                        break;
@@ -462,11 +565,12 @@ static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
                case vfs_id_pwrite:
                case vfs_id_read:
                case vfs_id_pread: ;
-                       str = smb_traffic_analyzer_create_string( tm, \
-                               seconds, handle, username, vfs_operation, 2,\
-                               ((struct rw_data *) data)->filename, \
+                       str = smb_traffic_analyzer_create_string( talloc_tos(),
+                               tm, seconds, handle, username, vfs_operation,
+                               2, ((struct rw_data *) data)->filename, \
                                talloc_asprintf(talloc_tos(), "%u", \
-                               ((struct rw_data *) data)->len));
+                               (unsigned int)
+                                       ((struct rw_data *) data)->len));
                        break;
                default:
                        DEBUG(1, ("smb_traffic_analyzer: error! "
@@ -474,10 +578,6 @@ static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
                        return;
                }
 
-       } else {
-               DEBUG(1, ("smb_traffic_analyzer_send_data_socket: "
-                       "error, unkown protocol given!\n"));
-               return;
        }
 
        if (!str) {
@@ -491,54 +591,33 @@ static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
         * If configured, optain the key and run AES encryption
         * over the data.
         */
-       size_t size;
-       char *akey = secrets_fetch("smb_traffic_analyzer_key", &size);
+       become_root();
+       akey = (char *) secrets_fetch("smb_traffic_analyzer_key", &size);
+       unbecome_root();
        if ( akey != NULL ) {
-               char *crypted;
                state_flags[2] = 'E';
-               DEBUG(10, ("smb_traffic_analyzer: a key was found, encrypting "
-                       "data!"));
-               AES_KEY *key;
-               samba_AES_set_encrypt_key(akey, 128, key);
-               samba_AES_encrypt( str, crypted, key );
-               len = strlen( crypted );
-               header = talloc_asprintf( talloc_tos(), "V2.%s%017u",
+               DEBUG(10, ("smb_traffic_analyzer_send_data_socket: a key was"
+                       " found, encrypting data!\n"));
+               output = smb_traffic_analyzer_encrypt( talloc_tos(),
+                                               akey, str, &len);
+               SAFE_FREE(akey);
+               header = smb_traffic_analyzer_create_header( talloc_tos(),
                                                state_flags, len);
 
                DEBUG(10, ("smb_traffic_analyzer_send_data_socket:"
-                       " header created for crypted data: %s", header));
-               len = strlen(header);
-               if (write_data(rf_sock->sock, header, len) != len) {
-                       DEBUG(1, ("smb_traffic_analyzer_send_data_socket: "
-                                               "error sending the header"
-                                                " over the socket!\n"));
-               }
-               len = strlen(crypted);
-               if (write_data(rf_sock->sock, crypted, len) != len) {
-                       DEBUG(1, ("smb_traffic_analyzer_send_data_socket: "
-                               "error sending crypted data to socket!\n"));
-               free( crypted );
-               return ;
-               }
+                       " header created for crypted data: %s\n", header));
+               smb_traffic_analyzer_write_data(header, output, len,
+                                                       rf_sock->sock);
+               return;
+
        }
 
         len = strlen(str);
-        header = talloc_asprintf(talloc_tos(), "V2.%s%017u", state_flags, len);
-        DEBUG(10, ("smb_traffic_analyzer_send_data_socket: header created:"
-                                                        "%s\n", header));
-        len = strlen(header);
-        if (write_data(rf_sock->sock, header, len) != len) {
-                DEBUG(1, ("smb_traffic_analyzer_send_data_socket: error "
-                        "sending the header over the socket!\n"));
-        }
-        len = strlen(str);
-       DEBUG(10, ("smb_traffic_analyzer_send_data_socket: going to send "
-                       "data block: %s\n",str));
-       if (write_data(rf_sock->sock, str, len) != len) {
-               DEBUG(1, ("smb_traffic_analyzer_send_data_socket: "
-                       "error sending data to socket!\n"));
-               return ;
-       }
+       header = smb_traffic_analyzer_create_header( talloc_tos(),
+                               state_flags, len);
+       smb_traffic_analyzer_write_data(header, str, strlen(str),
+                               rf_sock->sock);
+
 }
 
 static struct refcounted_sock *sock_list;
@@ -594,7 +673,7 @@ static int smb_traffic_analyzer_connect(struct vfs_handle_struct *handle,
                rf_sock->ref_count++;
        } else {
                /* New connection. */
-               rf_sock = TALLOC_ZERO_P(NULL, struct refcounted_sock);
+               rf_sock = talloc_zero(NULL, struct refcounted_sock);
                if (rf_sock == NULL) {
                        SMB_VFS_NEXT_DISCONNECT(handle);
                        errno = ENOMEM;
@@ -686,6 +765,44 @@ static int smb_traffic_analyzer_mkdir(vfs_handle_struct *handle, \
        return s_data.result;
 }
 
+static ssize_t smb_traffic_analyzer_sendfile(vfs_handle_struct *handle,
+                               int tofd,
+                               files_struct *fromfsp,
+                               const DATA_BLOB *hdr,
+                               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,
+                               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;
+}
+
+
 static ssize_t smb_traffic_analyzer_read(vfs_handle_struct *handle, \
                                files_struct *fsp, void *data, size_t n)
 {
@@ -703,7 +820,7 @@ static ssize_t smb_traffic_analyzer_read(vfs_handle_struct *handle, \
 
 
 static ssize_t smb_traffic_analyzer_pread(vfs_handle_struct *handle, \
-               files_struct *fsp, void *data, size_t n, SMB_OFF_T offset)
+               files_struct *fsp, void *data, size_t n, off_t offset)
 {
        struct rw_data s_data;
 
@@ -736,7 +853,7 @@ static ssize_t smb_traffic_analyzer_write(vfs_handle_struct *handle, \
 }
 
 static ssize_t smb_traffic_analyzer_pwrite(vfs_handle_struct *handle, \
-            files_struct *fsp, const void *data, size_t n, SMB_OFF_T offset)
+            files_struct *fsp, const void *data, size_t n, off_t offset)
 {
        struct rw_data s_data;
 
@@ -751,15 +868,53 @@ static ssize_t smb_traffic_analyzer_pwrite(vfs_handle_struct *handle, \
        return s_data.len;
 }
 
+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;
+       s_data.mode = mode;
+       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;
+}
+
+       
 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,
-       .mkdir = smb_traffic_analyzer_mkdir,
-       .rename = smb_traffic_analyzer_rename,
-       .chdir = smb_traffic_analyzer_chdir
+       .connect_fn = smb_traffic_analyzer_connect,
+       .read_fn = smb_traffic_analyzer_read,
+       .pread_fn = smb_traffic_analyzer_pread,
+       .write_fn = smb_traffic_analyzer_write,
+       .pwrite_fn = smb_traffic_analyzer_pwrite,
+       .mkdir_fn = smb_traffic_analyzer_mkdir,
+       .rename_fn = smb_traffic_analyzer_rename,
+       .chdir_fn = smb_traffic_analyzer_chdir,
+       .open_fn = smb_traffic_analyzer_open,
+       .rmdir_fn = smb_traffic_analyzer_rmdir,
+       .close_fn = smb_traffic_analyzer_close,
+       .sendfile_fn = smb_traffic_analyzer_sendfile,
+       .recvfile_fn = smb_traffic_analyzer_recvfile
 };
 
 /* Module initialization */