smbstatus: always initialize a messaing context
[samba.git] / source3 / modules / vfs_smb_traffic_analyzer.c
index 150b112ee6db7f2c9bbc26cbabdf08e3c8d1e436..f5c39ad6d7ce096346cba9410f3241605f902999 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"
+#include "lib/util/sys_rw_data.h"
 
 /* abstraction for the send_over_network function */
 enum sock_type {INTERNET_SOCKET = 0, UNIX_DOMAIN_SOCKET};
 
 #define LOCAL_PATHNAME "/var/tmp/stadsocket"
 
-/* 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.                           */
-
-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)
@@ -91,7 +53,6 @@ static enum sock_type smb_traffic_analyzer_connMode(vfs_handle_struct *handle)
 
 
 /* Connect to an internet socket */
-
 static int smb_traffic_analyzer_connect_inet_socket(vfs_handle_struct *handle,
                                        const char *name, uint16_t port)
 {
@@ -155,7 +116,6 @@ static int smb_traffic_analyzer_connect_inet_socket(vfs_handle_struct *handle,
 }
 
 /* Connect to a unix domain socket */
-
 static int smb_traffic_analyzer_connect_unix_socket(vfs_handle_struct *handle,
                                                const char *name)
 {
@@ -187,8 +147,7 @@ static int smb_traffic_analyzer_connect_unix_socket(vfs_handle_struct *handle,
        return sock;
 }
 
-/* Private data allowing shared connection sockets.    */
-
+/* Private data allowing shared connection sockets. */
 struct refcounted_sock {
        struct refcounted_sock *next, *prev;
        char *name;
@@ -198,30 +157,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, \
-       char *username, int count, ... )
+/**
+ * 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;
+       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++) {
+               AES_encrypt((const unsigned char *) str+(16*h), (unsigned char *)output+16*h,
+                       &key);
+       }
+       AES_encrypt(filler, (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;
-       char *str = NULL;
        int len;
-       char *header = NULL;
-       char *buf = NULL;
+       char *common_data_count_str = NULL;
        char *timestr = NULL;
+       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;
+       }
 
-       /* first create the data that is transfered with any VFS op     */
-       len = strlen( username );
-       buf = talloc_asprintf(talloc_tos(),"%04u%s", len, username);
-       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(), \
+       /* time stamp */
+       timestr = talloc_asprintf( common_data_count_str, \
                "%04d-%02d-%02d %02d:%02d:%02d.%03d", \
                tm->tm_year+1900, \
                tm->tm_mon+1, \
@@ -231,25 +360,43 @@ 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 * );
-               /* protocol v2 sends a four byte string */
-               /* as a header to each block, including */
-               /* the numbers of bytes to come in the  */
-               /* next string.                         */
+               /*
+                *  protocol v2 sends a four byte string
+                * as a header to each block, including
+                * the numbers of bytes to come in the
+                * next string.
+                */
                len = strlen( arg );
                buf = talloc_asprintf_append( buf, "%04u%s", len, arg);
        }
        va_end( ap );
-
-       /* now create the protocol v2 header.   */
-       len = strlen( buf );
-       str = talloc_asprintf_append( str, "V2,%017u%s", len, buf);
-       DEBUG(10, ("smb_traffic_analyzer_create_string: %s\n",str));
-       return str;
+       return buf;
 }
 
 static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
@@ -263,11 +410,31 @@ static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
        int seconds;
        char *str = NULL;
        char *username = NULL;
-       const char *anon_prefix = NULL;
-       const char *total_anonymization = NULL;
+       char *header = 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);
 
