smbstatus: always initialize a messaing context
[samba.git] / source3 / modules / vfs_smb_traffic_analyzer.c
index 57d483fa46bd4491be3fa13850a133d979bee54c..f5c39ad6d7ce096346cba9410f3241605f902999 100644 (file)
  */
 
 #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/dom_sid.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};
@@ -164,28 +170,27 @@ struct refcounted_sock {
 static char *smb_traffic_analyzer_encrypt( TALLOC_CTX *ctx,
        const char *akey, const char *str, size_t *len)
 {
-       int s1,s2,h,d;
+       int s1,s2,h;
        AES_KEY key;
        unsigned char filler[17]= "................";
        char *output;
-       unsigned char crypted[18];
        if (akey == NULL) return NULL;
-       samba_AES_set_encrypt_key((unsigned char *) akey, 128, &key);
+       AES_set_encrypt_key((const unsigned char *) akey, 128, &key);
        s1 = strlen(str) / 16;
        s2 = strlen(str) % 16;
-       for (h = 0; h < s2; h++) *(filler+h)=*(str+(s1*16)+h);
+       memcpy(filler, str + (s1*16), s2);
        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;
+
+       *len = ((s1 + 1)*16);
+       output = talloc_array(ctx, char, *len);
        for (h = 0; h < s1; h++) {
-               samba_AES_encrypt((unsigned char *) str+(16*h), crypted, &key);
-               for (d = 0; d<16; d++) output[d+(16*h)]=crypted[d];
+               AES_encrypt((const unsigned char *) str+(16*h), (unsigned char *)output+16*h,
+                       &key);
        }
-       samba_AES_encrypt( (unsigned char *) str+(16*h), filler, &key );
-       for (d = 0;d < 16; d++) output[d+(16*h)]=*(filler+d);
+       AES_encrypt(filler, (unsigned char *)(output+(16*h)), &key);
        *len = (s1*16)+16;
-       return output;  
+       return output;
 }
 
 /**
@@ -298,6 +303,7 @@ static char *smb_traffic_analyzer_create_string( TALLOC_CTX *ctx,
        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);
@@ -312,6 +318,7 @@ static char *smb_traffic_analyzer_create_string( TALLOC_CTX *ctx,
         * 4.affected share
         * 5.domain
         * 6.timestamp
+        * 7.IP Addresss of client
         */
 
        /*
@@ -329,13 +336,19 @@ static char *smb_traffic_analyzer_create_string( TALLOC_CTX *ctx,
         * anonymized if needed, by the calling function.
         */
        usersid = dom_sid_string( common_data_count_str,
-               &handle->conn->server_info->ptok->user_sids[0]);
+               &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", \
@@ -347,10 +360,9 @@ static char *smb_traffic_analyzer_create_string( TALLOC_CTX *ctx,
                tm->tm_sec, \
                (int)seconds);
        len = strlen( timestr );
-
        /* create the string of common data */
        buf = talloc_asprintf(ctx,
-               "%s%04u%s%04u%s%04u%s%04u%s%04u%s%04u%s",
+               "%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,
@@ -361,10 +373,12 @@ static char *smb_traffic_analyzer_create_string( TALLOC_CTX *ctx,
                (unsigned int) strlen(service_name),
                service_name,
                (unsigned int)
-               strlen(handle->conn->server_info->info3->base.domain.string),
-               handle->conn->server_info->info3->base.domain.string,
+               strlen(handle->conn->session_info->info->domain_name),
+               handle->conn->session_info->info->domain_name,
                (unsigned int) strlen(timestr),
-               timestr);
+               timestr,
+               (unsigned int) strlen(raddr),
+               raddr);
 
        talloc_free(common_data_count_str);
 
@@ -411,6 +425,17 @@ static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
         */
        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) {
@@ -420,7 +445,7 @@ 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;
@@ -434,7 +459,7 @@ static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
         * function.
         */
        username = smb_traffic_analyzer_anonymize( talloc_tos(),
-                       handle->conn->server_info->sanitized_username,
+                       handle->conn->session_info->unix_info->sanitized_username,
                        handle);
 
        if (!username) {
@@ -446,7 +471,7 @@ static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
                                        "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;
 
@@ -465,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,
-                       handle->conn->server_info->info3->base.domain.string,
+                       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,
@@ -483,7 +508,10 @@ static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
                return;
                }
 
-       } else if ( strcmp( protocol_version, "V2") == 0) {
+       } else {
+               /**
+                * Protocol 2 is used by default.
+                */
 
                switch( vfs_operation ) {
                case vfs_id_open: ;
@@ -491,7 +519,7 @@ static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
                                tm, seconds, handle, username, vfs_id_open,
                                3, ((struct open_data *) data)->filename,
                                talloc_asprintf( talloc_tos(), "%u",
-                               ((struct open_data *) data)->mode),
+                               (unsigned int)((struct open_data *) data)->mode),
                                talloc_asprintf( talloc_tos(), "%u",
                                ((struct open_data *) data)->result));
                        break;
@@ -507,7 +535,7 @@ static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
                                tm, seconds, handle, username, vfs_id_mkdir, \
                                3, ((struct mkdir_data *) data)->path, \
                                talloc_asprintf( talloc_tos(), "%u", \
-                               ((struct mkdir_data *) data)->mode), \
+                               (unsigned int)((struct mkdir_data *) data)->mode), \
                                talloc_asprintf( talloc_tos(), "%u", \
                                ((struct mkdir_data *) data)->result ));
                        break;
@@ -551,10 +579,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) {
@@ -577,6 +601,7 @@ static void smb_traffic_analyzer_send_data(vfs_handle_struct *handle,
                        " 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);
 
@@ -649,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;
@@ -741,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)
 {
@@ -758,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;
 
@@ -791,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;
 
@@ -840,20 +903,23 @@ static int smb_traffic_analyzer_close(vfs_handle_struct *handle, \
 
        
 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,
-       .open = smb_traffic_analyzer_open,
-       .rmdir = smb_traffic_analyzer_rmdir,
-       .close_fn = smb_traffic_analyzer_close
+       .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,