@@ -278,53 +445,41 @@ 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) {
-               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) {
 
-               struct rw_data *s_data = (struct rw_data *) data;
+       if (protocol_version != NULL && strcmp(protocol_version,"V1") == 0) {
 
-               /* in case of protocol v1, ignore any vfs operations    */
-               /* except read,pread,write,pwrite, and set the "Write"  */
-               /* bool accordingly.                                    */
+               struct rw_data *s_data = (struct rw_data *) data;
 
+               /*
+                * in case of protocol v1, ignore any vfs operations
+                * except read,pread,write,pwrite, and set the "Write"
+                * bool accordingly, send data and return.
+                */
                if ( vfs_operation > vfs_id_pwrite ) return;
 
                if ( vfs_operation <= vfs_id_pread ) Write=false;
@@ -335,9 +490,9 @@ 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,
+                       handle->conn->cwd,
                        s_data->filename,
                        tm->tm_year+1900,
                        tm->tm_mon+1,
@@ -346,61 +501,84 @@ static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
                        tm->tm_min,
                        tm->tm_sec,
                        (int)seconds);
-       } else if ( strcmp( protocol_version, "V2") == 0) {
+               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 {
+               /**
+                * Protocol 2 is used by default.
+                */
 
                switch( vfs_operation ) {
-                       case vfs_id_mkdir: ;
-                               str = smb_traffic_analyzer_create_string( tm, \
-                                       seconds, handle, username, 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, 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, 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, 2,\
-                                       ((struct chdir_data *) data)->path, \
-                                       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: ;
-                               str = smb_traffic_analyzer_create_string( tm, \
-                                       seconds, handle, username, 2,\
-                                       ((struct rw_data *) data)->filename, \
-                                       talloc_asprintf(talloc_tos(), "%u", \
+               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",
+                               (unsigned int)((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( talloc_tos(),
+                               tm, seconds, handle, username, vfs_id_mkdir, \
+                               3, ((struct mkdir_data *) data)->path, \
+                               talloc_asprintf( talloc_tos(), "%u", \
+                               (unsigned int)((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( 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( 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( 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;
+
+               case vfs_id_write:
+               case vfs_id_pwrite:
+               case vfs_id_read:
+               case vfs_id_pread: ;
+                       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", \
+                               (unsigned int)
                                        ((struct rw_data *) data)->len));
-                               break;
-                       default:
-                               DEBUG(1, ("smb_traffic_analyzer: error! "
-                                       "wrong VFS operation id detected!\n"));
-                               return;
+                       break;
+               default:
+                       DEBUG(1, ("smb_traffic_analyzer: error! "
+                               "wrong VFS operation id detected!\n"));
+                       return;
                }
 
-       } else {
-               DEBUG(1, ("smb_traffic_analyzer_send_data_socket: "
-                       "error, unkown protocol given!\n"));
-               return;
        }
 
        if (!str) {
@@ -409,34 +587,38 @@ static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
                return;
        }
 
-       len = strlen(str);
 
-       DEBUG(10, ("smb_traffic_analyzer_send_data_socket: going to send "
-               "%s\n", str));
-       /* If configured, optain the key and run AES encryption */
-       /* over the data.                                       */
-       size_t size;
-       char *akey = secrets_fetch("smb_traffic_analyzer_key", &size);
+       /*
+        * If configured, optain the key and run AES encryption
+        * over the data.
+        */
+       become_root();
+       akey = (char *) secrets_fetch("smb_traffic_analyzer_key", &size);
+       unbecome_root();
        if ( akey != NULL ) {
-               char *crypted;
-               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 );
-               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 ;
-               }
-       }
-       if (write_data(rf_sock->sock, str, len) != len) {
-               DEBUG(1, ("smb_traffic_analyzer_send_data_socket: "
-                       "error sending data to socket!\n"));
-               return ;
+               state_flags[2] = 'E';
+               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\n", header));
+               smb_traffic_analyzer_write_data(header, output, len,
+                                                       rf_sock->sock);
+               return;
+
        }
+
+        len = strlen(str);
+       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;
@@ -492,7 +674,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;
@@ -584,6 +766,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)
 {
@@ -601,7 +821,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;
 
@@ -634,7 +854,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;
 
@@ -649,19 +869,57 @@ 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 */
-
+static_decl_vfs;
 NTSTATUS vfs_smb_traffic_analyzer_init(void)
 {
        NTSTATUS ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION,