"Fossies" - the Fresh Open Source Software Archive

Member "snort-2.9.17/src/dynamic-preprocessors/dcerpc2/dce2_smb.c" (16 Oct 2020, 375702 Bytes) of package /linux/misc/snort-2.9.17.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "dce2_smb.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.9.16.1_vs_2.9.17.

    1 /****************************************************************************
    2  * Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved.
    3  * Copyright (C) 2008-2013 Sourcefire, Inc.
    4  *
    5  * This program is free software; you can redistribute it and/or modify
    6  * it under the terms of the GNU General Public License Version 2 as
    7  * published by the Free Software Foundation.  You may not use, modify or
    8  * distribute this program under any other version of the GNU General
    9  * Public License.
   10  *
   11  * This program is distributed in the hope that it will be useful,
   12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14  * GNU General Public License for more details.
   15  *
   16  * You should have received a copy of the GNU General Public License
   17  * along with this program; if not, write to the Free Software
   18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   19  *
   20  ****************************************************************************
   21  *
   22  ****************************************************************************/
   23 
   24 #ifdef HAVE_CONFIG_H
   25 #include "config.h"
   26 #endif
   27 
   28 #include "sf_types.h"
   29 #include "spp_dce2.h"
   30 #include "dce2_smb.h"
   31 #include "dce2_tcp.h"
   32 #include "dce2_co.h"
   33 #include "snort_dce2.h"
   34 #include "dce2_config.h"
   35 #include "dce2_memory.h"
   36 #include "dce2_utils.h"
   37 #include "dce2_debug.h"
   38 #include "dce2_stats.h"
   39 #include "dce2_event.h"
   40 #include "smb.h"
   41 #include "sf_snort_packet.h"
   42 #include "sf_types.h"
   43 #include "stream_api.h"
   44 #include "session_api.h"
   45 #include "profiler.h"
   46 #include "snort_debug.h"
   47 #include "sf_dynamic_preprocessor.h"
   48 #include "file_api.h"
   49 #include "dce2_smb2.h"
   50 
   51 #ifdef DUMP_BUFFER
   52 #include "dcerpc2_buffer_dump.h"
   53 #endif
   54 
   55 #ifndef WIN32
   56 #include <arpa/inet.h>  /* for ntohl */
   57 #endif  /* WIN32 */
   58 
   59 /********************************************************************
   60  * Enums
   61  ********************************************************************/
   62 typedef enum _DCE2_SmbComError
   63 {
   64     // No errors associated with the command
   65     DCE2_SMB_COM_ERROR__COMMAND_OK          = 0x0000,
   66 
   67     // An error was reported in the SMB response header
   68     DCE2_SMB_COM_ERROR__STATUS_ERROR        = 0x0001,
   69 
   70     // An invalid word count makes it unlikely any data accessed will be correct
   71     // and if accessed the possibility of accessing out of bounds data
   72     DCE2_SMB_COM_ERROR__INVALID_WORD_COUNT  = 0x0002,
   73 
   74     // An invalid byte count just means the byte count is not right for
   75     // the command processed.  The command can still be processed but
   76     // the byte count should not be used.  In general, the byte count
   77     // should not be used since Windows and Samba often times ignore it
   78     DCE2_SMB_COM_ERROR__INVALID_BYTE_COUNT  = 0x0004,
   79 
   80     // Not enough data to process command so don't try to access any
   81     // of the command's header or data.
   82     DCE2_SMB_COM_ERROR__BAD_LENGTH          = 0x0008
   83 
   84 } DCE2_SmbComError;
   85 
   86 /********************************************************************
   87  * Structures
   88  ********************************************************************/
   89 typedef struct _DCE2_SmbComInfo
   90 {
   91     int smb_type;   // SMB_TYPE__REQUEST or SMB_TYPE__RESPONSE
   92     int cmd_error;  // mask of DCE2_SmbComError
   93     uint8_t smb_com;
   94     uint8_t word_count;
   95     uint16_t byte_count;
   96     uint16_t cmd_size;
   97 
   98 } DCE2_SmbComInfo;
   99 
  100 unsigned smb_upload_ret_cb_id = 0;
  101 
  102 // Inline accessor functions for DCE2_SmbComInfo
  103 
  104 static inline bool DCE2_ComInfoIsResponse(const DCE2_SmbComInfo *com_info)
  105 {
  106     return (com_info->smb_type == SMB_TYPE__RESPONSE) ? true : false;
  107 }
  108 
  109 static inline bool DCE2_ComInfoIsRequest(const DCE2_SmbComInfo *com_info)
  110 {
  111     return (com_info->smb_type == SMB_TYPE__REQUEST) ? true : false;
  112 }
  113 
  114 static inline uint8_t DCE2_ComInfoWordCount(const DCE2_SmbComInfo *com_info)
  115 {
  116     return com_info->word_count;
  117 }
  118 
  119 static inline uint8_t DCE2_ComInfoSmbCom(const DCE2_SmbComInfo *com_info)
  120 {
  121     return com_info->smb_com;
  122 }
  123 
  124 static inline uint16_t DCE2_ComInfoByteCount(const DCE2_SmbComInfo *com_info)
  125 {
  126     return com_info->byte_count;
  127 }
  128 
  129 static inline uint16_t DCE2_ComInfoCommandSize(const DCE2_SmbComInfo *com_info)
  130 {
  131     return com_info->cmd_size;
  132 }
  133 
  134 static inline bool DCE2_ComInfoIsStatusError(const DCE2_SmbComInfo *com_info)
  135 {
  136     return (com_info->cmd_error & DCE2_SMB_COM_ERROR__STATUS_ERROR) ? true : false;
  137 }
  138 
  139 static inline bool DCE2_ComInfoIsInvalidWordCount(const DCE2_SmbComInfo *com_info)
  140 {
  141     return (com_info->cmd_error & DCE2_SMB_COM_ERROR__INVALID_WORD_COUNT) ? true : false;
  142 }
  143 
  144 static inline bool DCE2_ComInfoIsBadLength(const DCE2_SmbComInfo *com_info)
  145 {
  146     return (com_info->cmd_error & DCE2_SMB_COM_ERROR__BAD_LENGTH) ? true : false;
  147 }
  148 
  149 // If this returns false, the command should not be processed
  150 static inline bool DCE2_ComInfoCanProcessCommand(const DCE2_SmbComInfo *com_info)
  151 {
  152     if (DCE2_ComInfoIsBadLength(com_info)
  153             || DCE2_ComInfoIsStatusError(com_info)
  154             || DCE2_ComInfoIsInvalidWordCount(com_info))
  155         return false;
  156     return true;
  157 }
  158 
  159 /********************************************************************
  160  * Global variables
  161  ********************************************************************/
  162 typedef DCE2_Ret (*DCE2_SmbComFunc)(DCE2_SmbSsnData *, const SmbNtHdr *,
  163         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  164 
  165 static DCE2_SmbComFunc smb_com_funcs[SMB_MAX_NUM_COMS];
  166 static uint8_t smb_wcts[SMB_MAX_NUM_COMS][2][32];
  167 static uint16_t smb_bccs[SMB_MAX_NUM_COMS][2][2];
  168 static DCE2_SmbComFunc smb_chain_funcs[DCE2_POLICY__MAX][SMB_ANDX_COM__MAX][SMB_MAX_NUM_COMS];
  169 static bool smb_deprecated_coms[SMB_MAX_NUM_COMS];
  170 static bool smb_unusual_coms[SMB_MAX_NUM_COMS];
  171 
  172 // File name of the current file we are tracking for logging since the
  173 // file tracker may be gone before logging occurs.
  174 uint8_t smb_file_name[2*DCE2_SMB_MAX_PATH_LEN + UTF_16_LE_BOM_LEN + 2];
  175 uint16_t smb_file_name_len;
  176 
  177 // Exported
  178 SmbAndXCom smb_chain_map[SMB_MAX_NUM_COMS];
  179 
  180 const char *smb_com_strings[SMB_MAX_NUM_COMS] = {
  181     "Create Directory",            // 0x00
  182     "Delete Directory",            // 0x01
  183     "Open",                        // 0x02
  184     "Create",                      // 0x03
  185     "Close",                       // 0x04
  186     "Flush",                       // 0x05
  187     "Delete",                      // 0x06
  188     "Rename",                      // 0x07
  189     "Query Information",           // 0x08
  190     "Set Information",             // 0x09
  191     "Read",                        // 0x0A
  192     "Write",                       // 0x0B
  193     "Lock Byte Range",             // 0x0C
  194     "Unlock Byte Range",           // 0x0D
  195     "Create Temporary",            // 0x0E
  196     "Create New",                  // 0x0F
  197     "Check Directory",             // 0x10
  198     "Process Exit",                // 0x11
  199     "Seek",                        // 0x12
  200     "Lock And Read",               // 0x13
  201     "Write And Unlock",            // 0x14
  202     "Unknown",                     // 0X15
  203     "Unknown",                     // 0X16
  204     "Unknown",                     // 0X17
  205     "Unknown",                     // 0X18
  206     "Unknown",                     // 0X19
  207     "Read Raw",                    // 0x1A
  208     "Read Mpx",                    // 0x1B
  209     "Read Mpx Secondary",          // 0x1C
  210     "Write Raw",                   // 0x1D
  211     "Write Mpx",                   // 0x1E
  212     "Write Mpx Secondary",         // 0x1F
  213     "Write Complete",              // 0x20
  214     "Query Server",                // 0x21
  215     "Set Information2",            // 0x22
  216     "Query Information2",          // 0x23
  217     "Locking AndX",                // 0x24
  218     "Transaction",                 // 0x25
  219     "Transaction Secondary",       // 0x26
  220     "Ioctl",                       // 0x27
  221     "Ioctl Secondary",             // 0x28
  222     "Copy",                        // 0x29
  223     "Move",                        // 0x2A
  224     "Echo",                        // 0x2B
  225     "Write And Close",             // 0x2C
  226     "Open AndX",                   // 0x2D
  227     "Read AndX",                   // 0x2E
  228     "Write AndX",                  // 0x2F
  229     "New File Size",               // 0x30
  230     "Close And Tree Disc",         // 0x31
  231     "Transaction2",                // 0x32
  232     "Transaction2 Secondary",      // 0x33
  233     "Find Close2",                 // 0x34
  234     "Find Notify Close",           // 0x35
  235     "Unknown",                     // 0X36
  236     "Unknown",                     // 0X37
  237     "Unknown",                     // 0X38
  238     "Unknown",                     // 0X39
  239     "Unknown",                     // 0X3A
  240     "Unknown",                     // 0X3B
  241     "Unknown",                     // 0X3C
  242     "Unknown",                     // 0X3D
  243     "Unknown",                     // 0X3E
  244     "Unknown",                     // 0X3F
  245     "Unknown",                     // 0X40
  246     "Unknown",                     // 0X41
  247     "Unknown",                     // 0X42
  248     "Unknown",                     // 0X43
  249     "Unknown",                     // 0X44
  250     "Unknown",                     // 0X45
  251     "Unknown",                     // 0X46
  252     "Unknown",                     // 0X47
  253     "Unknown",                     // 0X48
  254     "Unknown",                     // 0X49
  255     "Unknown",                     // 0X4A
  256     "Unknown",                     // 0X4B
  257     "Unknown",                     // 0X4C
  258     "Unknown",                     // 0X4D
  259     "Unknown",                     // 0X4E
  260     "Unknown",                     // 0X4F
  261     "Unknown",                     // 0X50
  262     "Unknown",                     // 0X51
  263     "Unknown",                     // 0X52
  264     "Unknown",                     // 0X53
  265     "Unknown",                     // 0X54
  266     "Unknown",                     // 0X55
  267     "Unknown",                     // 0X56
  268     "Unknown",                     // 0X57
  269     "Unknown",                     // 0X58
  270     "Unknown",                     // 0X59
  271     "Unknown",                     // 0X5A
  272     "Unknown",                     // 0X5B
  273     "Unknown",                     // 0X5C
  274     "Unknown",                     // 0X5D
  275     "Unknown",                     // 0X5E
  276     "Unknown",                     // 0X5F
  277     "Unknown",                     // 0X60
  278     "Unknown",                     // 0X61
  279     "Unknown",                     // 0X62
  280     "Unknown",                     // 0X63
  281     "Unknown",                     // 0X64
  282     "Unknown",                     // 0X65
  283     "Unknown",                     // 0X66
  284     "Unknown",                     // 0X67
  285     "Unknown",                     // 0X68
  286     "Unknown",                     // 0X69
  287     "Unknown",                     // 0X6A
  288     "Unknown",                     // 0X6B
  289     "Unknown",                     // 0X6C
  290     "Unknown",                     // 0X6D
  291     "Unknown",                     // 0X6E
  292     "Unknown",                     // 0X6F
  293     "Tree Connect",                // 0x70
  294     "Tree Disconnect",             // 0x71
  295     "Negotiate",                   // 0x72
  296     "Session Setup AndX",          // 0x73
  297     "Logoff AndX",                 // 0x74
  298     "Tree Connect AndX",           // 0x75
  299     "Unknown",                     // 0X76
  300     "Unknown",                     // 0X77
  301     "Unknown",                     // 0X78
  302     "Unknown",                     // 0X79
  303     "Unknown",                     // 0X7A
  304     "Unknown",                     // 0X7B
  305     "Unknown",                     // 0X7C
  306     "Unknown",                     // 0X7D
  307     "Security Package AndX",       // 0x7E
  308     "Unknown",                     // 0X7F
  309     "Query Information Disk",      // 0x80
  310     "Search",                      // 0x81
  311     "Find",                        // 0x82
  312     "Find Unique",                 // 0x83
  313     "Find Close",                  // 0x84
  314     "Unknown",                     // 0X85
  315     "Unknown",                     // 0X86
  316     "Unknown",                     // 0X87
  317     "Unknown",                     // 0X88
  318     "Unknown",                     // 0X89
  319     "Unknown",                     // 0X8A
  320     "Unknown",                     // 0X8B
  321     "Unknown",                     // 0X8C
  322     "Unknown",                     // 0X8D
  323     "Unknown",                     // 0X8E
  324     "Unknown",                     // 0X8F
  325     "Unknown",                     // 0X90
  326     "Unknown",                     // 0X91
  327     "Unknown",                     // 0X92
  328     "Unknown",                     // 0X93
  329     "Unknown",                     // 0X94
  330     "Unknown",                     // 0X95
  331     "Unknown",                     // 0X96
  332     "Unknown",                     // 0X97
  333     "Unknown",                     // 0X98
  334     "Unknown",                     // 0X99
  335     "Unknown",                     // 0X9A
  336     "Unknown",                     // 0X9B
  337     "Unknown",                     // 0X9C
  338     "Unknown",                     // 0X9D
  339     "Unknown",                     // 0X9E
  340     "Unknown",                     // 0X9F
  341     "Nt Transact",                 // 0xA0
  342     "Nt Transact Secondary",       // 0xA1
  343     "Nt Create AndX",              // 0xA2
  344     "Unknown",                     // 0XA3
  345     "Nt Cancel",                   // 0xA4
  346     "Nt Rename",                   // 0xA5
  347     "Unknown",                     // 0XA6
  348     "Unknown",                     // 0XA7
  349     "Unknown",                     // 0XA8
  350     "Unknown",                     // 0XA9
  351     "Unknown",                     // 0XAA
  352     "Unknown",                     // 0XAB
  353     "Unknown",                     // 0XAC
  354     "Unknown",                     // 0XAD
  355     "Unknown",                     // 0XAE
  356     "Unknown",                     // 0XAF
  357     "Unknown",                     // 0XB0
  358     "Unknown",                     // 0XB1
  359     "Unknown",                     // 0XB2
  360     "Unknown",                     // 0XB3
  361     "Unknown",                     // 0XB4
  362     "Unknown",                     // 0XB5
  363     "Unknown",                     // 0XB6
  364     "Unknown",                     // 0XB7
  365     "Unknown",                     // 0XB8
  366     "Unknown",                     // 0XB9
  367     "Unknown",                     // 0XBA
  368     "Unknown",                     // 0XBB
  369     "Unknown",                     // 0XBC
  370     "Unknown",                     // 0XBD
  371     "Unknown",                     // 0XBE
  372     "Unknown",                     // 0XBF
  373     "Open Print File",             // 0xC0
  374     "Write Print File",            // 0xC1
  375     "Close Print File",            // 0xC2
  376     "Get Print Queue",             // 0xC3
  377     "Unknown",                     // 0XC4
  378     "Unknown",                     // 0XC5
  379     "Unknown",                     // 0XC6
  380     "Unknown",                     // 0XC7
  381     "Unknown",                     // 0XC8
  382     "Unknown",                     // 0XC9
  383     "Unknown",                     // 0XCA
  384     "Unknown",                     // 0XCB
  385     "Unknown",                     // 0XCC
  386     "Unknown",                     // 0XCD
  387     "Unknown",                     // 0XCE
  388     "Unknown",                     // 0XCF
  389     "Unknown",                     // 0XD0
  390     "Unknown",                     // 0XD1
  391     "Unknown",                     // 0XD2
  392     "Unknown",                     // 0XD3
  393     "Unknown",                     // 0XD4
  394     "Unknown",                     // 0XD5
  395     "Unknown",                     // 0XD6
  396     "Unknown",                     // 0XD7
  397     "Read Bulk",                   // 0xD8
  398     "Write Bulk",                  // 0xD9
  399     "Write Bulk Data",             // 0xDA
  400     "Unknown",                     // 0XDB
  401     "Unknown",                     // 0XDC
  402     "Unknown",                     // 0XDD
  403     "Unknown",                     // 0XDE
  404     "Unknown",                     // 0XDF
  405     "Unknown",                     // 0XE0
  406     "Unknown",                     // 0XE1
  407     "Unknown",                     // 0XE2
  408     "Unknown",                     // 0XE3
  409     "Unknown",                     // 0XE4
  410     "Unknown",                     // 0XE5
  411     "Unknown",                     // 0XE6
  412     "Unknown",                     // 0XE7
  413     "Unknown",                     // 0XE8
  414     "Unknown",                     // 0XE9
  415     "Unknown",                     // 0XEA
  416     "Unknown",                     // 0XEB
  417     "Unknown",                     // 0XEC
  418     "Unknown",                     // 0XED
  419     "Unknown",                     // 0XEE
  420     "Unknown",                     // 0XEF
  421     "Unknown",                     // 0XF0
  422     "Unknown",                     // 0XF1
  423     "Unknown",                     // 0XF2
  424     "Unknown",                     // 0XF3
  425     "Unknown",                     // 0XF4
  426     "Unknown",                     // 0XF5
  427     "Unknown",                     // 0XF6
  428     "Unknown",                     // 0XF7
  429     "Unknown",                     // 0XF8
  430     "Unknown",                     // 0XF9
  431     "Unknown",                     // 0XFA
  432     "Unknown",                     // 0XFB
  433     "Unknown",                     // 0XFC
  434     "Unknown",                     // 0XFD
  435     "Invalid",                     // 0xFE
  436     "No AndX Command"              // 0xFF
  437 };
  438 
  439 const char *smb_transaction_sub_command_strings[TRANS_SUBCOM_MAX] = {
  440     "Unknown",                               // 0x0000
  441     "TRANS_SET_NMPIPE_STATE",                // 0x0001
  442     "Unknown",                               // 0x0002
  443     "Unknown",                               // 0x0003
  444     "Unknown",                               // 0x0004
  445     "Unknown",                               // 0x0005
  446     "Unknown",                               // 0x0006
  447     "Unknown",                               // 0x0007
  448     "Unknown",                               // 0x0008
  449     "Unknown",                               // 0x0009
  450     "Unknown",                               // 0x000A
  451     "Unknown",                               // 0x000B
  452     "Unknown",                               // 0x000C
  453     "Unknown",                               // 0x000D
  454     "Unknown",                               // 0x000E
  455     "Unknown",                               // 0x000F
  456     "Unknown",                               // 0x0010
  457     "TRANS_RAW_READ_NMPIPE",                 // 0x0011
  458     "Unknown",                               // 0x0012
  459     "Unknown",                               // 0x0013
  460     "Unknown",                               // 0x0014
  461     "Unknown",                               // 0x0015
  462     "Unknown",                               // 0x0016
  463     "Unknown",                               // 0x0017
  464     "Unknown",                               // 0x0018
  465     "Unknown",                               // 0x0019
  466     "Unknown",                               // 0x001A
  467     "Unknown",                               // 0x001B
  468     "Unknown",                               // 0x001C
  469     "Unknown",                               // 0x001D
  470     "Unknown",                               // 0x001E
  471     "Unknown",                               // 0x001F
  472     "Unknown",                               // 0x0020
  473     "TRANS_QUERY_NMPIPE_STATE",              // 0x0021
  474     "TRANS_QUERY_NMPIPE_INFO",               // 0x0022
  475     "TRANS_PEEK_NMPIPE",                     // 0x0023
  476     "Unknown",                               // 0x0024
  477     "Unknown",                               // 0x0025
  478     "TRANS_TRANSACT_NMPIPE",                 // 0x0026
  479     "Unknown",                               // 0x0027
  480     "Unknown",                               // 0x0028
  481     "Unknown",                               // 0x0029
  482     "Unknown",                               // 0x002A
  483     "Unknown",                               // 0x002B
  484     "Unknown",                               // 0x002C
  485     "Unknown",                               // 0x002D
  486     "Unknown",                               // 0x002E
  487     "Unknown",                               // 0x002F
  488     "Unknown",                               // 0x0030
  489     "TRANS_RAW_WRITE_NMPIPE",                // 0x0031
  490     "Unknown",                               // 0x0032
  491     "Unknown",                               // 0x0033
  492     "Unknown",                               // 0x0034
  493     "Unknown",                               // 0x0035
  494     "TRANS_READ_NMPIPE",                     // 0x0036
  495     "TRANS_WRITE_NMPIPE",                    // 0x0037
  496     "Unknown",                               // 0x0038
  497     "Unknown",                               // 0x0039
  498     "Unknown",                               // 0x003A
  499     "Unknown",                               // 0x003B
  500     "Unknown",                               // 0x003C
  501     "Unknown",                               // 0x003D
  502     "Unknown",                               // 0x003E
  503     "Unknown",                               // 0x003F
  504     "Unknown",                               // 0x0040
  505     "Unknown",                               // 0x0041
  506     "Unknown",                               // 0x0042
  507     "Unknown",                               // 0x0043
  508     "Unknown",                               // 0x0044
  509     "Unknown",                               // 0x0045
  510     "Unknown",                               // 0x0046
  511     "Unknown",                               // 0x0047
  512     "Unknown",                               // 0x0048
  513     "Unknown",                               // 0x0049
  514     "Unknown",                               // 0x004A
  515     "Unknown",                               // 0x004B
  516     "Unknown",                               // 0x004C
  517     "Unknown",                               // 0x004D
  518     "Unknown",                               // 0x004E
  519     "Unknown",                               // 0x004F
  520     "Unknown",                               // 0x0050
  521     "Unknown",                               // 0x0051
  522     "Unknown",                               // 0x0052
  523     "TRANS_WAIT_NMPIPE",                     // 0x0053
  524     "TRANS_CALL_NMPIPE"                      // 0x0054
  525 };
  526 
  527 const char *smb_transaction2_sub_command_strings[TRANS2_SUBCOM_MAX] = {
  528     "TRANS2_OPEN2",                          // 0x0000
  529     "TRANS2_FIND_FIRST2",                    // 0x0001
  530     "TRANS2_FIND_NEXT2",                     // 0x0002
  531     "TRANS2_QUERY_FS_INFORMATION",           // 0x0003
  532     "TRANS2_SET_FS_INFORMATION",             // 0x0004
  533     "TRANS2_QUERY_PATH_INFORMATION",         // 0x0005
  534     "TRANS2_SET_PATH_INFORMATION",           // 0x0006
  535     "TRANS2_QUERY_FILE_INFORMATION",         // 0x0007
  536     "TRANS2_SET_FILE_INFORMATION",           // 0x0008
  537     "TRANS2_FSCTL",                          // 0x0009
  538     "TRANS2_IOCTL2",                         // 0x000A
  539     "TRANS2_FIND_NOTIFY_FIRST",              // 0x000B
  540     "TRANS2_FIND_NOTIFY_NEXT",               // 0x000C
  541     "TRANS2_CREATE_DIRECTORY",               // 0x000D
  542     "TRANS2_SESSION_SETUP",                  // 0x000E
  543     "Unknown",                               // 0x000F
  544     "TRANS2_GET_DFS_REFERRAL",               // 0x0010
  545     "TRANS2_REPORT_DFS_INCONSISTENCY"        // 0x0011
  546 };
  547 
  548 const char *smb_nt_transact_sub_command_strings[NT_TRANSACT_SUBCOM_MAX] = {
  549     "Unknown",                               // 0x0000
  550     "NT_TRANSACT_CREATE",                    // 0x0001
  551     "NT_TRANSACT_IOCTL",                     // 0x0002
  552     "NT_TRANSACT_SET_SECURITY_DESC",         // 0x0003
  553     "NT_TRANSACT_NOTIFY_CHANGE",             // 0x0004
  554     "NT_TRANSACT_RENAME",                    // 0x0005
  555     "NT_TRANSACT_QUERY_SECURITY_DESC"        // 0x0006
  556 };
  557 
  558 /********************************************************************
  559  * Private function prototypes
  560  ********************************************************************/
  561 static inline int DCE2_SmbType(DCE2_SmbSsnData *);
  562 static inline void DCE2_SmbSetValidWordCount(uint8_t, uint8_t, uint8_t);
  563 static inline bool DCE2_SmbIsValidWordCount(uint8_t, uint8_t, uint8_t);
  564 static inline void DCE2_SmbSetValidByteCount(uint8_t, uint8_t, uint16_t, uint16_t);
  565 static inline bool DCE2_SmbIsValidByteCount(uint8_t, uint8_t, uint16_t);
  566 static DCE2_Ret DCE2_NbssHdrChecks(DCE2_SmbSsnData *, const NbssHdr *);
  567 static DCE2_SmbRequestTracker * DCE2_SmbInspect(DCE2_SmbSsnData *, const SmbNtHdr *);
  568 static DCE2_Ret DCE2_SmbHdrChecks(DCE2_SmbSsnData *, const SmbNtHdr *);
  569 static uint32_t DCE2_IgnoreJunkData(const uint8_t *, uint16_t, uint32_t);
  570 static inline DCE2_Ret DCE2_SmbHandleSegmentation(DCE2_Buffer **,
  571         const uint8_t *, uint32_t, uint32_t);
  572 static inline DCE2_Buffer ** DCE2_SmbGetSegBuffer(DCE2_SmbSsnData *);
  573 static inline uint32_t * DCE2_SmbGetIgnorePtr(DCE2_SmbSsnData *);
  574 static inline DCE2_SmbDataState * DCE2_SmbGetDataState(DCE2_SmbSsnData *);
  575 static inline bool DCE2_SmbIsSegBuffer(DCE2_SmbSsnData *, const uint8_t *);
  576 static inline void DCE2_SmbSegAlert(DCE2_SmbSsnData *, DCE2_Event);
  577 static inline bool DCE2_SmbIsRawData(DCE2_SmbSsnData *);
  578 static void DCE2_SmbProcessRawData(DCE2_SmbSsnData *, const uint8_t *, uint32_t);
  579 static DCE2_SmbComInfo * DCE2_SmbCheckCommand(DCE2_SmbSsnData *,
  580         const SmbNtHdr *, const uint8_t, const uint8_t *, uint32_t);
  581 static void DCE2_SmbProcessCommand(DCE2_SmbSsnData *, const SmbNtHdr *, const uint8_t *, uint32_t);
  582 static inline DCE2_Ret DCE2_SmbCheckData(DCE2_SmbSsnData *, const uint8_t *,
  583         const uint8_t *, const uint32_t, const uint16_t, const uint32_t, uint16_t);
  584 static inline DCE2_Ret DCE2_SmbValidateTransactionFields(DCE2_SmbSsnData *, const uint8_t *,
  585         const uint8_t *, const uint32_t, const uint16_t, const uint32_t,
  586         const uint32_t, const uint32_t, const uint32_t, const uint32_t,
  587         const uint32_t, const uint32_t, const uint32_t);
  588 static inline DCE2_Ret DCE2_SmbValidateTransactionSent(DCE2_SmbSsnData *,
  589         uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
  590 static inline DCE2_Ret DCE2_SmbCheckTransDataParams(DCE2_SmbSsnData *,
  591         const uint8_t *, const uint8_t *, const uint32_t, const uint16_t,
  592         const uint32_t, const uint32_t, const uint32_t, const uint32_t);
  593 static inline DCE2_Ret DCE2_SmbCheckTotalCount(DCE2_SmbSsnData *,
  594         const uint32_t, const uint32_t, const uint32_t);
  595 static inline void DCE2_SmbCheckFmtData(DCE2_SmbSsnData *, const uint32_t,
  596         const uint16_t, const uint8_t, const uint16_t, const uint16_t);
  597 static inline DCE2_Ret DCE2_SmbCheckAndXOffset(DCE2_SmbSsnData *, const uint8_t *,
  598         const uint8_t *, const uint32_t);
  599 static inline void DCE2_SmbInvalidShareCheck(DCE2_SmbSsnData *,
  600         const SmbNtHdr *, const uint8_t *, uint32_t);
  601 static DCE2_Ret DCE2_SmbTransactionGetName(const uint8_t *, uint32_t, uint16_t, bool);
  602 static inline bool DCE2_SmbIsTransactionComplete(DCE2_SmbTransactionTracker *);
  603 static DCE2_Ret DCE2_SmbUpdateTransRequest(DCE2_SmbSsnData *, const SmbNtHdr *,
  604         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  605 static DCE2_Ret DCE2_SmbUpdateTransSecondary(DCE2_SmbSsnData *, const SmbNtHdr *,
  606         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  607 static DCE2_Ret DCE2_SmbUpdateTransResponse(DCE2_SmbSsnData *, const SmbNtHdr *,
  608         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  609 static DCE2_Ret DCE2_SmbOpen(DCE2_SmbSsnData *, const SmbNtHdr *,
  610         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  611 static DCE2_Ret DCE2_SmbCreate(DCE2_SmbSsnData *, const SmbNtHdr *,
  612         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  613 static DCE2_Ret DCE2_SmbClose(DCE2_SmbSsnData *, const SmbNtHdr *,
  614         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  615 static DCE2_Ret DCE2_SmbRename(DCE2_SmbSsnData *, const SmbNtHdr *,
  616         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  617 static DCE2_Ret DCE2_SmbRead(DCE2_SmbSsnData *, const SmbNtHdr *,
  618         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  619 static DCE2_Ret DCE2_SmbWrite(DCE2_SmbSsnData *, const SmbNtHdr *,
  620         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  621 static DCE2_Ret DCE2_SmbCreateNew(DCE2_SmbSsnData *, const SmbNtHdr *,
  622         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  623 static DCE2_Ret DCE2_SmbLockAndRead(DCE2_SmbSsnData *, const SmbNtHdr *,
  624         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  625 static DCE2_Ret DCE2_SmbWriteAndUnlock(DCE2_SmbSsnData *, const SmbNtHdr *,
  626         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  627 static DCE2_Ret DCE2_SmbReadRaw(DCE2_SmbSsnData *, const SmbNtHdr *,
  628         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  629 static DCE2_Ret DCE2_SmbWriteRaw(DCE2_SmbSsnData *, const SmbNtHdr *,
  630         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  631 static DCE2_Ret DCE2_SmbWriteComplete(DCE2_SmbSsnData *, const SmbNtHdr *,
  632         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  633 static inline DCE2_Ret DCE2_SmbTransactionReq(DCE2_SmbSsnData *,
  634         DCE2_SmbTransactionTracker *, const uint8_t *, uint32_t,
  635         const uint8_t *, uint32_t);
  636 static DCE2_Ret DCE2_SmbTransaction(DCE2_SmbSsnData *, const SmbNtHdr *,
  637         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  638 static DCE2_Ret DCE2_SmbTransactionSecondary(DCE2_SmbSsnData *, const SmbNtHdr *,
  639         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  640 static DCE2_Ret DCE2_SmbWriteAndClose(DCE2_SmbSsnData *, const SmbNtHdr *,
  641         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  642 static DCE2_Ret DCE2_SmbOpenAndX(DCE2_SmbSsnData *, const SmbNtHdr *,
  643         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  644 static DCE2_Ret DCE2_SmbReadAndX(DCE2_SmbSsnData *, const SmbNtHdr *,
  645         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  646 static DCE2_Ret DCE2_SmbWriteAndX(DCE2_SmbSsnData *, const SmbNtHdr *,
  647         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  648 static DCE2_Ret DCE2_SmbWriteAndXRawRequest(DCE2_SmbSsnData *, const SmbNtHdr *,
  649         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  650 static inline DCE2_Ret DCE2_SmbTrans2Open2Req(DCE2_SmbSsnData *,
  651         const uint8_t *, uint32_t, bool);
  652 static inline DCE2_Ret DCE2_SmbTrans2QueryFileInfoReq(DCE2_SmbSsnData *,
  653         const uint8_t *, uint32_t);
  654 static inline DCE2_Ret DCE2_SmbTrans2SetFileInfoReq(DCE2_SmbSsnData *,
  655         const uint8_t *, uint32_t, const uint8_t *, uint32_t);
  656 static DCE2_Ret DCE2_SmbTransaction2(DCE2_SmbSsnData *, const SmbNtHdr *,
  657         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  658 static DCE2_Ret DCE2_SmbTransaction2Secondary(DCE2_SmbSsnData *, const SmbNtHdr *,
  659         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  660 static DCE2_Ret DCE2_SmbTreeConnect(DCE2_SmbSsnData *, const SmbNtHdr *,
  661         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  662 static DCE2_Ret DCE2_SmbTreeDisconnect(DCE2_SmbSsnData *, const SmbNtHdr *,
  663         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  664 static DCE2_Ret DCE2_SmbNegotiate(DCE2_SmbSsnData *, const SmbNtHdr *,
  665         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  666 static DCE2_Ret DCE2_SmbSessionSetupAndX(DCE2_SmbSsnData *, const SmbNtHdr *,
  667         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  668 static DCE2_Ret DCE2_SmbLogoffAndX(DCE2_SmbSsnData *, const SmbNtHdr *,
  669         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  670 static DCE2_Ret DCE2_SmbTreeConnectAndX(DCE2_SmbSsnData *, const SmbNtHdr *,
  671         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  672 static inline DCE2_Ret DCE2_SmbNtTransactCreateReq(DCE2_SmbSsnData *,
  673         const uint8_t *, uint32_t, bool);
  674 static DCE2_Ret DCE2_SmbNtTransact(DCE2_SmbSsnData *, const SmbNtHdr *,
  675         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  676 static DCE2_Ret DCE2_SmbNtTransactSecondary(DCE2_SmbSsnData *, const SmbNtHdr *,
  677         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  678 static DCE2_Ret DCE2_SmbNtCreateAndX(DCE2_SmbSsnData *, const SmbNtHdr *,
  679         const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
  680 static inline DCE2_Ret DCE2_SmbProcessRequestData(DCE2_SmbSsnData *, const uint16_t,
  681         const uint8_t *, uint32_t, uint64_t);
  682 static inline DCE2_Ret DCE2_SmbProcessResponseData(DCE2_SmbSsnData *,
  683         const uint8_t *, uint32_t);
  684 static void DCE2_SmbProcessFileData(DCE2_SmbSsnData *,
  685         DCE2_SmbFileTracker *, const uint8_t *, uint32_t, bool);
  686 static inline DCE2_SmbRequestTracker * DCE2_SmbNewRequestTracker(DCE2_SmbSsnData *, const SmbNtHdr *);
  687 static inline DCE2_Ret DCE2_SmbBufferTransactionData(DCE2_SmbTransactionTracker *,
  688         const uint8_t *, uint16_t, uint16_t);
  689 static inline DCE2_Ret DCE2_SmbBufferTransactionParameters(DCE2_SmbTransactionTracker *,
  690         const uint8_t *, uint16_t, uint16_t);
  691 static inline DCE2_SmbRequestTracker * DCE2_SmbFindRequestTracker(DCE2_SmbSsnData *,
  692         const SmbNtHdr *);
  693 static inline void DCE2_SmbRemoveRequestTracker(DCE2_SmbSsnData *, DCE2_SmbRequestTracker *);
  694 static void DCE2_SmbInsertUid(DCE2_SmbSsnData *, const uint16_t);
  695 static DCE2_Ret DCE2_SmbFindUid(DCE2_SmbSsnData *, const uint16_t);
  696 static void DCE2_SmbRemoveUid(DCE2_SmbSsnData *ssd, const uint16_t);
  697 static void DCE2_SmbInsertTid(DCE2_SmbSsnData *, const uint16_t, const bool);
  698 static DCE2_Ret DCE2_SmbFindTid(DCE2_SmbSsnData *, const uint16_t);
  699 static bool DCE2_SmbIsTidIPC(DCE2_SmbSsnData *, const uint16_t);
  700 static void DCE2_SmbRemoveTid(DCE2_SmbSsnData *, const uint16_t);
  701 static DCE2_SmbFileTracker * DCE2_SmbNewFileTracker(DCE2_SmbSsnData *,
  702         const uint16_t, const uint16_t, const uint16_t);
  703 static void DCE2_SmbQueueTmpFileTracker(DCE2_SmbSsnData *,
  704         DCE2_SmbRequestTracker *, const uint16_t, const uint16_t);
  705 static inline DCE2_SmbFileTracker * DCE2_SmbGetTmpFileTracker(DCE2_SmbRequestTracker *);
  706 static DCE2_SmbFileTracker * DCE2_SmbDequeueTmpFileTracker(DCE2_SmbSsnData *,
  707         DCE2_SmbRequestTracker *, const uint16_t);
  708 static inline DCE2_SmbFileTracker * DCE2_SmbGetFileTracker(DCE2_SmbSsnData *,
  709         const uint16_t);
  710 static DCE2_SmbFileTracker * DCE2_SmbFindFileTracker(DCE2_SmbSsnData *, const uint16_t,
  711         const uint16_t, const uint16_t);
  712 static DCE2_Ret DCE2_SmbRemoveFileTracker(DCE2_SmbSsnData *, DCE2_SmbFileTracker *);
  713 static inline void DCE2_SmbCleanFileTracker(DCE2_SmbFileTracker *);
  714 static inline void DCE2_SmbCleanTransactionTracker(DCE2_SmbTransactionTracker *);
  715 static inline void DCE2_SmbCleanRequestTracker(DCE2_SmbRequestTracker *);
  716 static int DCE2_SmbUidTidFidCompare(const void *, const void *);
  717 static void DCE2_SmbFileTrackerDataFree(void *);
  718 static void DCE2_SmbRequestTrackerDataFree(void *);
  719 static inline SFSnortPacket * DCE2_SmbGetRpkt(DCE2_SmbSsnData *, const uint8_t **,
  720         uint32_t *, DCE2_RpktType);
  721 static inline void DCE2_SmbReturnRpkt(void);
  722 static inline void DCE2_SmbSetFileName(uint8_t *, uint16_t);
  723 static uint8_t* DCE2_SmbGetString(const uint8_t *, uint32_t, bool, uint16_t *);
  724 static inline void DCE2_Update_Ftracker_from_ReqTracker(DCE2_SmbFileTracker *ftracker, DCE2_SmbRequestTracker *cur_rtracker);
  725 static inline void DCE2_SmbResetFileChunks(DCE2_SmbFileTracker *);
  726 static inline void DCE2_SmbAbortFileAPI(DCE2_SmbSsnData *);
  727 static inline DCE2_SmbRetransmitPending DCE2_SmbFinishFileAPI(DCE2_SmbSsnData *);
  728 static inline void DCE2_SmbSetNewFileAPIFileTracker(DCE2_SmbSsnData *);
  729 static int DCE2_SmbFileOffsetCompare(const void *, const void *);
  730 static void DCE2_SmbFileChunkFree(void *);
  731 static DCE2_Ret DCE2_SmbHandleOutOfOrderFileData(DCE2_SmbSsnData *,
  732         DCE2_SmbFileTracker *, const uint8_t *, uint32_t, bool);
  733 static DCE2_Ret DCE2_SmbFileAPIProcess(DCE2_SmbSsnData *,
  734         DCE2_SmbFileTracker *, const uint8_t *, uint32_t, bool);
  735 static inline void DCE2_SmbRemoveFileTrackerFromRequestTrackers(DCE2_SmbSsnData *,
  736         DCE2_SmbFileTracker *);
  737 #ifdef ACTIVE_RESPONSE
  738 static void DCE2_SmbInjectDeletePdu(DCE2_SmbSsnData *, DCE2_SmbFileTracker *);
  739 static void DCE2_SmbFinishFileBlockVerdict(DCE2_SmbSsnData *);
  740 static File_Verdict DCE2_SmbGetFileVerdict(void *, void *);
  741 #endif
  742 static inline void DCE2_SmbCleanSessionFileTracker(DCE2_SmbSsnData *, DCE2_SmbFileTracker *);
  743 /********************************************************************
  744  * Function: DCE2_SmbType()
  745  *
  746  * Purpose:
  747  *  Since Windows and Samba don't seem to care or even look at the
  748  *  actual flag in the SMB header, make the determination based on
  749  *  whether from client or server.
  750  *
  751  * Arguments:
  752  *  DCE2_SmbSsnData * - session data structure that has the raw
  753  *     packet and packet flags to make determination
  754  *
  755  * Returns:
  756  *  SMB_TYPE__REQUEST if packet is from client
  757  *  SMB_TYPE__RESPONSE if packet is from server
  758  *
  759  ********************************************************************/
  760 static inline int DCE2_SmbType(DCE2_SmbSsnData *ssd)
  761 {
  762     if (DCE2_SsnFromClient(ssd->sd.wire_pkt))
  763         return SMB_TYPE__REQUEST;
  764     else
  765         return SMB_TYPE__RESPONSE;
  766 }
  767 
  768 /********************************************************************
  769  * Function: DCE2_SmbSetValidWordCount()
  770  *
  771  * Purpose:
  772  *  Initializes global data for valid word counts for supported
  773  *  SMB command requests and responses.
  774  *
  775  * Arguments:
  776  *  uint8_t - the SMB command code
  777  *  uint8_t - SMB_TYPE__REQUEST or SMB_TYPE__RESPONSE
  778  *  uint8_t - the valid word count
  779  *
  780  * Returns: None
  781  *
  782  ********************************************************************/
  783 static inline void DCE2_SmbSetValidWordCount(uint8_t com,
  784         uint8_t resp, uint8_t wct)
  785 {
  786     smb_wcts[com][resp][wct/8] |= (1 << (wct % 8));
  787 }
  788 
  789 /********************************************************************
  790  * Function: DCE2_SmbIsValidWordCount()
  791  *
  792  * Purpose:
  793  *  Checks if a word count is valid for a given command request
  794  *  or response.
  795  *
  796  * Arguments:
  797  *  uint8_t - the SMB command code
  798  *  uint8_t - SMB_TYPE__REQUEST or SMB_TYPE__RESPONSE
  799  *  uint8_t - the word count to validate
  800  *
  801  * Returns:
  802  *  bool - true if valid, false if not valid.
  803  *
  804  ********************************************************************/
  805 static inline bool DCE2_SmbIsValidWordCount(uint8_t com,
  806         uint8_t resp, uint8_t wct)
  807 {
  808     return (smb_wcts[com][resp][wct/8] & (1 << (wct % 8))) ? true : false;
  809 }
  810 
  811 /********************************************************************
  812  * Function: DCE2_SmbSetValidByteCount()
  813  *
  814  * Purpose:
  815  *  Initializes global data for valid byte counts as a range for
  816  *  supported SMB command requests and responses.
  817  *  Since a byte count is 2 bytes, a 4 byte type is used to store
  818  *  the range.  The maximum is in the most significant 2 bytes and
  819  *  the minimum in the least significant 2 bytes.
  820  *
  821  * Arguments:
  822  *  uint8_t - the SMB command code
  823  *  uint8_t - SMB_TYPE__REQUEST or SMB_TYPE__RESPONSE
  824  *  uint8_t - the minimum word count that is valid
  825  *  uint8_t - the maximum word count that is valid
  826  *
  827  * Returns: None
  828  *
  829  ********************************************************************/
  830 static inline void DCE2_SmbSetValidByteCount(uint8_t com,
  831         uint8_t resp, uint16_t min, uint16_t max)
  832 {
  833     smb_bccs[com][resp][0] = min;
  834     smb_bccs[com][resp][1] = max;
  835 }
  836 
  837 /********************************************************************
  838  * Function: DCE2_SmbIsValidByteCount()
  839  *
  840  * Purpose:
  841  *  Checks if a byte count is valid for a given command request
  842  *  or response.
  843  *
  844  * Arguments:
  845  *  uint8_t - the SMB command code
  846  *  uint8_t - SMB_TYPE__REQUEST or SMB_TYPE__RESPONSE
  847  *  uint8_t - the byte count to validate
  848  *
  849  * Returns:
  850  *  bool - true if valid, false if not valid.
  851  *
  852  ********************************************************************/
  853 static inline bool DCE2_SmbIsValidByteCount(uint8_t com,
  854         uint8_t resp, uint16_t bcc)
  855 {
  856     return ((bcc < smb_bccs[com][resp][0])
  857             || (bcc > smb_bccs[com][resp][1])) ? false : true;
  858 }
  859 
  860 /********************************************************************
  861  * Function: DCE2_SmbGetMinByteCount()
  862  *
  863  * Purpose:
  864  *  Returns the minimum byte count for the given command request
  865  *  or response.
  866  *
  867  * Arguments:
  868  *  uint8_t - the SMB command code
  869  *  uint8_t - SMB_TYPE__REQUEST or SMB_TYPE__RESPONSE
  870  *
  871  * Returns:
  872  *  uint16_t - the minimum byte count
  873  *
  874  ********************************************************************/
  875 static inline uint16_t DCE2_SmbGetMinByteCount(uint8_t com, uint8_t resp)
  876 {
  877     return smb_bccs[com][resp][0];
  878 }
  879 
  880 /********************************************************************
  881  * Function: DCE2_SmbInitGlobals()
  882  *
  883  * Purpose:
  884  *  Initializes global variables for SMB processing.
  885  *  Sets up the functions and valid word and byte counts for SMB
  886  *  commands.
  887  *  Sets up AndX chain mappings and valid command chaining for
  888  *  supported policies.
  889  *
  890  * Arguments: None
  891  *
  892  * Returns: None
  893  *
  894  ********************************************************************/
  895 void DCE2_SmbInitGlobals(void)
  896 {
  897     int com;
  898     DCE2_Policy policy;
  899     SmbAndXCom andx;
  900     int i;
  901 
  902     memset(&smb_wcts, 0, sizeof(smb_wcts));
  903     memset(&smb_bccs, 0, sizeof(smb_bccs));
  904 
  905     if (!smb_upload_ret_cb_id)
  906         smb_upload_ret_cb_id = _dpd.streamAPI->register_event_handler(DCE2_Process_Retransmitted);
  907  
  908     // Sets up the function to call for the command and valid word and byte
  909     // counts for the command.  Ensuring valid word and byte counts is very
  910     // important to processing the command as it will assume the command is
  911     // legitimate and can access data that is acutally there.  Note that
  912     // commands with multiple word counts indicate a different command
  913     // structure, however most, if not all just have an extended version
  914     // of the structure for which the extended part isn't used.  If the
  915     // extended part of a command structure needs to be used, be sure to
  916     // check the word count in the command function before accessing data
  917     // in the extended version of the command structure.
  918     for (com = 0; com < SMB_MAX_NUM_COMS; com++)
  919     {
  920         switch (com)
  921         {
  922             case SMB_COM_OPEN:
  923                 smb_com_funcs[com] = DCE2_SmbOpen;
  924 
  925                 smb_deprecated_coms[com] = true;
  926                 smb_unusual_coms[com] = false;
  927 
  928                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 2);
  929                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 7);
  930 
  931                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 2, UINT16_MAX);
  932                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
  933                 break;
  934             case SMB_COM_CREATE:
  935                 smb_com_funcs[com] = DCE2_SmbCreate;
  936 
  937                 smb_deprecated_coms[com] = true;
  938                 smb_unusual_coms[com] = false;
  939 
  940                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 3);
  941                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
  942 
  943                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 2, UINT16_MAX);
  944                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
  945                 break;
  946             case SMB_COM_CLOSE:
  947                 smb_com_funcs[com] = DCE2_SmbClose;
  948 
  949                 smb_deprecated_coms[com] = false;
  950                 smb_unusual_coms[com] = false;
  951 
  952                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 3);
  953                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 0);
  954 
  955                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
  956                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
  957                 break;
  958             case SMB_COM_RENAME:
  959                 smb_com_funcs[com] = DCE2_SmbRename;
  960 
  961                 smb_deprecated_coms[com] = false;
  962                 smb_unusual_coms[com] = false;
  963 
  964                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 1);
  965                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 0);
  966 
  967                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 4, UINT16_MAX);
  968                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
  969                 break;
  970             case SMB_COM_READ:
  971                 smb_com_funcs[com] = DCE2_SmbRead;
  972 
  973                 smb_deprecated_coms[com] = true;
  974                 smb_unusual_coms[com] = false;
  975 
  976                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 5);
  977                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 5);
  978 
  979                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
  980                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 3, UINT16_MAX);
  981                 break;
  982             case SMB_COM_WRITE:
  983                 smb_com_funcs[com] = DCE2_SmbWrite;
  984 
  985                 smb_deprecated_coms[com] = true;
  986                 smb_unusual_coms[com] = false;
  987 
  988                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 5);
  989                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
  990 
  991                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 3, UINT16_MAX);
  992                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
  993                 break;
  994             case SMB_COM_CREATE_NEW:
  995                 smb_com_funcs[com] = DCE2_SmbCreateNew;
  996 
  997                 smb_deprecated_coms[com] = true;
  998                 smb_unusual_coms[com] = false;
  999 
 1000                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 3);
 1001                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
 1002 
 1003                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 2, UINT16_MAX);
 1004                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
 1005                 break;
 1006             case SMB_COM_LOCK_AND_READ:
 1007                 smb_com_funcs[com] = DCE2_SmbLockAndRead;
 1008 
 1009                 smb_deprecated_coms[com] = true;
 1010                 smb_unusual_coms[com] = false;
 1011 
 1012                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 5);
 1013                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 5);
 1014 
 1015                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
 1016                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 3, UINT16_MAX);
 1017                 break;
 1018             case SMB_COM_WRITE_AND_UNLOCK:
 1019                 smb_com_funcs[com] = DCE2_SmbWriteAndUnlock;
 1020 
 1021                 smb_deprecated_coms[com] = true;
 1022                 smb_unusual_coms[com] = false;
 1023 
 1024                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 5);
 1025                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
 1026 
 1027                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 3, UINT16_MAX);
 1028                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
 1029                 break;
 1030             case SMB_COM_READ_RAW:
 1031                 smb_com_funcs[com] = DCE2_SmbReadRaw;
 1032 
 1033                 smb_deprecated_coms[com] = true;
 1034                 smb_unusual_coms[com] = false;
 1035 
 1036                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 8);
 1037                 // With optional OffsetHigh
 1038                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 10);
 1039 
 1040                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
 1041                 // Response is raw data, i.e. without SMB
 1042                 break;
 1043             case SMB_COM_WRITE_RAW:
 1044                 smb_com_funcs[com] = DCE2_SmbWriteRaw;
 1045 
 1046                 smb_deprecated_coms[com] = true;
 1047                 smb_unusual_coms[com] = false;
 1048 
 1049                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 12);
 1050                 // With optional OffsetHigh
 1051                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 14);
 1052                 // Interim server response
 1053                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
 1054 
 1055                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
 1056                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
 1057                 break;
 1058             case SMB_COM_WRITE_COMPLETE:
 1059                 // Final server response to SMB_COM_WRITE_RAW
 1060                 smb_com_funcs[com] = DCE2_SmbWriteComplete;
 1061 
 1062                 smb_deprecated_coms[com] = true;
 1063                 smb_unusual_coms[com] = false;
 1064 
 1065                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
 1066 
 1067                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
 1068                 break;
 1069             case SMB_COM_TRANSACTION:
 1070                 smb_com_funcs[com] = DCE2_SmbTransaction;
 1071 
 1072                 smb_deprecated_coms[com] = false;
 1073                 smb_unusual_coms[com] = false;
 1074 
 1075                 // Word count depends on setup count
 1076                 //for (i = 14; i < 256; i++)
 1077                 //    DCE2_SmbSetValidWordCount(com, SMB_TYPE__REQUEST, i);
 1078                 // In reality, all subcommands of SMB_COM_TRANSACTION requests
 1079                 // have a setup count of 2 words.
 1080                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 16);
 1081 
 1082                 // \PIPE\LANMAN
 1083                 // Not something the preprocessor is looking at as it
 1084                 // doesn't carry DCE/RPC but don't want to false positive
 1085                 // on the preprocessor event.
 1086                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 14);
 1087 
 1088                 // Word count depends on setup count
 1089                 //for (i = 10; i < 256; i++)
 1090                 //    DCE2_SmbSetValidWordCount(com, SMB_TYPE__RESPONSE, i);
 1091                 // In reality, all subcommands of SMB_COM_TRANSACTION responses
 1092                 // have a setup count of 0 words.
 1093                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 10);
 1094 
 1095                 // Interim server response
 1096                 // When client sends an incomplete transaction and needs to
 1097                 // send TransactionSecondary requests to complete request.
 1098                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 0);
 1099 
 1100                 // Exception will be made for Interim responses when
 1101                 // byte count is checked.
 1102                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
 1103                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
 1104                 break;
 1105             case SMB_COM_TRANSACTION_SECONDARY:
 1106                 smb_com_funcs[com] = DCE2_SmbTransactionSecondary;
 1107 
 1108                 smb_deprecated_coms[com] = false;
 1109                 smb_unusual_coms[com] = false;
 1110 
 1111                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 8);
 1112                 // Response is an SMB_COM_TRANSACTION
 1113 
 1114                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
 1115                 break;
 1116             case SMB_COM_WRITE_AND_CLOSE:
 1117                 smb_com_funcs[com] = DCE2_SmbWriteAndClose;
 1118 
 1119                 smb_deprecated_coms[com] = true;
 1120                 smb_unusual_coms[com] = false;
 1121 
 1122                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 6);
 1123                 // For some reason MS-CIFS specifies a version of this command
 1124                 // with 6 extra words (12 bytes) of reserved, i.e. useless data.
 1125                 // Maybe had intentions of extending and defining the data at
 1126                 // some point, but there is no documentation that I could find
 1127                 // that does.
 1128                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 12);
 1129                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
 1130 
 1131                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 1, UINT16_MAX);
 1132                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
 1133                 break;
 1134             case SMB_COM_OPEN_ANDX:
 1135                 smb_com_funcs[com] = DCE2_SmbOpenAndX;
 1136 
 1137                 smb_deprecated_coms[com] = true;
 1138                 smb_unusual_coms[com] = false;
 1139 
 1140                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 15);
 1141                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 15);
 1142                 // Extended response
 1143                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 19);
 1144 
 1145                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 2, UINT16_MAX);
 1146                 // MS-SMB says that Windows 2000, XP and Vista set this to
 1147                 // some arbitrary value that is ignored on receipt.
 1148                 //DCE2_SmbSetValidByteCount(com, SMB_TYPE__RESPONSE, 0, 0);
 1149                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
 1150                 break;
 1151             case SMB_COM_READ_ANDX:
 1152                 smb_com_funcs[com] = DCE2_SmbReadAndX;
 1153 
 1154                 smb_deprecated_coms[com] = false;
 1155                 smb_unusual_coms[com] = false;
 1156 
 1157                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 10);
 1158                 // With optional OffsetHigh
 1159                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 12);
 1160                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 12);
 1161 
 1162                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
 1163                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
 1164                 break;
 1165             case SMB_COM_WRITE_ANDX:
 1166                 smb_com_funcs[com] = DCE2_SmbWriteAndX;
 1167 
 1168                 smb_deprecated_coms[com] = false;
 1169                 smb_unusual_coms[com] = false;
 1170 
 1171                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 12);
 1172                 // With optional OffsetHigh
 1173                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 14);
 1174                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 6);
 1175 
 1176                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 1, UINT16_MAX);
 1177                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
 1178                 break;
 1179             case SMB_COM_TRANSACTION2:
 1180                 smb_com_funcs[com] = DCE2_SmbTransaction2;
 1181 
 1182                 smb_deprecated_coms[com] = false;
 1183                 smb_unusual_coms[com] = false;
 1184 
 1185                 // Word count depends on setup count
 1186                 //for (i = 14; i < 256; i++)
 1187                 //    DCE2_SmbSetValidWordCount(com, SMB_TYPE__REQUEST, i);
 1188                 // In reality, all subcommands of SMB_COM_TRANSACTION2
 1189                 // requests have a setup count of 1 word.
 1190                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 15);
 1191 
 1192                 // Word count depends on setup count
 1193                 //for (i = 10; i < 256; i++)
 1194                 //    DCE2_SmbSetValidWordCount(com, SMB_TYPE__RESPONSE, i);
 1195                 // In reality, all subcommands of SMB_COM_TRANSACTION2
 1196                 // responses have a setup count of 0 or 1 word.
 1197                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 10);
 1198                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 11);
 1199 
 1200                 // Interim server response
 1201                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 0);
 1202 
 1203                 // Exception will be made for Interim responses when
 1204                 // byte count is checked.
 1205                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
 1206                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
 1207                 break;
 1208             case SMB_COM_TRANSACTION2_SECONDARY:
 1209                 smb_com_funcs[com] = DCE2_SmbTransaction2Secondary;
 1210 
 1211                 smb_deprecated_coms[com] = false;
 1212                 smb_unusual_coms[com] = false;
 1213 
 1214                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 9);
 1215                 // Response is an SMB_COM_TRANSACTION2
 1216 
 1217                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
 1218                 break;
 1219             case SMB_COM_TREE_CONNECT:
 1220                 smb_com_funcs[com] = DCE2_SmbTreeConnect;
 1221 
 1222                 smb_deprecated_coms[com] = true;
 1223                 smb_unusual_coms[com] = false;
 1224 
 1225                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 0);
 1226                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 2);
 1227 
 1228                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 6, UINT16_MAX);
 1229                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
 1230                 break;
 1231             case SMB_COM_TREE_DISCONNECT:
 1232                 smb_com_funcs[com] = DCE2_SmbTreeDisconnect;
 1233 
 1234                 smb_deprecated_coms[com] = false;
 1235                 smb_unusual_coms[com] = false;
 1236 
 1237                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 0);
 1238                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 0);
 1239 
 1240                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
 1241                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
 1242                 break;
 1243             case SMB_COM_NEGOTIATE:
 1244                 // Not doing anything with this command right now.
 1245                 smb_com_funcs[com] = DCE2_SmbNegotiate;
 1246 
 1247                 smb_deprecated_coms[com] = false;
 1248                 smb_unusual_coms[com] = false;
 1249 
 1250                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 0);
 1251                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
 1252                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 13);
 1253                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 17);
 1254 
 1255                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 2, UINT16_MAX);
 1256                 // This can vary depending on dialect so just set wide.
 1257                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
 1258                 break;
 1259             case SMB_COM_SESSION_SETUP_ANDX:
 1260                 smb_com_funcs[com] = DCE2_SmbSessionSetupAndX;
 1261 
 1262                 smb_deprecated_coms[com] = false;
 1263                 smb_unusual_coms[com] = false;
 1264 
 1265                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 10);
 1266                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 12);
 1267                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 13);
 1268                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 3);
 1269                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 4);
 1270 
 1271                 // These can vary so just set wide.
 1272                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
 1273                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
 1274                 break;
 1275             case SMB_COM_LOGOFF_ANDX:
 1276                 smb_com_funcs[com] = DCE2_SmbLogoffAndX;
 1277 
 1278                 smb_deprecated_coms[com] = false;
 1279                 smb_unusual_coms[com] = false;
 1280 
 1281                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 2);
 1282                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 2);
 1283                 // Windows responds to a LogoffAndX => SessionSetupAndX with just a
 1284                 // LogoffAndX and with the word count field containing 3, but only
 1285                 // has 2 words
 1286                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 3);
 1287 
 1288                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
 1289                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
 1290                 break;
 1291             case SMB_COM_TREE_CONNECT_ANDX:
 1292                 smb_com_funcs[com] = DCE2_SmbTreeConnectAndX;
 1293 
 1294                 smb_deprecated_coms[com] = false;
 1295                 smb_unusual_coms[com] = false;
 1296 
 1297                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 4);
 1298                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 2);
 1299                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 3);
 1300                 // Extended response
 1301                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 7);
 1302 
 1303                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 3, UINT16_MAX);
 1304                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 2, UINT16_MAX);
 1305                 break;
 1306             case SMB_COM_NT_TRANSACT:
 1307                 smb_com_funcs[com] = DCE2_SmbNtTransact;
 1308 
 1309                 smb_deprecated_coms[com] = false;
 1310                 smb_unusual_coms[com] = false;
 1311 
 1312                 // Word count depends on setup count
 1313                 // In reality, all subcommands of SMB_COM_NT_TRANSACT
 1314                 // requests have a setup count of 0 or 4 words.
 1315                 //for (i = 19; i < 256; i++)
 1316                 //    DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, i);
 1317                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 19);
 1318                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 23);
 1319 
 1320                 // Word count depends on setup count
 1321                 // In reality, all subcommands of SMB_COM_NT_TRANSACT
 1322                 // responses have a setup count of 0 or 1 word.
 1323                 //for (i = 18; i < 256; i++)
 1324                 //    DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, i);
 1325                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 18);
 1326                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 19);
 1327 
 1328                 // Interim server response
 1329                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 0);
 1330 
 1331                 // Exception will be made for Interim responses when
 1332                 // byte count is checked.
 1333                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
 1334                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
 1335                 break;
 1336             case SMB_COM_NT_TRANSACT_SECONDARY:
 1337                 smb_com_funcs[com] = DCE2_SmbNtTransactSecondary;
 1338 
 1339                 smb_deprecated_coms[com] = false;
 1340                 smb_unusual_coms[com] = false;
 1341 
 1342                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 18);
 1343                 // Response is an SMB_COM_NT_TRANSACT
 1344 
 1345                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
 1346                 break;
 1347             case SMB_COM_NT_CREATE_ANDX:
 1348                 smb_com_funcs[com] = DCE2_SmbNtCreateAndX;
 1349 
 1350                 smb_deprecated_coms[com] = false;
 1351                 smb_unusual_coms[com] = false;
 1352 
 1353                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 24);
 1354                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 34);
 1355                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 26);
 1356                 // Extended response - though there are actually 50 words
 1357                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 42);
 1358 
 1359                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 2, UINT16_MAX);
 1360                 // MS-SMB indicates that this field should be 0 but may be
 1361                 // sent uninitialized so basically ignore it.
 1362                 //DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
 1363                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
 1364                 break;
 1365             default:
 1366                 smb_com_funcs[com] = NULL;
 1367                 smb_deprecated_coms[com] = false;
 1368                 smb_unusual_coms[com] = false;
 1369                 // Just set to all valid since the specific command won't
 1370                 // be processed.  Don't want to false positive on these.
 1371                 for (i = 0; i < 256; i++)
 1372                 {
 1373                     DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, (uint8_t)i);
 1374                     DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, (uint8_t)i);
 1375                 }
 1376                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
 1377                 DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
 1378                 break;
 1379         }
 1380     }
 1381 
 1382     // Maps commands for use in quickly determining if a command
 1383     // is chainable and what command it is.
 1384     for (com = 0; com < SMB_MAX_NUM_COMS; com++)
 1385     {
 1386         switch (com)
 1387         {
 1388             case SMB_COM_SESSION_SETUP_ANDX:
 1389                 smb_chain_map[com] = SMB_ANDX_COM__SESSION_SETUP_ANDX;
 1390                 break;
 1391             case SMB_COM_LOGOFF_ANDX:
 1392                 smb_chain_map[com] = SMB_ANDX_COM__LOGOFF_ANDX;
 1393                 break;
 1394             case SMB_COM_TREE_CONNECT_ANDX:
 1395                 smb_chain_map[com] = SMB_ANDX_COM__TREE_CONNECT_ANDX;
 1396                 break;
 1397             case SMB_COM_OPEN_ANDX:
 1398                 smb_chain_map[com] = SMB_ANDX_COM__OPEN_ANDX;
 1399                 break;
 1400             case SMB_COM_NT_CREATE_ANDX:
 1401                 smb_chain_map[com] = SMB_ANDX_COM__NT_CREATE_ANDX;
 1402                 break;
 1403             case SMB_COM_WRITE_ANDX:
 1404                 smb_chain_map[com] = SMB_ANDX_COM__WRITE_ANDX;
 1405                 break;
 1406             case SMB_COM_READ_ANDX:
 1407                 smb_chain_map[com] = SMB_ANDX_COM__READ_ANDX;
 1408                 break;
 1409             default:
 1410                 smb_chain_map[com] = SMB_ANDX_COM__NONE;
 1411                 break;
 1412         }
 1413     }
 1414 
 1415     // Sets up the valid command chaining combinations per policy
 1416     for (policy = DCE2_POLICY__NONE; policy < DCE2_POLICY__MAX; policy++)
 1417     {
 1418         for (andx = SMB_ANDX_COM__NONE; andx < SMB_ANDX_COM__MAX; andx++)
 1419         {
 1420             /* com is the chained command or com2 */
 1421             for (com = 0; com < SMB_MAX_NUM_COMS; com++)
 1422             {
 1423                 DCE2_SmbComFunc com_func = NULL;
 1424 
 1425                 switch (policy)
 1426                 {
 1427                     case DCE2_POLICY__WIN2000:
 1428                     case DCE2_POLICY__WINXP:
 1429                     case DCE2_POLICY__WINVISTA:
 1430                     case DCE2_POLICY__WIN2003:
 1431                     case DCE2_POLICY__WIN2008:
 1432                     case DCE2_POLICY__WIN7:
 1433                         switch (andx)
 1434                         {
 1435                             case SMB_ANDX_COM__SESSION_SETUP_ANDX:
 1436                                 switch (com)
 1437                                 {
 1438                                     case SMB_COM_TREE_CONNECT_ANDX:
 1439                                     case SMB_COM_OPEN:
 1440                                     case SMB_COM_OPEN_ANDX:
 1441                                     case SMB_COM_CREATE:
 1442                                     case SMB_COM_CREATE_NEW:
 1443                                         com_func = smb_com_funcs[com];
 1444                                         break;
 1445                                     case SMB_COM_TRANSACTION:
 1446                                         if (policy == DCE2_POLICY__WIN2000)
 1447                                             com_func = smb_com_funcs[com];
 1448                                         break;
 1449                                     default:
 1450                                         break;
 1451                                 }
 1452                                 break;
 1453                             case SMB_ANDX_COM__LOGOFF_ANDX:
 1454                                 switch (com)
 1455                                 {
 1456                                     case SMB_COM_SESSION_SETUP_ANDX:
 1457                                     case SMB_COM_TREE_CONNECT_ANDX:   // Only for responses
 1458                                         com_func = smb_com_funcs[com];
 1459                                         break;
 1460                                     default:
 1461                                         break;
 1462                                 }
 1463                                 break;
 1464                             case SMB_ANDX_COM__TREE_CONNECT_ANDX:
 1465                                 switch (com)
 1466                                 {
 1467                                     case SMB_COM_OPEN:
 1468                                     case SMB_COM_CREATE:
 1469                                     case SMB_COM_CREATE_NEW:
 1470                                         com_func = smb_com_funcs[com];
 1471                                         break;
 1472                                     case SMB_COM_TRANSACTION:
 1473                                         if (policy == DCE2_POLICY__WIN2000)
 1474                                             com_func = smb_com_funcs[com];
 1475                                         break;
 1476                                     default:
 1477                                         break;
 1478                                 }
 1479                                 break;
 1480                             case SMB_ANDX_COM__OPEN_ANDX:
 1481                                 break;
 1482                             case SMB_ANDX_COM__NT_CREATE_ANDX:
 1483                                 switch (com)
 1484                                 {
 1485                                     case SMB_COM_READ_ANDX:  // Only for normal files
 1486                                         com_func = smb_com_funcs[com];
 1487                                         break;
 1488                                     default:
 1489                                         break;
 1490                                 }
 1491                                 break;
 1492                             case SMB_ANDX_COM__WRITE_ANDX:
 1493                                 switch (com)
 1494                                 {
 1495                                     case SMB_COM_CLOSE:
 1496                                     case SMB_COM_WRITE_ANDX:
 1497                                     case SMB_COM_READ:
 1498                                     case SMB_COM_READ_ANDX:
 1499                                         com_func = smb_com_funcs[com];
 1500                                         break;
 1501                                     default:
 1502                                         break;
 1503                                 }
 1504                                 break;
 1505                             case SMB_ANDX_COM__READ_ANDX:
 1506                                 break;
 1507                             default:
 1508                                 break;
 1509                         }
 1510                         break;
 1511                     case DCE2_POLICY__SAMBA:
 1512                     case DCE2_POLICY__SAMBA_3_0_37:
 1513                     case DCE2_POLICY__SAMBA_3_0_22:
 1514                     case DCE2_POLICY__SAMBA_3_0_20:
 1515                         switch (andx)
 1516                         {
 1517                             case SMB_ANDX_COM__SESSION_SETUP_ANDX:
 1518                                 switch (com)
 1519                                 {
 1520                                     case SMB_COM_LOGOFF_ANDX:
 1521                                     case SMB_COM_TREE_CONNECT:
 1522                                     case SMB_COM_TREE_CONNECT_ANDX:
 1523                                     case SMB_COM_TREE_DISCONNECT:
 1524                                     case SMB_COM_OPEN_ANDX:
 1525                                     case SMB_COM_NT_CREATE_ANDX:
 1526                                     case SMB_COM_CLOSE:
 1527                                     case SMB_COM_READ_ANDX:
 1528                                         com_func = smb_com_funcs[com];
 1529                                         break;
 1530                                     case SMB_COM_WRITE:
 1531                                         if ((policy == DCE2_POLICY__SAMBA_3_0_22)
 1532                                                 || (policy == DCE2_POLICY__SAMBA_3_0_20))
 1533                                             com_func = smb_com_funcs[com];
 1534                                         break;
 1535                                     default:
 1536                                         break;
 1537                                 }
 1538                                 break;
 1539                             case SMB_ANDX_COM__LOGOFF_ANDX:
 1540                                 switch (com)
 1541                                 {
 1542                                     case SMB_COM_SESSION_SETUP_ANDX:
 1543                                     case SMB_COM_TREE_DISCONNECT:
 1544                                         com_func = smb_com_funcs[com];
 1545                                         break;
 1546                                     default:
 1547                                         break;
 1548                                 }
 1549                                 break;
 1550                             case SMB_ANDX_COM__TREE_CONNECT_ANDX:
 1551                                 switch (com)
 1552                                 {
 1553                                     case SMB_COM_SESSION_SETUP_ANDX:
 1554                                     case SMB_COM_LOGOFF_ANDX:
 1555                                     case SMB_COM_TREE_DISCONNECT:
 1556                                     case SMB_COM_OPEN_ANDX:
 1557                                     case SMB_COM_NT_CREATE_ANDX:
 1558                                     case SMB_COM_CLOSE:
 1559                                     case SMB_COM_WRITE:
 1560                                     case SMB_COM_READ_ANDX:
 1561                                         com_func = smb_com_funcs[com];
 1562                                         break;
 1563                                     default:
 1564                                         break;
 1565                                 }
 1566                                 break;
 1567                             case SMB_ANDX_COM__OPEN_ANDX:
 1568                                 switch (com)
 1569                                 {
 1570                                     case SMB_COM_SESSION_SETUP_ANDX:
 1571                                     case SMB_COM_LOGOFF_ANDX:
 1572                                     case SMB_COM_TREE_CONNECT:
 1573                                     case SMB_COM_TREE_CONNECT_ANDX:
 1574                                     case SMB_COM_TREE_DISCONNECT:
 1575                                     case SMB_COM_OPEN_ANDX:
 1576                                     case SMB_COM_NT_CREATE_ANDX:
 1577                                     case SMB_COM_CLOSE:
 1578                                     case SMB_COM_WRITE:
 1579                                     case SMB_COM_READ_ANDX:
 1580                                         com_func = smb_com_funcs[com];
 1581                                         break;
 1582                                     default:
 1583                                         break;
 1584                                 }
 1585                                 break;
 1586                             case SMB_ANDX_COM__NT_CREATE_ANDX:
 1587                                 switch (com)
 1588                                 {
 1589                                     case SMB_COM_SESSION_SETUP_ANDX:
 1590                                     case SMB_COM_TREE_CONNECT:
 1591                                     case SMB_COM_TREE_CONNECT_ANDX:
 1592                                     case SMB_COM_OPEN_ANDX:
 1593                                     case SMB_COM_NT_CREATE_ANDX:
 1594                                     case SMB_COM_WRITE:
 1595                                     case SMB_COM_READ_ANDX:
 1596                                         com_func = smb_com_funcs[com];
 1597                                         break;
 1598                                     case SMB_COM_LOGOFF_ANDX:
 1599                                     case SMB_COM_TREE_DISCONNECT:
 1600                                     case SMB_COM_CLOSE:
 1601                                         if ((policy == DCE2_POLICY__SAMBA)
 1602                                                 || (policy == DCE2_POLICY__SAMBA_3_0_37))
 1603                                             com_func = smb_com_funcs[com];
 1604                                         break;
 1605                                     default:
 1606                                         break;
 1607                                 }
 1608                                 break;
 1609                             case SMB_ANDX_COM__WRITE_ANDX:
 1610                                 switch (com)
 1611                                 {
 1612                                     case SMB_COM_SESSION_SETUP_ANDX:
 1613                                     case SMB_COM_LOGOFF_ANDX:
 1614                                     case SMB_COM_TREE_CONNECT:
 1615                                     case SMB_COM_TREE_CONNECT_ANDX:
 1616                                     case SMB_COM_OPEN_ANDX:
 1617                                     case SMB_COM_NT_CREATE_ANDX:
 1618                                     case SMB_COM_CLOSE:
 1619                                     case SMB_COM_WRITE:
 1620                                     case SMB_COM_READ_ANDX:
 1621                                     case SMB_COM_WRITE_ANDX:
 1622                                         com_func = smb_com_funcs[com];
 1623                                         break;
 1624                                     default:
 1625                                         break;
 1626                                 }
 1627                                 break;
 1628                             case SMB_ANDX_COM__READ_ANDX:
 1629                                 switch (com)
 1630                                 {
 1631                                     case SMB_COM_SESSION_SETUP_ANDX:
 1632                                     case SMB_COM_WRITE:
 1633                                         com_func = smb_com_funcs[com];
 1634                                         break;
 1635                                     case SMB_COM_LOGOFF_ANDX:
 1636                                     case SMB_COM_TREE_CONNECT:
 1637                                     case SMB_COM_TREE_CONNECT_ANDX:
 1638                                     case SMB_COM_TREE_DISCONNECT:
 1639                                     case SMB_COM_OPEN_ANDX:
 1640                                     case SMB_COM_NT_CREATE_ANDX:
 1641                                     case SMB_COM_CLOSE:
 1642                                     case SMB_COM_READ_ANDX:
 1643                                         if ((policy == DCE2_POLICY__SAMBA)
 1644                                                 || (policy == DCE2_POLICY__SAMBA_3_0_37))
 1645                                             com_func = smb_com_funcs[com];
 1646                                         break;
 1647                                     default:
 1648                                         break;
 1649                                 }
 1650                                 break;
 1651                             default:
 1652                                 break;
 1653                         }
 1654                         break;
 1655                     default:
 1656                         break;
 1657                 }
 1658 
 1659                 smb_chain_funcs[policy][andx][com] = com_func;
 1660             }
 1661         }
 1662     }
 1663 }
 1664 
 1665 /********************************************************************
 1666  * Function: DCE2_SmbInitRdata()
 1667  *
 1668  * Purpose:
 1669  *  Initializes the reassembled packet structure for an SMB
 1670  *  reassembled packet.  Uses WriteAndX and ReadAndX.
 1671  *  TODO Use command that was used when reassembly occurred.
 1672  *  One issue with this is that multiple different write/read
 1673  *  commands can be used to write/read the full DCE/RPC
 1674  *  request/response.
 1675  *
 1676  * Arguments:
 1677  *  uint8_t * - pointer to the start of the NetBIOS header where
 1678  *              data initialization should start.
 1679  *  int dir   - FLAG_FROM_CLIENT or FLAG_FROM_SERVER
 1680  *
 1681  * Returns: None
 1682  *
 1683  ********************************************************************/
 1684 void DCE2_SmbInitRdata(uint8_t *nb_ptr, int dir)
 1685 {
 1686     NbssHdr *nb_hdr = (NbssHdr *)nb_ptr;
 1687     SmbNtHdr *smb_hdr = (SmbNtHdr *)((uint8_t *)nb_hdr + sizeof(NbssHdr));
 1688 
 1689     nb_hdr->type = NBSS_SESSION_TYPE__MESSAGE;
 1690     memcpy((void *)smb_hdr->smb_idf, (void *)"\xffSMB", sizeof(smb_hdr->smb_idf));
 1691 
 1692     if (dir == FLAG_FROM_CLIENT)
 1693     {
 1694         SmbWriteAndXReq *writex =
 1695             (SmbWriteAndXReq *)((uint8_t *)smb_hdr + sizeof(SmbNtHdr));
 1696         uint16_t offset = sizeof(SmbNtHdr) + sizeof(SmbWriteAndXReq);
 1697 
 1698         smb_hdr->smb_com = SMB_COM_WRITE_ANDX;
 1699         smb_hdr->smb_flg = 0x00;
 1700 
 1701         writex->smb_wct = 12;
 1702         writex->smb_com2 = SMB_COM_NO_ANDX_COMMAND;
 1703         writex->smb_doff = SmbHtons(&offset);
 1704     }
 1705     else
 1706     {
 1707         SmbReadAndXResp *readx =
 1708             (SmbReadAndXResp *)((uint8_t *)smb_hdr + sizeof(SmbNtHdr));
 1709         uint16_t offset = sizeof(SmbNtHdr) + sizeof(SmbReadAndXResp);
 1710 
 1711         smb_hdr->smb_com = SMB_COM_READ_ANDX;
 1712         smb_hdr->smb_flg = 0x80;
 1713 
 1714         readx->smb_wct = 12;
 1715         readx->smb_com2 = SMB_COM_NO_ANDX_COMMAND;
 1716         readx->smb_doff = SmbHtons(&offset);
 1717     }
 1718 }
 1719 
 1720 /********************************************************************
 1721  * Function: DCE2_SmbSetRdata()
 1722  *
 1723  * Purpose:
 1724  *  When a reassembled packet is needed this function is called to
 1725  *  fill in appropriate fields to make the reassembled packet look
 1726  *  correct from an SMB standpoint.
 1727  *
 1728  * Arguments:
 1729  *  DCE2_SmbSsnData * - the session data structure.
 1730  *  uint8_t * - pointer to the start of the NetBIOS header where
 1731  *              data initialization should start.
 1732  *  uint16_t  - the length of the connection-oriented DCE/RPC data.
 1733  *
 1734  * Returns: None
 1735  *
 1736  ********************************************************************/
 1737 void DCE2_SmbSetRdata(DCE2_SmbSsnData *ssd, uint8_t *nb_ptr, uint16_t co_len)
 1738 {
 1739     NbssHdr *nb_hdr = (NbssHdr *)nb_ptr;
 1740     SmbNtHdr *smb_hdr = (SmbNtHdr *)((uint8_t *)nb_hdr + sizeof(NbssHdr));
 1741     uint16_t uid = (ssd->cur_rtracker == NULL) ? 0 : ssd->cur_rtracker->uid;
 1742     uint16_t tid = (ssd->cur_rtracker == NULL) ? 0 : ssd->cur_rtracker->tid;
 1743     DCE2_SmbFileTracker *ftracker = (ssd->cur_rtracker == NULL) ? NULL : ssd->cur_rtracker->ftracker;
 1744 
 1745     smb_hdr->smb_uid = SmbHtons((const uint16_t *)&uid);
 1746     smb_hdr->smb_tid = SmbHtons((const uint16_t *)&tid);
 1747 
 1748     if (DCE2_SsnFromClient(ssd->sd.wire_pkt))
 1749     {
 1750         SmbWriteAndXReq *writex =
 1751             (SmbWriteAndXReq *)((uint8_t *)smb_hdr + sizeof(SmbNtHdr));
 1752         uint32_t nb_len = sizeof(SmbNtHdr) + sizeof(SmbWriteAndXReq) + co_len;
 1753 
 1754         /* The data will get truncated anyway since we can only fit
 1755          * 64K in the reassembly buffer */
 1756         if (nb_len > UINT16_MAX)
 1757             nb_len = UINT16_MAX;
 1758 
 1759         nb_hdr->length = htons((uint16_t)nb_len);
 1760 
 1761         if ((ftracker != NULL) && (ftracker->fid_v1 > 0))
 1762         {
 1763             uint16_t fid = (uint16_t)ftracker->fid_v1;
 1764             writex->smb_fid = SmbHtons(&fid);
 1765         }
 1766         else
 1767         {
 1768             writex->smb_fid = 0;
 1769         }
 1770 
 1771         writex->smb_countleft = SmbHtons(&co_len);
 1772         writex->smb_dsize = SmbHtons(&co_len);
 1773         writex->smb_bcc = SmbHtons(&co_len);
 1774     }
 1775     else
 1776     {
 1777         SmbReadAndXResp *readx =
 1778             (SmbReadAndXResp *)((uint8_t *)smb_hdr + sizeof(SmbNtHdr));
 1779         uint32_t nb_len = sizeof(SmbNtHdr) + sizeof(SmbReadAndXResp) + co_len;
 1780 
 1781         /* The data will get truncated anyway since we can only fit
 1782          * 64K in the reassembly buffer */
 1783         if (nb_len > UINT16_MAX)
 1784             nb_len = UINT16_MAX;
 1785 
 1786         nb_hdr->length = htons((uint16_t)nb_len);
 1787 
 1788         readx->smb_remaining = SmbHtons(&co_len);
 1789         readx->smb_dsize = SmbHtons(&co_len);
 1790         readx->smb_bcc = SmbHtons(&co_len);
 1791     }
 1792 }
 1793 
 1794 /********************************************************************
 1795  * Function: DCE2_SmbSsnInit()
 1796  *
 1797  * Purpose:
 1798  *  Allocates and initializes a new session data structure.
 1799  *
 1800  * Arguments: None
 1801  *
 1802  * Returns:
 1803  *  DCE2_SmbSsnData * - a new initialized session data structure.
 1804  *
 1805  ********************************************************************/
 1806 DCE2_SmbSsnData * DCE2_SmbSsnInit(SFSnortPacket *p)
 1807 {
 1808     DCE2_SmbSsnData *ssd =
 1809         (DCE2_SmbSsnData *)DCE2_Alloc(sizeof(DCE2_SmbSsnData), DCE2_MEM_TYPE__SMB_SSN);
 1810 
 1811     if (ssd == NULL)
 1812         return NULL;
 1813 
 1814     ssd->dialect_index = DCE2_SENTINEL;
 1815     ssd->max_outstanding_requests = 10;  // Until Negotiate/SessionSetupAndX 
 1816     ssd->cli_data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
 1817     ssd->srv_data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
 1818     ssd->pdu_state = DCE2_SMB_PDU_STATE__COMMAND;
 1819 
 1820     ssd->uid = DCE2_SENTINEL;
 1821     ssd->tid = DCE2_SENTINEL;
 1822     ssd->ftracker.fid_v1 = DCE2_SENTINEL;
 1823     ssd->rtracker.mid = DCE2_SENTINEL;
 1824     ssd->smbfound = false;
 1825     ssd->max_file_depth = _dpd.fileAPI->get_max_file_depth(_dpd.getCurrentSnortConfig(), false);
 1826     ssd->smbretransmit = false;
 1827 
 1828     DCE2_ResetRopts(&ssd->sd.ropts);
 1829 
 1830     dce2_stats.smb_sessions++;
 1831 
 1832     return ssd;
 1833 }
 1834 
 1835 /********************************************************************
 1836  * Function: DCE2_NbssHdrChecks()
 1837  *
 1838  * Purpose:
 1839  *  Does validation of the NetBIOS header.  SMB will only run over
 1840  *  the Session Message type.  On port 139, there is always an
 1841  *  initial Session Request / Session Positive/Negative response
 1842  *  followed by the normal SMB conversation, i.e. Negotiate,
 1843  *  SessionSetupAndX, etc.
 1844  *  Side effects are potential alerts for anomolous behavior.
 1845  *
 1846  * Arguments:
 1847  *  DCE2_SmbSsnData * - the session data structure.
 1848  *  const NbssHdr *   - pointer to the NetBIOS Session Service
 1849  *                      header structure.  Size is already validated.
 1850  *
 1851  * Returns:
 1852  *  DCE2_Ret  -  DCE2_RET__SUCCESS if all goes well and processing
 1853  *               should continue.
 1854  *               DCE2_RET__IGNORE if it's not something we need to
 1855  *               look at.
 1856  *               DCE2_RET__ERROR if an invalid NetBIOS Session
 1857  *               Service type is found.
 1858  *
 1859  ********************************************************************/
 1860 static DCE2_Ret DCE2_NbssHdrChecks(DCE2_SmbSsnData *ssd, const NbssHdr *nb_hdr)
 1861 {
 1862     const SFSnortPacket *p = ssd->sd.wire_pkt;
 1863     bool is_seg_buf = DCE2_SmbIsSegBuffer(ssd, (uint8_t *)nb_hdr);
 1864 
 1865     DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "NetBIOS Session Service type: "));
 1866 
 1867     switch (NbssType(nb_hdr))
 1868     {
 1869         case NBSS_SESSION_TYPE__MESSAGE:
 1870             /* Only want to look at session messages */
 1871             DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Session Message\n"));
 1872 
 1873             if (!DCE2_SmbIsRawData(ssd))
 1874             {
 1875                 uint32_t nb_len = NbssLen(nb_hdr);
 1876 
 1877                 if (nb_len == 0)
 1878                     return DCE2_RET__IGNORE;
 1879 
 1880                 if (nb_len < sizeof(SmbNtHdr))
 1881                 {
 1882                     DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "NetBIOS SS len(%u) < SMB header len(%u).\n",
 1883                                 sizeof(SmbNtHdr), sizeof(NbssHdr) + nb_len));
 1884 
 1885                     if (is_seg_buf)
 1886                         DCE2_SmbSegAlert(ssd, DCE2_EVENT__SMB_NB_LT_SMBHDR);
 1887                     else
 1888                         DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_NB_LT_SMBHDR, nb_len, sizeof(SmbNtHdr));
 1889 
 1890                     return DCE2_RET__IGNORE;
 1891                 }
 1892             }
 1893 
 1894             return DCE2_RET__SUCCESS;
 1895 
 1896         case NBSS_SESSION_TYPE__REQUEST:
 1897             DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Session Request\n"));
 1898             if (DCE2_SsnFromServer(p))
 1899             {
 1900                 if (is_seg_buf)
 1901                     DCE2_SmbSegAlert(ssd, DCE2_EVENT__SMB_BAD_NBSS_TYPE);
 1902                 else
 1903                     DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BAD_NBSS_TYPE);
 1904             }
 1905 
 1906             break;
 1907 
 1908         case NBSS_SESSION_TYPE__POS_RESPONSE:
 1909         case NBSS_SESSION_TYPE__NEG_RESPONSE:
 1910         case NBSS_SESSION_TYPE__RETARGET_RESPONSE:
 1911             DCE2_DEBUG_CODE(DCE2_DEBUG__SMB,
 1912                     if (NbssType(nb_hdr) == NBSS_SESSION_TYPE__POS_RESPONSE)
 1913                     printf("Positive Session Response\n");
 1914                     else if (NbssType(nb_hdr) == NBSS_SESSION_TYPE__NEG_RESPONSE)
 1915                     printf("Negative Session Response\n");
 1916                     else printf("Session Retarget Response\n"););
 1917             if (DCE2_SsnFromClient(p))
 1918             {
 1919                 if (is_seg_buf)
 1920                     DCE2_SmbSegAlert(ssd, DCE2_EVENT__SMB_BAD_NBSS_TYPE);
 1921                 else
 1922                     DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BAD_NBSS_TYPE);
 1923             }
 1924 
 1925             break;
 1926 
 1927         case NBSS_SESSION_TYPE__KEEP_ALIVE:
 1928             DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Session Keep Alive\n"));
 1929             break;
 1930 
 1931         default:
 1932             DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB,
 1933                         "Invalid Session Service type: 0x%02X\n", NbssType(nb_hdr)));
 1934 
 1935             if (is_seg_buf)
 1936                 DCE2_SmbSegAlert(ssd, DCE2_EVENT__SMB_BAD_NBSS_TYPE);
 1937             else
 1938                 DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BAD_NBSS_TYPE);
 1939 
 1940             return DCE2_RET__ERROR;
 1941     }
 1942 
 1943     return DCE2_RET__IGNORE;
 1944 }
 1945 
 1946 /********************************************************************
 1947  * Function: DCE2_SmbInspect()
 1948  *
 1949  * Purpose:
 1950  *  Determines whether the SMB command is something the preprocessor
 1951  *  needs to inspect.
 1952  *  This function returns a DCE2_SmbRequestTracker which tracks command
 1953  *  requests / responses.
 1954  *
 1955  * Arguments:
 1956  *  DCE2_SmbSsnData * - the session data structure.
 1957  *  const SmbNtHdr *  - pointer to the SMB header.
 1958  *
 1959  * Returns:
 1960  *  DCE2_SmbRequestTracker * - NULL if it's not something we want to or can
 1961  *                     inspect.
 1962  *                     Otherwise an initialized structure if request
 1963  *                     and the found structure if response.
 1964  *
 1965  ********************************************************************/
 1966 static DCE2_SmbRequestTracker * DCE2_SmbInspect(DCE2_SmbSsnData *ssd, const SmbNtHdr *smb_hdr)
 1967 {
 1968     DCE2_Policy policy = DCE2_SsnGetServerPolicy(&ssd->sd);
 1969     DCE2_SmbRequestTracker *rtracker = NULL;
 1970     int smb_com = SmbCom(smb_hdr);
 1971 
 1972     DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "SMB command: %s (0x%02X)\n",
 1973                 smb_com_strings[smb_com], smb_com));
 1974 
 1975     if (smb_com_funcs[smb_com] == NULL)
 1976     {
 1977         DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Command isn't processed "
 1978                     "by preprocessor.\n"));
 1979         return NULL;
 1980     }
 1981 
 1982     // See if this is something we need to inspect
 1983     if (DCE2_SmbType(ssd) == SMB_TYPE__REQUEST)
 1984     {
 1985         switch (smb_com)
 1986         {
 1987             case SMB_COM_NEGOTIATE:
 1988                 if (ssd->ssn_state_flags & DCE2_SMB_SSN_STATE__NEGOTIATED)
 1989                 {
 1990                     DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_MULTIPLE_NEGOTIATIONS);
 1991                     return NULL;
 1992                 }
 1993                 break;
 1994             case SMB_COM_SESSION_SETUP_ANDX:
 1995                 break;
 1996             case SMB_COM_TREE_CONNECT:
 1997             case SMB_COM_TREE_CONNECT_ANDX:
 1998             case SMB_COM_RENAME:
 1999             case SMB_COM_LOGOFF_ANDX:
 2000                 if (DCE2_SmbFindUid(ssd, SmbUid(smb_hdr)) != DCE2_RET__SUCCESS)
 2001                     return NULL;
 2002                 break;
 2003             default:
 2004                 if (DCE2_SmbFindTid(ssd, SmbTid(smb_hdr)) != DCE2_RET__SUCCESS)
 2005                 {
 2006                     DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB,
 2007                                 "Couldn't find Tid (%u)\n", SmbTid(smb_hdr)));
 2008 
 2009                     return NULL;
 2010                 }
 2011 
 2012                 if (DCE2_SmbIsTidIPC(ssd, SmbTid(smb_hdr)))
 2013                 {
 2014                     switch (smb_com)
 2015                     {
 2016                         case SMB_COM_OPEN:
 2017                         case SMB_COM_CREATE:
 2018                         case SMB_COM_CREATE_NEW:
 2019                         case SMB_COM_WRITE_AND_CLOSE:
 2020                         case SMB_COM_WRITE_AND_UNLOCK:
 2021                         case SMB_COM_READ:
 2022                             // Samba doesn't allow these commands under an IPC tree
 2023                             switch (policy)
 2024                             {
 2025                                 case DCE2_POLICY__SAMBA:
 2026                                 case DCE2_POLICY__SAMBA_3_0_37:
 2027                                 case DCE2_POLICY__SAMBA_3_0_22:
 2028                                 case DCE2_POLICY__SAMBA_3_0_20:
 2029                                     DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Samba doesn't "
 2030                                                 "process this command under an IPC tree.\n"));
 2031                                     return NULL;
 2032                                 default:
 2033                                     break;
 2034                             }
 2035                             break;
 2036                         case SMB_COM_READ_RAW:
 2037                         case SMB_COM_WRITE_RAW:
 2038                             // Samba and Windows Vista on don't allow these commands
 2039                             // under an IPC tree, whether or not the raw read/write
 2040                             // flag is set in the Negotiate capabilities.
 2041                             // Windows RSTs the connection and Samba FINs it.
 2042                             switch (policy)
 2043                             {
 2044                                 case DCE2_POLICY__WINVISTA:
 2045                                 case DCE2_POLICY__WIN2008:
 2046                                 case DCE2_POLICY__WIN7:
 2047                                 case DCE2_POLICY__SAMBA:
 2048                                 case DCE2_POLICY__SAMBA_3_0_37:
 2049                                 case DCE2_POLICY__SAMBA_3_0_22:
 2050                                 case DCE2_POLICY__SAMBA_3_0_20:
 2051                                     DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Samba and "
 2052                                                 "Windows Vista on don't process this "
 2053                                                 "command under an IPC tree.\n"));
 2054                                     return NULL;
 2055                                 default:
 2056                                     break;
 2057                             }
 2058                             break;
 2059                         case SMB_COM_LOCK_AND_READ:
 2060                             // The lock will fail so the read won't happen
 2061                             return NULL;
 2062                         default:
 2063                             break;
 2064                     }
 2065                 }
 2066                 else  // Not IPC
 2067                 {
 2068                     switch (smb_com)
 2069                     {
 2070                         // These commands are only used for IPC
 2071                         case SMB_COM_TRANSACTION:
 2072                         case SMB_COM_TRANSACTION_SECONDARY:
 2073                             return NULL;
 2074                         case SMB_COM_READ_RAW:
 2075                         case SMB_COM_WRITE_RAW:
 2076                             // Windows Vista on don't seem to support these
 2077                             // commands, whether or not the raw read/write
 2078                             // flag is set in the Negotiate capabilities.
 2079                             // Windows RSTs the connection.
 2080                             switch (policy)
 2081                             {
 2082                                 case DCE2_POLICY__WINVISTA:
 2083                                 case DCE2_POLICY__WIN2008:
 2084                                 case DCE2_POLICY__WIN7:
 2085                                     DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB,
 2086                                                 "Windows Vista on don't process "
 2087                                                 "this command.\n"));
 2088                                     return NULL;
 2089                                 default:
 2090                                     break;
 2091                             }
 2092                             break;
 2093                         default:
 2094                             break;
 2095                     }
 2096                 }
 2097                 break;
 2098         }
 2099 
 2100         switch (smb_com)
 2101         {
 2102             case SMB_COM_TRANSACTION_SECONDARY:
 2103             case SMB_COM_TRANSACTION2_SECONDARY:
 2104             case SMB_COM_NT_TRANSACT_SECONDARY:
 2105                 rtracker = DCE2_SmbFindRequestTracker(ssd, smb_hdr);
 2106                 break;
 2107             case SMB_COM_TRANSACTION:
 2108             case SMB_COM_TRANSACTION2:
 2109             case SMB_COM_NT_TRANSACT:
 2110                 // If there is already and existing request tracker
 2111                 // and the transaction is not complete, server will
 2112                 // return an error.
 2113                 rtracker = DCE2_SmbFindRequestTracker(ssd, smb_hdr);
 2114                 if (rtracker != NULL)
 2115                     break;
 2116                 // Fall through
 2117             default:
 2118                 rtracker = DCE2_SmbNewRequestTracker(ssd, smb_hdr);
 2119                 break;
 2120         }
 2121     }
 2122     else
 2123     {
 2124         rtracker = DCE2_SmbFindRequestTracker(ssd, smb_hdr);
 2125     }
 2126 
 2127     DCE2_DEBUG_CODE(DCE2_DEBUG__SMB,
 2128             if (rtracker == NULL) printf("Failed to get request tracker.\n"););
 2129 
 2130     return rtracker;
 2131 }
 2132 
 2133 /********************************************************************
 2134  * Function: DCE2_SmbHdrChecks()
 2135  *
 2136  * Checks some relevant fields in the header to make sure they're
 2137  * sane.
 2138  * Side effects are potential alerts for anomolous behavior.
 2139  *
 2140  * Arguments:
 2141  *  DCE2_SmbSsnData *
 2142  *      Pointer to the session data structure.
 2143  *  SmbNtHdr *
 2144  *      Pointer to the header struct layed over the packet data.
 2145  *
 2146  * Returns:
 2147  *  DCE2_Ret
 2148  *      DCE2_RET__IGNORE if we should continue processing, but
 2149  *          ignore data because of the error.
 2150  *      DCE2_RET__SUCCESS if we should continue processing.
 2151  *
 2152  ********************************************************************/
 2153 static DCE2_Ret DCE2_SmbHdrChecks(DCE2_SmbSsnData *ssd, const SmbNtHdr *smb_hdr)
 2154 {
 2155     const SFSnortPacket *p = ssd->sd.wire_pkt;
 2156     bool is_seg_buf = DCE2_SmbIsSegBuffer(ssd, (uint8_t *)smb_hdr);
 2157 
 2158     if ((DCE2_SsnFromServer(p) && (SmbType(smb_hdr) == SMB_TYPE__REQUEST)) ||
 2159             (DCE2_SsnFromClient(p) && (SmbType(smb_hdr) == SMB_TYPE__RESPONSE)))
 2160     {
 2161         if (is_seg_buf)
 2162             DCE2_SmbSegAlert(ssd, DCE2_EVENT__SMB_BAD_TYPE);
 2163         else
 2164             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BAD_TYPE);
 2165 
 2166         // Continue looking at traffic.  Neither Windows nor Samba seem
 2167         // to care, or even look at this flag
 2168     }
 2169 
 2170     if ((SmbId(smb_hdr) != DCE2_SMB_ID)
 2171             && (SmbId(smb_hdr) != DCE2_SMB2_ID))
 2172     {
 2173         if (is_seg_buf)
 2174             DCE2_SmbSegAlert(ssd, DCE2_EVENT__SMB_BAD_ID);
 2175         else
 2176             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BAD_ID);
 2177 
 2178         return DCE2_RET__IGNORE;
 2179     }
 2180 
 2181     return DCE2_RET__SUCCESS;
 2182 }
 2183 
 2184 /********************************************************************
 2185  * Function: DCE2_IgnoreJunkData()
 2186  *
 2187  * Purpose:
 2188  *   An evasion technique can be to put a bunch of junk data before
 2189  *   the actual SMB request and it seems the MS implementation has
 2190  *   no problem with it and seems to just ignore the data.  This
 2191  *   function attempts to move past all the junk to get to the
 2192  *   actual NetBIOS message request.
 2193  *
 2194  * Arguments:
 2195  *   const uint8_t *  - pointer to the current position in the data
 2196  *      being inspected
 2197  *   uint16_t  -  the amount of data left to look at
 2198  *   uint32_t  -  the amount of data to ignore if there doesn't seem
 2199  *      to be any junk data.  Just use the length as if the bad
 2200  *      NetBIOS header was good.
 2201  *
 2202  * Returns:
 2203  *    uint32_t - the amount of bytes to ignore as junk.
 2204  *
 2205  ********************************************************************/
 2206 static uint32_t DCE2_IgnoreJunkData(const uint8_t *data_ptr, uint16_t data_len,
 2207         uint32_t assumed_nb_len)
 2208 {
 2209     const uint8_t *tmp_ptr = data_ptr;
 2210     uint32_t ignore_bytes = 0;
 2211 
 2212     /* Try to find \xffSMB and go back 8 bytes to beginning
 2213      * of what should be a Netbios header with type Session
 2214      * Message (\x00) - do appropriate buffer checks to make
 2215      * sure the index is in bounds. Ignore all intervening
 2216      * bytes */
 2217 
 2218     while ((tmp_ptr + sizeof(uint32_t)) <= (data_ptr + data_len))
 2219     {
 2220         if ((SmbId((SmbNtHdr *)tmp_ptr) == DCE2_SMB_ID)
 2221                 || (SmbId((SmbNtHdr *)tmp_ptr) == DCE2_SMB2_ID))
 2222         {
 2223             break;
 2224         }
 2225 
 2226         tmp_ptr++;
 2227     }
 2228 
 2229     if ((tmp_ptr + sizeof(uint32_t)) > (data_ptr + data_len))
 2230     {
 2231         ignore_bytes = data_len;
 2232     }
 2233     else
 2234     {
 2235         if ((tmp_ptr - sizeof(NbssHdr)) > data_ptr)
 2236             ignore_bytes = (tmp_ptr - data_ptr) - sizeof(NbssHdr);
 2237         else  /* Just ignore whatever the bad NB header had as a length */
 2238             ignore_bytes = assumed_nb_len;
 2239     }
 2240 
 2241     return ignore_bytes;
 2242 }
 2243 
 2244 /********************************************************************
 2245  * Function: DCE2_Smb1Process()
 2246  *
 2247  * Purpose:
 2248  *  This is the main entry point for SMB1 processing.
 2249  *
 2250  * Arguments:
 2251  *  DCE2_SmbSsnData * - the session data structure.
 2252  *
 2253  * Returns: None
 2254  *
 2255  ********************************************************************/
 2256 static inline void DCE2_Smb1Process(DCE2_SmbSsnData *ssd)
 2257 {
 2258     const SFSnortPacket *p = ssd->sd.wire_pkt;
 2259     const uint8_t *data_ptr = p->payload;
 2260     uint16_t data_len = p->payload_size;
 2261     uint32_t *ignore_bytes = DCE2_SmbGetIgnorePtr(ssd);
 2262     DCE2_Buffer **seg_buf = DCE2_SmbGetSegBuffer(ssd);
 2263     DCE2_SmbDataState *data_state = DCE2_SmbGetDataState(ssd);
 2264 
 2265 #ifdef DUMP_BUFFER
 2266     dumpBuffer(DCERPC_SMB1_DUMP,data_ptr,data_len);
 2267 #endif
 2268     DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Processing SMB packet.\n"));
 2269     dce2_stats.smb_pkts++;
 2270 
 2271     /* Have to account for segmentation.  Even though stream will give
 2272      * us larger chunks, we might end up in the middle of something */
 2273     while (data_len > 0)
 2274     {
 2275         // The amount of data needed in a given state to continue processing
 2276         uint32_t data_need;
 2277         NbssHdr *nb_hdr = NULL;
 2278         SmbNtHdr *smb_hdr = NULL;
 2279         uint32_t nb_len;
 2280         const uint8_t *nb_ptr;
 2281         DCE2_SmbRequestTracker *rtracker = NULL;
 2282         DCE2_Ret status;
 2283 
 2284         // We are ignoring an entire PDU or junk data so state should be NETBIOS_HEADER
 2285         // Note that it could be TCP segmented so ignore_bytes could be greater than
 2286         // the amount of data we have
 2287         if (*ignore_bytes)
 2288         {
 2289             DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Ignoring %u bytes\n", *ignore_bytes));
 2290 
 2291             if (data_len <= *ignore_bytes)
 2292             {
 2293                 *ignore_bytes -= data_len;
 2294                 return;
 2295             }
 2296             else
 2297             {
 2298                 /* ignore bytes is less than UINT16_MAX */
 2299                 DCE2_MOVE(data_ptr, data_len, (uint16_t)*ignore_bytes);
 2300                 *ignore_bytes = 0;
 2301             }
 2302         }
 2303 
 2304         switch (*data_state)
 2305         {
 2306             // This state is to verify it's a NetBIOS Session Message packet
 2307             // and to get the length of the SMB PDU.  Also does the SMB junk
 2308             // data check.  If it's not a Session Message the data isn't
 2309             // processed since it won't be carrying SMB.
 2310             case DCE2_SMB_DATA_STATE__NETBIOS_HEADER:
 2311                 data_need = sizeof(NbssHdr) - DCE2_BufferLength(*seg_buf);
 2312 
 2313                 // See if there is enough data to process the NetBIOS header
 2314                 if (data_len < data_need)
 2315                 {
 2316                     DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Data len(%u) < NetBIOS SS header(%u). "
 2317                                 "Queueing data.\n", data_len, data_need));
 2318 
 2319                     if (DCE2_SmbHandleSegmentation(seg_buf, data_ptr,
 2320                                 data_len, sizeof(NbssHdr)) != DCE2_RET__SUCCESS)
 2321                     {
 2322                         DCE2_BufferEmpty(*seg_buf);
 2323                     }
 2324 
 2325                     return;
 2326                 }
 2327 
 2328                 // Set the NetBIOS header structure
 2329                 if (DCE2_BufferIsEmpty(*seg_buf))
 2330                 {
 2331                     nb_hdr = (NbssHdr *)data_ptr;
 2332                 }
 2333                 else
 2334                 {
 2335                     // If data already buffered add the remainder for the
 2336                     // size of the NetBIOS header
 2337                     if (DCE2_SmbHandleSegmentation(seg_buf, data_ptr,
 2338                                 data_need, sizeof(NbssHdr)) != DCE2_RET__SUCCESS)
 2339                     {
 2340                         DCE2_BufferEmpty(*seg_buf);
 2341                         return;
 2342                     }
 2343 
 2344                     nb_hdr = (NbssHdr *)DCE2_BufferData(*seg_buf);
 2345                 }
 2346 
 2347                 nb_len = NbssLen(nb_hdr);
 2348 
 2349                 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB,
 2350                             "NetBIOS PDU length: %u\n", nb_len));
 2351 
 2352                 status = DCE2_NbssHdrChecks(ssd, nb_hdr);
 2353                 if (status != DCE2_RET__SUCCESS)
 2354                 {
 2355                     DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Not a NetBIOS Session Message.\n"));
 2356 
 2357                     if (status == DCE2_RET__IGNORE)
 2358                     {
 2359                         DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Valid NetBIOS header "
 2360                                     "type so ignoring NetBIOS length bytes.\n"));
 2361                         *ignore_bytes = data_need + nb_len;
 2362                     }
 2363                     else  // nb_ret == DCE2_RET__ERROR, i.e. invalid NetBIOS type
 2364                     {
 2365                         DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Not a valid NetBIOS "
 2366                                     "header type so trying to find \\xffSMB to "
 2367                                     "determine how many bytes to ignore.\n"));
 2368 
 2369                         *ignore_bytes = DCE2_IgnoreJunkData(data_ptr, data_len, data_need + nb_len);
 2370                     }
 2371 
 2372                     DCE2_BufferEmpty(*seg_buf);
 2373                     dce2_stats.smb_ignored_bytes += *ignore_bytes;
 2374                     continue;
 2375                 }
 2376 
 2377                 if (!DCE2_BufferIsEmpty(*seg_buf))
 2378                     DCE2_MOVE(data_ptr, data_len, (uint16_t)data_need);
 2379 
 2380                 switch (ssd->pdu_state)
 2381                 {
 2382                     case DCE2_SMB_PDU_STATE__COMMAND:
 2383                         *data_state = DCE2_SMB_DATA_STATE__SMB_HEADER;
 2384                         break;
 2385                     case DCE2_SMB_PDU_STATE__RAW_DATA:
 2386                         *data_state = DCE2_SMB_DATA_STATE__NETBIOS_PDU;
 2387                         // Continue here because of fall through below
 2388                         continue;
 2389                     default:
 2390                         DCE2_Log(DCE2_LOG_TYPE__ERROR, "%s(%d) Invalid SMB PDU "
 2391                                 "state: %d\n", __FILE__, __LINE__, ssd->pdu_state);
 2392                         return;
 2393                 }
 2394 
 2395                 // Fall through for DCE2_SMB_DATA_STATE__SMB_HEADER
 2396                 // This is the normal progression without segmentation.
 2397 
 2398                 // This state is to do validation checks on the SMB header and
 2399                 // more importantly verify it's data that needs to be inspected.
 2400                 // If the TID in the SMB header is not referring to the IPC share
 2401                 // there won't be any DCE/RPC traffic associated with it.
 2402             case DCE2_SMB_DATA_STATE__SMB_HEADER:
 2403                 data_need = (sizeof(NbssHdr) + sizeof(SmbNtHdr)) - DCE2_BufferLength(*seg_buf);
 2404 
 2405                 // See if there is enough data to process the SMB header
 2406                 if (data_len < data_need)
 2407                 {
 2408                     DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Data len (%u) < "
 2409                                 "NetBIOS SS header + SMB header (%u). Queueing data.\n",
 2410                                 data_len, data_need));
 2411 
 2412                     if (DCE2_SmbHandleSegmentation(seg_buf, data_ptr, data_len,
 2413                                 sizeof(NbssHdr) + sizeof(SmbNtHdr)) != DCE2_RET__SUCCESS)
 2414                     {
 2415                         DCE2_BufferEmpty(*seg_buf);
 2416                         *data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
 2417                     }
 2418 
 2419                     return;
 2420                 }
 2421 
 2422                 // Set the SMB header structure
 2423                 if (DCE2_BufferIsEmpty(*seg_buf))
 2424                 {
 2425                     smb_hdr = (SmbNtHdr *)(data_ptr + sizeof(NbssHdr));
 2426                 }
 2427                 else
 2428                 {
 2429                     if (DCE2_SmbHandleSegmentation(seg_buf, data_ptr, data_need,
 2430                                 sizeof(NbssHdr) + sizeof(SmbNtHdr)) != DCE2_RET__SUCCESS)
 2431                     {
 2432                         DCE2_BufferEmpty(*seg_buf);
 2433                         *data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
 2434                         return;
 2435                     }
 2436 
 2437                     smb_hdr = (SmbNtHdr *)(DCE2_BufferData(*seg_buf) + sizeof(NbssHdr));
 2438                 }
 2439 
 2440 
 2441                 if (SmbId(smb_hdr) == DCE2_SMB2_ID)
 2442                 {
 2443                     ssd->sd.flags |= DCE2_SSN_FLAG__SMB2;
 2444                     if (!DCE2_GcIsLegacyMode())
 2445                     {
 2446                         DCE2_Smb2InitFileTracker(&(ssd->ftracker), false, 0);
 2447                         DCE2_Smb2Process(ssd);
 2448                     }
 2449                     return;
 2450                 }
 2451 
 2452                 // See if this is something we need to inspect
 2453                 rtracker = DCE2_SmbInspect(ssd, smb_hdr);
 2454                 if (rtracker == NULL)
 2455                 {
 2456                     DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Not inspecting SMB packet.\n"));
 2457 
 2458                     if (DCE2_BufferIsEmpty(*seg_buf))
 2459                     {
 2460                         *ignore_bytes = sizeof(NbssHdr) + NbssLen((NbssHdr *)data_ptr);
 2461                     }
 2462                     else
 2463                     {
 2464                         *ignore_bytes = (NbssLen((NbssHdr *)DCE2_BufferData(*seg_buf))
 2465                                 - sizeof(SmbNtHdr)) + data_need;
 2466                         DCE2_BufferEmpty(*seg_buf);
 2467                     }
 2468 
 2469                     *data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
 2470 
 2471                     dce2_stats.smb_ignored_bytes += *ignore_bytes;
 2472                     continue;
 2473                 }
 2474 
 2475                 // Check the SMB header for anomolies
 2476                 if (DCE2_SmbHdrChecks(ssd, smb_hdr) != DCE2_RET__SUCCESS)
 2477                 {
 2478                     DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Bad SMB header.\n"));
 2479 
 2480                     if (DCE2_BufferIsEmpty(*seg_buf))
 2481                     {
 2482                         *ignore_bytes = sizeof(NbssHdr) + NbssLen((NbssHdr *)data_ptr);
 2483                     }
 2484                     else
 2485                     {
 2486                         *ignore_bytes = (NbssLen((NbssHdr *)DCE2_BufferData(*seg_buf))
 2487                                 - sizeof(SmbNtHdr)) + data_need;
 2488                         DCE2_BufferEmpty(*seg_buf);
 2489                     }
 2490 
 2491                     *data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
 2492 
 2493                     dce2_stats.smb_ignored_bytes += *ignore_bytes;
 2494                     continue;
 2495                 }
 2496 
 2497                 if (!DCE2_BufferIsEmpty(*seg_buf))
 2498                     DCE2_MOVE(data_ptr, data_len, (uint16_t)data_need);
 2499 
 2500                 *data_state = DCE2_SMB_DATA_STATE__NETBIOS_PDU;
 2501 
 2502                 // Fall through
 2503 
 2504                 // This state ensures that we have the entire PDU before continuing
 2505                 // to process.
 2506             case DCE2_SMB_DATA_STATE__NETBIOS_PDU:
 2507                 if (DCE2_BufferIsEmpty(*seg_buf))
 2508                 {
 2509                     nb_len = NbssLen((NbssHdr *)data_ptr);
 2510                     data_need = sizeof(NbssHdr) + nb_len;
 2511                 }
 2512                 else
 2513                 {
 2514                     nb_len = NbssLen((NbssHdr *)DCE2_BufferData(*seg_buf));
 2515                     data_need = (sizeof(NbssHdr) + nb_len) - DCE2_BufferLength(*seg_buf);
 2516                 }
 2517 
 2518                 /* It's something we want to inspect so make sure we have the full NBSS packet */
 2519                 if (data_len < data_need)
 2520                 {
 2521                     DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Data len(%u) < "
 2522                                 "NetBIOS SS header + NetBIOS len(%u). "
 2523                                 "Queueing data.\n", data_len, sizeof(NbssHdr) + nb_len));
 2524 
 2525                     if (DCE2_SmbHandleSegmentation(seg_buf, data_ptr, data_len,
 2526                                 sizeof(NbssHdr) + nb_len) != DCE2_RET__SUCCESS)
 2527                     {
 2528                         DCE2_BufferEmpty(*seg_buf);
 2529                         *data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
 2530                     }
 2531 
 2532                     return;
 2533                 }
 2534 
 2535                 // data_len >= data_need which means data_need <= UINT16_MAX
 2536                 // So casts below of data_need to uint16_t are okay.
 2537 
 2538                 *data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
 2539 
 2540                 if (DCE2_BufferIsEmpty(*seg_buf))
 2541                 {
 2542                     nb_ptr = data_ptr;
 2543                     nb_len = data_need;
 2544                     DCE2_MOVE(data_ptr, data_len, (uint16_t)data_need);
 2545                 }
 2546                 else
 2547                 {
 2548                     SFSnortPacket *rpkt;
 2549 
 2550                     if (DCE2_SmbHandleSegmentation(seg_buf, data_ptr, data_need,
 2551                                 sizeof(NbssHdr) + nb_len) != DCE2_RET__SUCCESS)
 2552                     {
 2553                         DCE2_BufferEmpty(*seg_buf);
 2554                         DCE2_MOVE(data_ptr, data_len, (uint16_t)data_need);
 2555                         continue;
 2556                     }
 2557 
 2558                     DCE2_MOVE(data_ptr, data_len, (uint16_t)data_need);
 2559 
 2560                     nb_ptr = DCE2_BufferData(*seg_buf);
 2561                     nb_len = DCE2_BufferLength(*seg_buf);
 2562 
 2563                     // Get reassembled packet
 2564                     rpkt = DCE2_SmbGetRpkt(ssd, &nb_ptr, &nb_len,
 2565                             DCE2_RPKT_TYPE__SMB_SEG);
 2566                     if (rpkt == NULL)
 2567                     {
 2568                         DCE2_BufferEmpty(*seg_buf);
 2569                         continue;
 2570                     }
 2571 
 2572                     nb_ptr = DCE2_BufferData(*seg_buf);
 2573                     nb_len = DCE2_BufferLength(*seg_buf);
 2574 
 2575                     DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB,
 2576                                 "Segmentation buffer: len: %u, size: %u\n",
 2577                                 DCE2_BufferLength(*seg_buf), DCE2_BufferSize(*seg_buf)););
 2578 
 2579                     if (DCE2_SsnFromClient(ssd->sd.wire_pkt))
 2580                         dce2_stats.smb_cli_seg_reassembled++;
 2581                     else
 2582                         dce2_stats.smb_srv_seg_reassembled++;
 2583                     DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "TCP reassembled SMB PDU\n"));
 2584                     DCE2_DEBUG_CODE(DCE2_DEBUG__MAIN, DCE2_PrintPktData(rpkt->payload, rpkt->payload_size););
 2585                 }
 2586 
 2587                 switch (ssd->pdu_state)
 2588                 {
 2589                     case DCE2_SMB_PDU_STATE__COMMAND:
 2590                         smb_hdr = (SmbNtHdr *)(nb_ptr + sizeof(NbssHdr));
 2591                         DCE2_MOVE(nb_ptr, nb_len, (sizeof(NbssHdr) + sizeof(SmbNtHdr)));
 2592                         ssd->cur_rtracker = (rtracker != NULL)
 2593                             ? rtracker : DCE2_SmbFindRequestTracker(ssd, smb_hdr);
 2594                         if (ssd->cur_rtracker != NULL)
 2595                             DCE2_SmbProcessCommand(ssd, smb_hdr, nb_ptr, nb_len);
 2596                         break;
 2597                     case DCE2_SMB_PDU_STATE__RAW_DATA:
 2598                         DCE2_MOVE(nb_ptr, nb_len, sizeof(NbssHdr));
 2599                         if (ssd->cur_rtracker != NULL)
 2600                             DCE2_SmbProcessRawData(ssd, nb_ptr, nb_len);
 2601                         // Only one raw read or write
 2602                         ssd->pdu_state = DCE2_SMB_PDU_STATE__COMMAND;
 2603                         break;
 2604                     default:
 2605                         DCE2_Log(DCE2_LOG_TYPE__ERROR, "%s(%d) Invalid SMB PDU "
 2606                                 "state: %d\n", __FILE__, __LINE__, ssd->pdu_state);
 2607                         return;
 2608                 }
 2609 
 2610                 if (!DCE2_BufferIsEmpty(*seg_buf))
 2611                 {
 2612                     DCE2_SmbReturnRpkt();
 2613                     DCE2_BufferDestroy(*seg_buf);
 2614                     *seg_buf = NULL;
 2615                 }
 2616 
 2617                 break;
 2618 
 2619             default:
 2620                 DCE2_Log(DCE2_LOG_TYPE__ERROR, "%s(%d) Invalid SMB Data "
 2621                         "state: %d\n", __FILE__, __LINE__, *data_state);
 2622                 return;
 2623         }
 2624     }
 2625 }
 2626 
 2627 
 2628 /********************************************************************
 2629  * Function: DCE2_SmbProcess()
 2630  *
 2631  * Purpose:
 2632  *  This is the main entry point for SMB processing.
 2633  *
 2634  * Arguments:
 2635  *  DCE2_SmbSsnData * - the session data structure.
 2636  *
 2637  * Returns: None
 2638  *
 2639  ********************************************************************/
 2640 void DCE2_SmbProcess(DCE2_SmbSsnData *ssd)
 2641 {
 2642     DCE2_SmbVersion smb_version;
 2643     const SFSnortPacket *p = ssd->sd.wire_pkt;
 2644 
 2645     if (DCE2_GcIsLegacyMode())
 2646     {
 2647         DCE2_Smb1Process(ssd);
 2648         return;
 2649     }
 2650 
 2651     smb_version = DCE2_Smb2Version(p);
 2652 
 2653     if ((ssd->smbfound == false) && (smb_version != DCE2_SMB_VERISON_NULL))
 2654     {
 2655         _dpd.sessionAPI->disable_preproc_for_session( p->stream_session, PP_HTTPINSPECT);
 2656         DCE2_EnableDetect();
 2657         ssd->smbfound=true;
 2658     }
 2659 
 2660     if (smb_version == DCE2_SMB_VERISON_1)
 2661     {
 2662         if ((ssd->sd.flags & DCE2_SSN_FLAG__SMB2))
 2663         {
 2664             DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "SMB1 packet detected!\n"));
 2665             ssd->sd.flags &= ~DCE2_SSN_FLAG__SMB2;
 2666             DCE2_SmbCleanFileTracker(&(ssd->ftracker));
 2667             ssd->ftracker.is_smb2 = false;
 2668         }
 2669     }
 2670     else if (smb_version == DCE2_SMB_VERISON_2)
 2671     {
 2672         if (!(ssd->sd.flags & DCE2_SSN_FLAG__SMB2))
 2673         {
 2674             DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "SMB2 packet detected!\n"));
 2675             DCE2_SmbCleanFileTracker(&(ssd->ftracker));
 2676             DCE2_Smb2InitFileTracker(&(ssd->ftracker), 0, 0);
 2677             ssd->sd.flags |= DCE2_SSN_FLAG__SMB2;
 2678         }
 2679     }
 2680 
 2681     ssd->max_file_depth = _dpd.fileAPI->get_max_file_depth(_dpd.getCurrentSnortConfig(), false);
 2682     if (ssd->sd.flags & DCE2_SSN_FLAG__SMB2)
 2683         DCE2_Smb2Process(ssd);
 2684     else
 2685         DCE2_Smb1Process(ssd);
 2686 }
 2687 /********************************************************************
 2688  * Function: DCE2_SmbHandleSegmentation()
 2689  *
 2690  * Wrapper around DCE2_HandleSegmentation() to allocate a new
 2691  * buffer object if necessary.
 2692  *
 2693  * Arguments:
 2694  *  DCE2_SmbBuffer **
 2695  *      Pointer to pointer of buffer to add data to.  If NULL
 2696  *      a new buffer will be allocated.
 2697  *  uint8_t *
 2698  *      Pointer to the current data cursor in packet.
 2699  *  uint32_t
 2700  *      Length of data to add to buffer.
 2701  *  uint32_t
 2702  *      The minimum allocation size so that small allocations
 2703  *      aren't consistently done.
 2704  *
 2705  * Returns:
 2706  *  DCE2_Ret
 2707  *      DCE2_RET__ERROR if an error occured.  Nothing can
 2708  *          be trusted.
 2709  *      DCE2_RET__SUCCESS if data was successfully added.
 2710  *
 2711  ********************************************************************/
 2712 static inline DCE2_Ret DCE2_SmbHandleSegmentation(DCE2_Buffer **buf,
 2713         const uint8_t *data_ptr, uint32_t add_len, uint32_t alloc_size)
 2714 {
 2715     DCE2_Ret status;
 2716     PROFILE_VARS;
 2717 
 2718     PREPROC_PROFILE_START(dce2_pstat_smb_seg);
 2719 
 2720     if (buf == NULL)
 2721     {
 2722         PREPROC_PROFILE_END(dce2_pstat_smb_seg);
 2723         return DCE2_RET__ERROR;
 2724     }
 2725 
 2726     if (*buf == NULL)
 2727     {
 2728         /* No initial size or min alloc size */
 2729         *buf = DCE2_BufferNew(alloc_size, alloc_size, DCE2_MEM_TYPE__SMB_SEG);
 2730         if (*buf == NULL)
 2731         {
 2732             PREPROC_PROFILE_END(dce2_pstat_smb_seg);
 2733             return DCE2_RET__ERROR;
 2734         }
 2735     }
 2736 
 2737     status = DCE2_BufferAddData(*buf, data_ptr, add_len,
 2738             DCE2_BufferLength(*buf), DCE2_BUFFER_MIN_ADD_FLAG__IGNORE);
 2739 
 2740     DCE2_DEBUG_CODE(DCE2_DEBUG__SMB,
 2741             if (status != DCE2_RET__SUCCESS)
 2742             printf("Failed to add data to SMB segmentation buffer.\n"););
 2743 
 2744     PREPROC_PROFILE_END(dce2_pstat_smb_seg);
 2745     return status;
 2746 }
 2747 
 2748 /********************************************************************
 2749  * Function: DCE2_SmbGetSegBuffer()
 2750  *
 2751  * Returns the appropriate segmentation buffer.
 2752  *
 2753  * Arguments:
 2754  *  DCE2_SmbSsnData *
 2755  *      Pointer to SMB session data.
 2756  *
 2757  * Returns:
 2758  *  DCE2_SmbSeg *
 2759  *      Pointer to client or server segmenation buffer.
 2760  *
 2761  ********************************************************************/
 2762 static inline DCE2_Buffer ** DCE2_SmbGetSegBuffer(DCE2_SmbSsnData *ssd)
 2763 {
 2764     if (DCE2_SsnFromServer(ssd->sd.wire_pkt))
 2765         return &ssd->srv_seg;
 2766     return &ssd->cli_seg;
 2767 }
 2768 
 2769 /********************************************************************
 2770  * Function: DCE2_SmbGetIgnorePtr()
 2771  *
 2772  * Returns a pointer to the bytes we are ignoring on client or
 2773  * server side.  Bytes are ignored if they are associated with
 2774  * data we are not interested in.
 2775  *
 2776  * Arguments:
 2777  *  DCE2_SmbSsnData * - Pointer to SMB session data.
 2778  *
 2779  * Returns:
 2780  *  uint32_t *
 2781  *      Pointer to the client or server ignore bytes.
 2782  *
 2783  ********************************************************************/
 2784 static inline uint32_t * DCE2_SmbGetIgnorePtr(DCE2_SmbSsnData *ssd)
 2785 {
 2786     if (DCE2_SsnFromServer(ssd->sd.wire_pkt))
 2787         return &ssd->srv_ignore_bytes;
 2788     return &ssd->cli_ignore_bytes;
 2789 }
 2790 
 2791 /********************************************************************
 2792  * Function: DCE2_SmbGetDataState()
 2793  *
 2794  * Returns a pointer to the data state of client or server
 2795  *
 2796  * Arguments:
 2797  *  DCE2_SmbSsnData * - Pointer to SMB session data.
 2798  *
 2799  * Returns:
 2800  *  DCE2_SmbDataState *
 2801  *      Pointer to the client or server data state.
 2802  *
 2803  ********************************************************************/
 2804 static inline DCE2_SmbDataState * DCE2_SmbGetDataState(DCE2_SmbSsnData *ssd)
 2805 {
 2806     if (DCE2_SsnFromServer(ssd->sd.wire_pkt))
 2807         return &ssd->srv_data_state;
 2808     return &ssd->cli_data_state;
 2809 }
 2810 
 2811 /********************************************************************
 2812  * Function: DCE2_SmbIsSegBuffer()
 2813  *
 2814  * Purpose:
 2815  *  Determines whether the pointer passed in lies within one of the
 2816  *  segmentation buffers or not.
 2817  *
 2818  * Arguments:
 2819  *  DCE2_SmbSsnData *
 2820  *      Pointer to SMB session data.
 2821  *
 2822  * Returns:
 2823  *  bool  -  True is the pointer lies within one of the segmentation
 2824  *           buffers.
 2825  *           False if it doesn't.
 2826  *
 2827  ********************************************************************/
 2828 static inline bool DCE2_SmbIsSegBuffer(DCE2_SmbSsnData *ssd, const uint8_t *ptr)
 2829 {
 2830     DCE2_Buffer *seg_buf;
 2831 
 2832     if (DCE2_SsnFromServer(ssd->sd.wire_pkt))
 2833         seg_buf = ssd->srv_seg;
 2834     else
 2835         seg_buf = ssd->cli_seg;
 2836 
 2837     if (DCE2_BufferIsEmpty(seg_buf))
 2838         return false;
 2839 
 2840     /* See if we're looking at a segmentation buffer */
 2841     if ((ptr < DCE2_BufferData(seg_buf)) ||
 2842             (ptr > (DCE2_BufferData(seg_buf) + DCE2_BufferLength(seg_buf))))
 2843     {
 2844         return false;
 2845     }
 2846 
 2847     return true;
 2848 }
 2849 
 2850 /********************************************************************
 2851  * Function: DCE2_SmbSegAlert()
 2852  *
 2853  * Purpose:
 2854  *  To create a reassembled packet using the data in one of the
 2855  *  segmentation buffers in order to generate an alert with the
 2856  *  correct, or more complete data.
 2857  *
 2858  * Arguments:
 2859  *  DCE2_SmbSsnData * - Pointer to SMB session data.
 2860  *  DCE2_Event        - the event code to generate and event for.
 2861  *
 2862  * Returns: None
 2863  *
 2864  ********************************************************************/
 2865 static inline void DCE2_SmbSegAlert(DCE2_SmbSsnData *ssd, DCE2_Event event)
 2866 {
 2867     SFSnortPacket *rpkt;
 2868     DCE2_Buffer *buf;
 2869     uint32_t nb_len = 0;
 2870     const uint8_t *data_ptr;
 2871     uint32_t data_len;
 2872 
 2873     if (DCE2_SsnFromClient(ssd->sd.wire_pkt))
 2874         buf = ssd->cli_seg;
 2875     else
 2876         buf = ssd->srv_seg;
 2877 
 2878     /* This should be called from the desegmentation code. */
 2879     if (DCE2_BufferIsEmpty(buf))
 2880         return;
 2881 
 2882     data_ptr = DCE2_BufferData(buf);
 2883     data_len = DCE2_BufferLength(buf);
 2884 
 2885     rpkt = DCE2_SmbGetRpkt(ssd, &data_ptr, &data_len, DCE2_RPKT_TYPE__SMB_SEG);
 2886     if (rpkt == NULL)
 2887         return;
 2888 
 2889     if (DCE2_BufferLength(buf) >= sizeof(NbssHdr))
 2890         nb_len = NbssLen((NbssHdr *)DCE2_BufferData(buf));
 2891 
 2892     switch (event)
 2893     {
 2894         case DCE2_EVENT__SMB_BAD_NBSS_TYPE:
 2895             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BAD_NBSS_TYPE);
 2896             break;
 2897 
 2898         case DCE2_EVENT__SMB_BAD_TYPE:
 2899             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BAD_TYPE);
 2900             break;
 2901 
 2902         case DCE2_EVENT__SMB_BAD_ID:
 2903             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BAD_ID);
 2904             break;
 2905 
 2906         case DCE2_EVENT__SMB_NB_LT_SMBHDR:
 2907             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_NB_LT_SMBHDR, nb_len, sizeof(SmbNtHdr));
 2908             break;
 2909 
 2910         default:
 2911             break;
 2912     }
 2913 
 2914     DCE2_SmbReturnRpkt();
 2915 }
 2916 
 2917 /********************************************************************
 2918  * Function: DCE2_SmbIsRawData()
 2919  *
 2920  * Purpose:
 2921  *  To determine if the current state is such that a raw read or
 2922  *  write is expected.
 2923  *
 2924  * Arguments:
 2925  *  DCE2_SmbSsnData * - Pointer to SMB session data.
 2926  *
 2927  * Returns:
 2928  *  bool -  True if expecting raw data.
 2929  *          False if not.
 2930  *
 2931  ********************************************************************/
 2932 static inline bool DCE2_SmbIsRawData(DCE2_SmbSsnData *ssd)
 2933 {
 2934     return (ssd->pdu_state == DCE2_SMB_PDU_STATE__RAW_DATA);
 2935 }
 2936 
 2937 /********************************************************************
 2938  * Function:
 2939  *
 2940  * Purpose:
 2941  *
 2942  * Arguments:
 2943  *
 2944  * Returns:
 2945  *
 2946  ********************************************************************/
 2947 static void DCE2_SmbProcessRawData(DCE2_SmbSsnData *ssd, const uint8_t *nb_ptr, uint32_t nb_len)
 2948 {
 2949     DCE2_SmbFileTracker *ftracker = ssd->cur_rtracker->ftracker;
 2950     bool remove_rtracker = false;
 2951 
 2952     if (ftracker == NULL)
 2953     {
 2954         DCE2_SmbRemoveRequestTracker(ssd, ssd->cur_rtracker);
 2955         ssd->cur_rtracker = NULL;
 2956         return;
 2957     }
 2958 
 2959     if (DCE2_SsnFromClient(ssd->sd.wire_pkt))
 2960     {
 2961         DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Raw data: Write Raw\n"));
 2962         DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Request Fid: 0x%04X\n", ftracker->fid_v1));
 2963 
 2964         dce2_stats.smb_com_stats[SMB_TYPE__REQUEST][SMB_COM_WRITE_RAW]++;
 2965 
 2966         if (nb_len > ssd->cur_rtracker->writeraw_remaining)
 2967         {
 2968             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_TDCNT_LT_DSIZE,
 2969                     ssd->cur_rtracker->writeraw_remaining, nb_len);
 2970 
 2971             // If this happens, Windows never responds regardless of
 2972             // WriteThrough flag, so get rid of request tracker
 2973             remove_rtracker = true;
 2974         }
 2975         else if (!ssd->cur_rtracker->writeraw_writethrough)
 2976         {
 2977             // If WriteThrough flag was not set on initial request, a
 2978             // SMB_COM_WRITE_COMPLETE will not be sent so need to get
 2979             // rid of request tracker.
 2980             remove_rtracker = true;
 2981         }
 2982         else
 2983         {
 2984             ssd->cur_rtracker->writeraw_writethrough = false;
 2985             ssd->cur_rtracker->writeraw_remaining = 0;
 2986         }
 2987     }
 2988     else
 2989     {
 2990         DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Raw data: Read Raw\n"));
 2991         DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Response Fid: 0x%04X\n", ftracker->fid_v1));
 2992 
 2993         dce2_stats.smb_com_stats[SMB_TYPE__RESPONSE][SMB_COM_READ_RAW]++;
 2994 
 2995         remove_rtracker = true;
 2996     }
 2997 
 2998     // Only one raw read/write allowed
 2999     ssd->pdu_state = DCE2_SMB_PDU_STATE__COMMAND;
 3000 
 3001     DCE2_SmbSetFileName(ftracker->file_name, ftracker->file_name_len);
 3002 
 3003     if (ftracker->is_ipc)
 3004     {
 3005         // Maximum possible fragment length is 16 bit
 3006         if (nb_len > UINT16_MAX)
 3007             nb_len = UINT16_MAX;
 3008 
 3009         DCE2_CoProcess(&ssd->sd, ftracker->fp_co_tracker, nb_ptr, (uint16_t)nb_len);
 3010     }
 3011     else
 3012     {
 3013         bool upload = DCE2_SsnFromClient(ssd->sd.wire_pkt) ? true : false;
 3014         DCE2_SmbProcessFileData(ssd, ftracker, nb_ptr, nb_len, upload);
 3015     }
 3016 
 3017     if (remove_rtracker)
 3018     {
 3019         DCE2_SmbRemoveRequestTracker(ssd, ssd->cur_rtracker);
 3020         ssd->cur_rtracker = NULL;
 3021     }
 3022 }
 3023 
 3024 /********************************************************************
 3025  * Function: DCE2_SmbCheckCommand()
 3026  *
 3027  * Purpose:
 3028  *  Checks basic validity of an SMB command.
 3029  *
 3030  * Arguments:
 3031  *  DCE2_SmbSsnData * - pointer to session data structure
 3032  *  SmbNtHdr *        - pointer to the SMB header structure
 3033  *  int               - the SMB command code, i.e. SMB_COM_*
 3034  *  uint8_t *         - current pointer to data, i.e. the command
 3035  *  uint32_t          - the remaining length
 3036  *
 3037  * Returns:
 3038  *  DCE2_SmbComInfo *
 3039  *      Populated structure for command processing
 3040  *
 3041  ********************************************************************/
 3042 static DCE2_SmbComInfo * DCE2_SmbCheckCommand(DCE2_SmbSsnData *ssd,
 3043         const SmbNtHdr *smb_hdr, const uint8_t smb_com,
 3044         const uint8_t *nb_ptr, uint32_t nb_len)
 3045 {
 3046     SmbAndXCom andx_com = smb_chain_map[smb_com];
 3047     const SmbCommon *sc = (SmbCommon *)nb_ptr;
 3048     int chk_com_size;
 3049     uint16_t smb_bcc;
 3050     static DCE2_SmbComInfo com_info;
 3051 
 3052     com_info.smb_type = DCE2_SmbType(ssd);
 3053     com_info.cmd_error = DCE2_SMB_COM_ERROR__COMMAND_OK;
 3054     com_info.word_count = 0;
 3055     com_info.smb_com = smb_com;
 3056     com_info.cmd_size = 0;
 3057     com_info.byte_count = 0;
 3058 
 3059     // Check for server error response
 3060     if (com_info.smb_type == SMB_TYPE__RESPONSE)
 3061     {
 3062         const SmbEmptyCom *ec = (SmbEmptyCom *)nb_ptr;
 3063 
 3064         // Verify there is enough data to do checks
 3065         if (nb_len < sizeof(SmbEmptyCom))
 3066         {
 3067             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_NB_LT_COM, nb_len, sizeof(SmbEmptyCom));
 3068             com_info.cmd_error |= DCE2_SMB_COM_ERROR__BAD_LENGTH;
 3069             return &com_info;
 3070         }
 3071 
 3072         // If word and byte counts are zero and there is an error
 3073         // the server didn't accept client request
 3074         if ((SmbEmptyComWct(ec) == 0)
 3075                 && (SmbEmptyComBcc(ec) == 0) && SmbError(smb_hdr))
 3076         {
 3077 
 3078             DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB,
 3079                         "Response error: 0x%08X\n", SmbNtStatus(smb_hdr)));
 3080 
 3081             // If broken pipe, clean up data associated with open named pipe
 3082             if (SmbBrokenPipe(smb_hdr))
 3083             {
 3084                 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB,
 3085                             "  Broken or disconnected pipe.\n"));
 3086 
 3087                 DCE2_SmbRemoveFileTracker(ssd, ssd->cur_rtracker->ftracker);
 3088             }
 3089 
 3090             com_info.cmd_error |= DCE2_SMB_COM_ERROR__STATUS_ERROR;
 3091             return &com_info;
 3092         }
 3093     }
 3094 
 3095     // Set the header size to the minimum size the command can be
 3096     // without the byte count to make sure there is enough data to
 3097     // get the word count.
 3098     if (andx_com == SMB_ANDX_COM__NONE)
 3099         chk_com_size = sizeof(SmbCommon);
 3100     else
 3101         chk_com_size = sizeof(SmbAndXCommon);
 3102 
 3103     // Verify there is enough data to do checks
 3104     if (nb_len < (uint32_t)chk_com_size)
 3105     {
 3106         DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_NB_LT_COM, nb_len, chk_com_size);
 3107         com_info.cmd_error |= DCE2_SMB_COM_ERROR__BAD_LENGTH;
 3108         return &com_info;
 3109     }
 3110 
 3111     com_info.word_count = SmbWct(sc);
 3112 
 3113     // Make sure the word count is a valid one for the command.  If not
 3114     // testing shows an error will be returned.  And command structures
 3115     // won't lie on data correctly and out of bounds data accesses are possible.
 3116     if (!DCE2_SmbIsValidWordCount(smb_com, (uint8_t)com_info.smb_type, com_info.word_count))
 3117     {
 3118         DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BAD_WCT, com_info.word_count);
 3119         com_info.cmd_error |= DCE2_SMB_COM_ERROR__INVALID_WORD_COUNT;
 3120         return &com_info;
 3121     }
 3122 
 3123     // This gets the size of the SMB command from word count through byte count
 3124     // using the advertised value in the word count field.
 3125     com_info.cmd_size = (uint16_t)SMB_COM_SIZE(com_info.word_count);
 3126     if (nb_len < com_info.cmd_size)
 3127     {
 3128         DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_NB_LT_COM, nb_len, com_info.cmd_size);
 3129         com_info.cmd_error |= DCE2_SMB_COM_ERROR__BAD_LENGTH;
 3130         return &com_info;
 3131     }
 3132 
 3133     smb_bcc = SmbBcc(nb_ptr, com_info.cmd_size);
 3134 
 3135     // SMB_COM_NT_CREATE_ANDX is a special case.  Who know what's going
 3136     // on with the word count (see MS-CIFS and MS-SMB).  A 42 word count
 3137     // command seems to actually have 50 words, so who knows where the
 3138     // byte count is.  Just set to zero since it's not needed.
 3139     if ((smb_com == SMB_COM_NT_CREATE_ANDX)
 3140             && (com_info.smb_type == SMB_TYPE__RESPONSE))
 3141         smb_bcc = 0;
 3142 
 3143     // If byte count is deemed invalid, alert but continue processing
 3144     switch (smb_com)
 3145     {
 3146         // Interim responses
 3147         case SMB_COM_TRANSACTION:
 3148         case SMB_COM_TRANSACTION2:
 3149         case SMB_COM_NT_TRANSACT:
 3150             // If word count is 0, byte count must be 0
 3151             if ((com_info.word_count == 0) && (com_info.smb_type == SMB_TYPE__RESPONSE))
 3152             {
 3153                 if (smb_bcc != 0)
 3154                 {
 3155                     DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BAD_BCC, smb_bcc);
 3156                     com_info.cmd_error |= DCE2_SMB_COM_ERROR__INVALID_BYTE_COUNT;
 3157                 }
 3158                 break;
 3159             }
 3160             // Fall through
 3161         default:
 3162             if (!DCE2_SmbIsValidByteCount(smb_com, (uint8_t)com_info.smb_type, smb_bcc))
 3163             {
 3164                 DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BAD_BCC, smb_bcc);
 3165                 com_info.cmd_error |= DCE2_SMB_COM_ERROR__INVALID_BYTE_COUNT;
 3166             }
 3167             break;
 3168     }
 3169 
 3170     // Move just past byte count field which is the end of the command
 3171     DCE2_MOVE(nb_ptr, nb_len, com_info.cmd_size);
 3172 
 3173     // Validate that there is enough data to be able to process the command
 3174     if (nb_len < DCE2_SmbGetMinByteCount(smb_com, (uint8_t)com_info.smb_type))
 3175     {
 3176         DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_NB_LT_BCC, nb_len,
 3177                 DCE2_SmbGetMinByteCount(smb_com, (uint8_t)com_info.smb_type));
 3178         com_info.cmd_error |= DCE2_SMB_COM_ERROR__BAD_LENGTH;
 3179     }
 3180 
 3181     // The byte count seems to be ignored by Windows and current Samba (3.5.4)
 3182     // as long as it is less than the amount of data left.  If more, an error
 3183     // is returned.
 3184     // !!!WARNING!!! the byte count should probably never be used.
 3185     if (smb_bcc > nb_len)
 3186     {
 3187         DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_NB_LT_BCC, nb_len, smb_bcc);
 3188 
 3189         // Large byte count doesn't seem to matter for early Samba
 3190         switch (DCE2_SsnGetPolicy(&ssd->sd))
 3191         {
 3192             case DCE2_POLICY__SAMBA_3_0_20:
 3193             case DCE2_POLICY__SAMBA_3_0_22:
 3194             case DCE2_POLICY__SAMBA_3_0_37:
 3195                 break;
 3196             default:
 3197                 com_info.cmd_error |= DCE2_SMB_COM_ERROR__BAD_LENGTH;
 3198                 break;
 3199         }
 3200     }
 3201     else if ((smb_bcc == 0) && (SmbCom(smb_hdr) == SMB_COM_TRANSACTION)
 3202             && (DCE2_SmbType(ssd) == SMB_TYPE__REQUEST)
 3203             && (DCE2_SsnGetPolicy(&ssd->sd) == DCE2_POLICY__SAMBA))
 3204     {
 3205         // Current Samba errors on a zero byte count Transaction because it
 3206         // uses it to get the Name string and if zero Name will be NULL and
 3207         // it won't process it.
 3208         com_info.cmd_error |= DCE2_SMB_COM_ERROR__BAD_LENGTH;
 3209     }
 3210 
 3211     com_info.byte_count = smb_bcc;
 3212 
 3213     return &com_info;
 3214 }
 3215 
 3216 /********************************************************************
 3217  * Function: DCE2_SmbProcessCommand()
 3218  *
 3219  * Purpose:
 3220  *  This is the main function for handling SMB commands and command
 3221  *  chaining.
 3222  *  It does an initial check of the command to determine validity
 3223  *  and gets basic information about the command.  Then it calls the
 3224  *  specific command function (setup in DCE2_SmbInitGlobals).
 3225  *  If there is command chaining, it will do the chaining foo to
 3226  *  get to the next command.
 3227  *
 3228  * Arguments:
 3229  *  DCE2_SmbSsnData * - pointer to session data structure
 3230  *  SmbNtHdr *        - pointer to the SMB header structure
 3231  *  uint8_t *         - current pointer to data, i.e. the command
 3232  *  uint32_t          - the remaining length
 3233  *
 3234  * Returns: None
 3235  *
 3236  ********************************************************************/
 3237 static void DCE2_SmbProcessCommand(DCE2_SmbSsnData *ssd, const SmbNtHdr *smb_hdr,
 3238         const uint8_t *nb_ptr, uint32_t nb_len)
 3239 {
 3240     DCE2_Ret status = DCE2_RET__ERROR;
 3241     DCE2_Policy policy = DCE2_SsnGetServerPolicy(&ssd->sd);
 3242     uint8_t smb_com = SmbCom(smb_hdr);
 3243     int smb_type = DCE2_SmbType(ssd);
 3244     int num_chained = 0;
 3245     bool sess_chain = false;
 3246     bool tree_chain = false;
 3247     bool open_chain = false;
 3248 
 3249     dce2_stats.smb_com_stats[smb_type][smb_com]++;
 3250 
 3251     while (nb_len > 0)
 3252     {
 3253         SmbAndXCom andx_com = smb_chain_map[smb_com];
 3254         const SmbAndXCommon *andx_ptr = (SmbAndXCommon *)nb_ptr;
 3255         uint8_t smb_com2;
 3256         const uint8_t *off2_ptr;
 3257         DCE2_SmbComInfo *com_info;
 3258 
 3259 #ifdef ACTIVE_RESPONSE
 3260         if (ssd->block_pdus && (smb_type == SMB_TYPE__REQUEST))
 3261         {
 3262             _dpd.inlineDropPacket((void *)ssd->sd.wire_pkt);
 3263             status = DCE2_RET__IGNORE;
 3264             if (*_dpd.pkt_tracer_enabled)
 3265                 _dpd.addPktTrace(VERDICT_REASON_SMB, snprintf(_dpd.trace, _dpd.traceMax,
 3266                     "SMB: gid %u, server message block file drop\n", GENERATOR_DCE2));
 3267             else _dpd.addPktTrace(VERDICT_REASON_SMB, 0);
 3268             break;
 3269         }
 3270 #endif
 3271 
 3272         // Break out if command not supported
 3273         if (smb_com_funcs[smb_com] == NULL)
 3274             break;
 3275 
 3276         if (smb_deprecated_coms[smb_com])
 3277         {
 3278             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_DEPR_COMMAND_USED,
 3279                     smb_com_strings[smb_com]);
 3280         }
 3281 
 3282         if (smb_unusual_coms[smb_com])
 3283         {
 3284             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_UNUSUAL_COMMAND_USED,
 3285                     smb_com_strings[smb_com]);
 3286         }
 3287 
 3288         com_info = DCE2_SmbCheckCommand(ssd, smb_hdr, smb_com, nb_ptr, nb_len);
 3289 
 3290         DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Processing command: %s (0x%02X)\n",
 3291                     smb_com_strings[smb_com], smb_com));
 3292 
 3293         // Note that even if the command shouldn't be processed, some of
 3294         // the command functions need to know and do cleanup or some other
 3295         // processing.
 3296         status = smb_com_funcs[smb_com](ssd, smb_hdr,
 3297                 (const DCE2_SmbComInfo *)com_info, nb_ptr, nb_len);
 3298 
 3299         if (status != DCE2_RET__SUCCESS)
 3300             break;
 3301 
 3302         // This command is not chainable
 3303         if (andx_com == SMB_ANDX_COM__NONE)
 3304             break;
 3305 
 3306         /**********************************************************
 3307          * AndX Chaining
 3308          **********************************************************/
 3309         smb_com2 = SmbAndXCom2(andx_ptr);
 3310         if (smb_com2 == SMB_COM_NO_ANDX_COMMAND)
 3311             break;
 3312 
 3313         dce2_stats.smb_chained_stats[smb_type][andx_com][smb_com2]++;
 3314         DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Chained SMB command: %s\n", smb_com_strings[smb_com2]));
 3315 
 3316         num_chained++;
 3317         if (DCE2_ScSmbMaxChain(ssd->sd.sconfig) &&
 3318                 (num_chained >= DCE2_ScSmbMaxChain(ssd->sd.sconfig)))
 3319         {
 3320             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_EXCESSIVE_CHAINING, DCE2_ScSmbMaxChain(ssd->sd.sconfig));
 3321         }
 3322 
 3323         // Multiple SessionSetupAndX, TreeConnectAndX, OpenAndX and NtCreateAndX
 3324         // are only allowed by Samba.
 3325         if (smb_com == SMB_COM_SESSION_SETUP_ANDX)
 3326             sess_chain = true;
 3327 
 3328         // Check for multiple chained SessionSetupAndX
 3329         if ((smb_com2 == SMB_COM_SESSION_SETUP_ANDX) && sess_chain)
 3330         {
 3331             // There is only one place to return a uid.
 3332             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_MULT_CHAIN_SS);
 3333             // XXX Should we continue processing?
 3334             break;
 3335         }
 3336 
 3337         // Check for chained SessionSetupAndX => .? => LogoffAndX
 3338         if ((smb_com2 == SMB_COM_LOGOFF_ANDX) && sess_chain)
 3339         {
 3340             // This essentially deletes the uid created by the login
 3341             // and doesn't make any sense.
 3342             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_CHAIN_SS_LOGOFF);
 3343         }
 3344 
 3345         if (smb_com == SMB_COM_TREE_CONNECT_ANDX)
 3346             tree_chain = true;
 3347 
 3348         // Check for multiple chained TreeConnects
 3349         if (((smb_com2 == SMB_COM_TREE_CONNECT_ANDX)
 3350                     || (smb_com2 == SMB_COM_TREE_CONNECT)) && tree_chain)
 3351         {
 3352             // There is only one place to return a tid.
 3353             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_MULT_CHAIN_TC);
 3354             // XXX Should we continue processing?
 3355             break;
 3356         }
 3357 
 3358         // Check for chained TreeConnectAndX => .? => TreeDisconnect
 3359         if ((smb_com2 == SMB_COM_TREE_DISCONNECT) && tree_chain)
 3360         {
 3361             // This essentially deletes the tid created by the tree connect
 3362             // and doesn't make any sense.
 3363             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_CHAIN_TC_TDIS);
 3364         }
 3365 
 3366         if ((smb_com == SMB_COM_OPEN_ANDX) || (smb_com == SMB_COM_NT_CREATE_ANDX))
 3367             open_chain = true;
 3368 
 3369         // Check for chained OpenAndX/NtCreateAndX => .? => Close
 3370         if ((smb_com2 == SMB_COM_CLOSE) && open_chain)
 3371         {
 3372             // This essentially deletes the fid created by the open command
 3373             // and doesn't make any sense.
 3374             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_CHAIN_OPEN_CLOSE);
 3375         }
 3376 
 3377         // Check that policy allows for such chaining
 3378         if (smb_chain_funcs[policy][andx_com][smb_com2] == NULL)
 3379             break;
 3380 
 3381         DCE2_MOVE(nb_ptr, nb_len, DCE2_ComInfoCommandSize(com_info));
 3382 
 3383         // XXX Need to test out of order chaining
 3384         off2_ptr = (uint8_t *)smb_hdr + SmbAndXOff2(andx_ptr);
 3385         if (DCE2_SmbCheckAndXOffset(ssd, off2_ptr, nb_ptr, nb_len) != DCE2_RET__SUCCESS)
 3386             break;
 3387 
 3388         DCE2_MOVE(nb_ptr, nb_len, (off2_ptr - nb_ptr));
 3389 
 3390         // XXX Need to test more.
 3391         switch (smb_com)
 3392         {
 3393             case SMB_COM_SESSION_SETUP_ANDX:
 3394             case SMB_COM_TREE_CONNECT_ANDX:
 3395             case SMB_COM_OPEN_ANDX:
 3396             case SMB_COM_NT_CREATE_ANDX:
 3397                 switch (smb_com2)
 3398                 {
 3399                     case SMB_COM_WRITE:
 3400                     case SMB_COM_WRITE_ANDX:
 3401                     case SMB_COM_TRANSACTION:
 3402                     case SMB_COM_READ_ANDX:
 3403                         if (DCE2_SsnFromClient(ssd->sd.wire_pkt) && open_chain)
 3404                         {
 3405                             DCE2_SmbQueueTmpFileTracker(ssd, ssd->cur_rtracker,
 3406                                     SmbUid(smb_hdr), SmbTid(smb_hdr));
 3407                         }
 3408                         break;
 3409                     default:
 3410                         break;
 3411                 }
 3412                 break;
 3413             default:
 3414                 break;
 3415         }
 3416 
 3417         smb_com = smb_com2;
 3418     }
 3419 
 3420     if (smb_type == SMB_TYPE__RESPONSE)
 3421     {
 3422         switch (smb_com)
 3423         {
 3424             case SMB_COM_TRANSACTION:
 3425             case SMB_COM_TRANSACTION2:
 3426             case SMB_COM_NT_TRANSACT:
 3427             case SMB_COM_TRANSACTION_SECONDARY:
 3428             case SMB_COM_TRANSACTION2_SECONDARY:
 3429             case SMB_COM_NT_TRANSACT_SECONDARY:
 3430                 // This case means there was an error with the initial response
 3431                 // so the tracker isn't yet officially in response mode
 3432                 if (ssd->cur_rtracker->ttracker.smb_type == SMB_TYPE__REQUEST)
 3433                 {
 3434                     // Samba throws out entire transaction and Windows just this request
 3435                     if (DCE2_SsnIsServerSambaPolicy(&ssd->sd) && (status != DCE2_RET__SUCCESS))
 3436                         break;
 3437 
 3438                     if (!DCE2_SmbIsTransactionComplete(&ssd->cur_rtracker->ttracker))
 3439                         return;
 3440                 }
 3441                 else
 3442                 {
 3443                     if ((status == DCE2_RET__SUCCESS)
 3444                             && !DCE2_SmbIsTransactionComplete(&ssd->cur_rtracker->ttracker))
 3445                         return;
 3446                 }
 3447                 break;
 3448             case SMB_COM_WRITE_RAW:
 3449                 if ((status == DCE2_RET__SUCCESS)
 3450                         && (ssd->cur_rtracker->writeraw_remaining != 0))
 3451                     return;
 3452                 break;
 3453             /*This is to handle packet that got verdict as pending & will be put in retry queue */
 3454             case SMB_COM_CLOSE:
 3455                 if (status == DCE2_RET__NOT_INSPECTED)
 3456                     return;
 3457             default:
 3458                 break;
 3459         }
 3460     }
 3461     else if (status != DCE2_RET__IGNORE)
 3462     {
 3463         switch (smb_com)
 3464         {
 3465             case SMB_COM_TRANSACTION:
 3466             case SMB_COM_TRANSACTION_SECONDARY:
 3467                 if (DCE2_SsnIsWindowsPolicy(&ssd->sd))
 3468                 {
 3469                     if (!ssd->cur_rtracker->ttracker.one_way
 3470                             || !DCE2_SmbIsTransactionComplete(&ssd->cur_rtracker->ttracker))
 3471                         return;
 3472 
 3473                     // Remove the request tracker if transaction is one-way and
 3474                     // all data and parameters have been sent
 3475                     break;
 3476                 }
 3477             default:
 3478                 // Anything else, keep the request tracker
 3479                 return;
 3480         }
 3481     }
 3482 
 3483     DCE2_SmbRemoveRequestTracker(ssd, ssd->cur_rtracker);
 3484     ssd->cur_rtracker = NULL;
 3485 }
 3486 
 3487 /********************************************************************
 3488  * Function: DCE2_SmbCheckData()
 3489  *
 3490  * Purpose:
 3491  *  Ensures that the data size reported in an SMB command is kosher.
 3492  *
 3493  * Arguments:
 3494  *  DCE2_SmbSsnData * - SMB session data structure
 3495  *  const uint8_t *   - pointer to start of SMB header where offset is
 3496  *                      taken from.
 3497  *  const uint8_t *   - current pointer - should be right after command
 3498  *                      structure.
 3499  *  const uint32_t    - remaining data left in PDU from current pointer.
 3500  *  const uint16_t    - the byte count from the SMB command
 3501  *  const uint16_t    - reported data count in SMB command
 3502  *  const uint16_t    - reported data offset in SMB command
 3503  *
 3504  * Returns:
 3505  *  DCE2_Ret -  DCE2_RET__ERROR if data should not be processed
 3506  *              DCE2_RET__SUCCESS if data can be processed
 3507  *
 3508  ********************************************************************/
 3509 static inline DCE2_Ret DCE2_SmbCheckData(DCE2_SmbSsnData *ssd,
 3510         const uint8_t *smb_hdr_ptr, const uint8_t *nb_ptr,
 3511         const uint32_t nb_len, const uint16_t bcc,
 3512         const uint32_t dcnt, uint16_t doff)
 3513 {
 3514     const uint8_t *offset = smb_hdr_ptr + doff;
 3515     const uint8_t *nb_end = nb_ptr + nb_len;
 3516 
 3517     // Byte counts don't usually matter, so no error but still alert
 3518     // Don't alert in the case where the data count is larger than what the
 3519     // byte count can handle.  This can happen if CAP_LARGE_READX or
 3520     // CAP_LARGE_WRITEX were negotiated.
 3521     if ((dcnt <= UINT16_MAX) && (bcc < dcnt))
 3522         DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BCC_LT_DSIZE, bcc, (uint64_t)dcnt);
 3523 
 3524     if (offset > nb_end)
 3525     {
 3526         DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BAD_OFF, offset, nb_ptr, nb_end);
 3527 
 3528         // Error if offset is beyond data left
 3529         return DCE2_RET__ERROR;
 3530     }
 3531 
 3532     // Only check if the data count is non-zero
 3533     if ((dcnt != 0) && (offset < nb_ptr))
 3534     {
 3535         // Not necessarily and error if the offset puts the data
 3536         // before or in the command structure.
 3537         DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BAD_OFF, offset, nb_ptr, nb_end);
 3538     }
 3539 
 3540     // Not necessarily an error if the addition of the data count goes
 3541     // beyond the data left
 3542     if (((offset + dcnt) > nb_end)           // beyond data left
 3543             || ((offset + dcnt) < offset))   // wrap
 3544     {
 3545         int pad = offset - nb_ptr;
 3546         if (pad > 0)
 3547             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_NB_LT_DSIZE, nb_len - pad, dcnt);
 3548         else
 3549             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_NB_LT_DSIZE, nb_len, dcnt);
 3550     }
 3551 
 3552     return DCE2_RET__SUCCESS;
 3553 }
 3554 
 3555 /********************************************************************
 3556  * Function: DCE2_SmbValidateTransactionFields()
 3557  *
 3558  * Purpose:
 3559  *  Wrapper that calls DCE2_SmbCheckTotalCount() for total parameter
 3560  *  count and total data count and DCE2_SmbCheckTransDataParams()
 3561  *
 3562  * Arguments:
 3563  *  DCE2_SmbSsnData * - SMB session data structure
 3564  *  const uint8_t *   - pointer to start of SMB header where offset is
 3565  *                      taken from.
 3566  *  const uint8_t *   - current pointer - should be right after command
 3567  *                      structure.
 3568  *  const uint32_t    - remaining data left in PDU from current pointer.
 3569  *  const uint16_t    - the byte count
 3570  *  const uint32_t    - reported total data count
 3571  *  const uint32_t    - reported total parameter count
 3572  *  const uint32_t    - reported data count
 3573  *  const uint32_t    - reported data offset
 3574  *  const uint32_t    - reported data displacement
 3575  *  const uint32_t    - reported parameter count
 3576  *  const uint32_t    - reported parameter offset
 3577  *  const uint32_t    - reported parameter displacement
 3578  *
 3579  * Returns:
 3580  *  DCE2_Ret -  DCE2_RET__ERROR if data should not be processed
 3581  *              DCE2_RET__SUCCESS if data can be processed
 3582  *
 3583  ********************************************************************/
 3584 static inline DCE2_Ret DCE2_SmbValidateTransactionFields(DCE2_SmbSsnData *ssd,
 3585         const uint8_t *smb_hdr_ptr,
 3586         const uint8_t *nb_ptr, const uint32_t nb_len, const uint16_t bcc,
 3587         const uint32_t tdcnt, const uint32_t tpcnt,
 3588         const uint32_t dcnt, const uint32_t doff, const uint32_t ddisp,
 3589         const uint32_t pcnt, const uint32_t poff, const uint32_t pdisp)
 3590 {
 3591     if (DCE2_SmbCheckTotalCount(ssd, tdcnt, dcnt, ddisp) != DCE2_RET__SUCCESS)
 3592         return DCE2_RET__ERROR;
 3593 
 3594     if (DCE2_SmbCheckTotalCount(ssd, tpcnt, pcnt, pdisp) != DCE2_RET__SUCCESS)
 3595         return DCE2_RET__ERROR;
 3596 
 3597     if (DCE2_SmbCheckTransDataParams(ssd, smb_hdr_ptr,
 3598                 nb_ptr, nb_len, bcc, dcnt, doff, pcnt, poff) != DCE2_RET__SUCCESS)
 3599         return DCE2_RET__ERROR;
 3600 
 3601     return DCE2_RET__SUCCESS;
 3602 }
 3603 
 3604 /********************************************************************
 3605  * Function: DCE2_SmbValidateTransactionSent()
 3606  *
 3607  * Purpose:
 3608  *  Checks that amount sent plus current amount is not greater than
 3609  *  the total count expected.
 3610  *
 3611  * Arguments:
 3612  *  DCE2_SmbSsnData * - SMB session data structure
 3613  *  const uint32_t    - amount of data sent so far
 3614  *  const uint32_t    - reported total data count
 3615  *  const uint32_t    - reported data count
 3616  *  const uint32_t    - amount of parameters sent so far
 3617  *  const uint32_t    - reported total parameter count
 3618  *  const uint32_t    - reported parameter count
 3619  *
 3620  * Returns:
 3621  *  DCE2_Ret -  DCE2_RET__ERROR if data should not be processed
 3622  *              DCE2_RET__SUCCESS if data can be processed
 3623  *
 3624  ********************************************************************/
 3625 static inline DCE2_Ret DCE2_SmbValidateTransactionSent(DCE2_SmbSsnData *ssd,
 3626         uint32_t dsent, uint32_t dcnt, uint32_t tdcnt,
 3627         uint32_t psent, uint32_t pcnt, uint32_t tpcnt)
 3628 {
 3629     if (((dsent + dcnt) > tdcnt) || ((psent + pcnt) > tpcnt))
 3630     {
 3631         if ((dsent + dcnt) > tdcnt)
 3632         {
 3633             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_DSENT_GT_TDCNT,
 3634                     ((uint64_t)dsent + dcnt), tdcnt);
 3635         }
 3636 
 3637         if ((psent + pcnt) > tpcnt)
 3638         {
 3639             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_DSENT_GT_TDCNT,
 3640                     ((uint64_t)psent + pcnt), tpcnt);
 3641         }
 3642 
 3643         // Samba throws out entire transaction and Windows seems to hang in
 3644         // limbo forever and never responds, so stop looking
 3645         return DCE2_RET__ERROR;
 3646     }
 3647 
 3648     return DCE2_RET__SUCCESS;
 3649 }
 3650 
 3651 /********************************************************************
 3652  * Function: DCE2_SmbCheckTransDataParams()
 3653  *
 3654  * Purpose:
 3655  *  Ensures that the data size reported in an SMB command is kosher.
 3656  *  Note the 32 bit values are because of the NtTransact command
 3657  *  though it's currently not checked.
 3658  *
 3659  * Arguments:
 3660  *  DCE2_SmbSsnData * - SMB session data structure
 3661  *  const uint8_t *   - pointer to start of SMB header where offset is
 3662  *                      taken from.
 3663  *  const uint8_t *   - current pointer - should be right after command
 3664  *                      structure.
 3665  *  const uint32_t    - remaining data left in PDU from current pointer.
 3666  *  const uint16_t    - the byte count
 3667  *  const uint32_t    - reported data count
 3668  *  const uint32_t    - reported data offset
 3669  *  const uint32_t    - reported parameter count
 3670  *  const uint32_t    - reported parameter offset
 3671  *
 3672  * Returns:
 3673  *  DCE2_Ret -  DCE2_RET__ERROR if data should not be processed
 3674  *              DCE2_RET__SUCCESS if data can be processed
 3675  *
 3676  ********************************************************************/
 3677 static inline DCE2_Ret DCE2_SmbCheckTransDataParams(DCE2_SmbSsnData *ssd,
 3678         const uint8_t *smb_hdr_ptr, const uint8_t *nb_ptr, const uint32_t nb_len,
 3679         const uint16_t bcc, const uint32_t dcnt, const uint32_t doff,
 3680         const uint32_t pcnt, const uint32_t poff)
 3681 {
 3682     const uint8_t *doffset = smb_hdr_ptr + doff;
 3683     const uint8_t *poffset = smb_hdr_ptr + poff;
 3684     const uint8_t *nb_end = nb_ptr + nb_len;
 3685 
 3686     if (bcc < ((uint64_t)dcnt + pcnt))
 3687         DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BCC_LT_DSIZE, bcc, ((uint64_t)dcnt + pcnt));
 3688 
 3689     // Check data offset out of bounds
 3690     if ((doffset > nb_end) || (doffset < smb_hdr_ptr))
 3691     {
 3692         // Beyond data left or wrap
 3693         DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BAD_OFF, doffset, nb_ptr, nb_end);
 3694         return DCE2_RET__ERROR;
 3695     }
 3696 
 3697     // Check data offset in bounds but backwards
 3698     // Only check if the data count is non-zero
 3699     if ((dcnt != 0) && (doffset < nb_ptr))
 3700     {
 3701         // Not necessarily and error if the offset puts the data
 3702         // before or in the command structure.
 3703         DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BAD_OFF, doffset, nb_ptr, nb_end);
 3704     }
 3705 
 3706     // Check the data offset + data count
 3707     if (((doffset + dcnt) > nb_end)            // beyond data left
 3708             || ((doffset + dcnt) < doffset))   // wrap
 3709     {
 3710         DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_NB_LT_DSIZE, nb_len, dcnt);
 3711         return DCE2_RET__ERROR;
 3712     }
 3713 
 3714     // Check parameter offset out of bounds
 3715     if ((poffset > nb_end) || (poffset < smb_hdr_ptr))
 3716     {
 3717         // Beyond data left or wrap
 3718         DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BAD_OFF, poffset, nb_ptr, nb_end);
 3719         return DCE2_RET__ERROR;
 3720     }
 3721 
 3722     // Check parameter offset in bounds but backwards
 3723     // Only check if the parameter count is non-zero
 3724     if ((pcnt != 0) && (poffset < nb_ptr))
 3725     {
 3726         // Not necessarily and error if the offset puts the data
 3727         // before or in the command structure.
 3728         DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BAD_OFF, poffset, nb_ptr, nb_end);
 3729     }
 3730 
 3731     // Check the parameter offset + parameter count
 3732     if (((poffset + pcnt) > nb_end)            // beyond data left
 3733             || ((poffset + pcnt) < poffset))   // wrap
 3734     {
 3735         DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_NB_LT_DSIZE, nb_len, pcnt);
 3736         return DCE2_RET__ERROR;
 3737     }
 3738 
 3739     return DCE2_RET__SUCCESS;
 3740 }
 3741 
 3742 /********************************************************************
 3743  * Function: DCE2_SmbCheckFmtData()
 3744  *
 3745  * Purpose:
 3746  *  Checks the data count in commands with formats, e.g.
 3747  *  SMB_COM_WRITE, SMB_COM_WRITE_AND_CLOSE, SMB_COM_WRITE_AND_UNLOCK.
 3748  *
 3749  * Arguments:
 3750  *  DCE2_SmbSsnData * - SMB session data structure
 3751  *  const uint32_t    - remaining NetBIOS PDU length
 3752  *  const uint16_t    - advertised byte count
 3753  *  const uint8_t     - data format specifier
 3754  *  const uint16_t    - data count reported in command
 3755  *  const uint16_t    - data count reported in format field
 3756  *
 3757  * Returns: None
 3758  *
 3759  ********************************************************************/
 3760 static inline void DCE2_SmbCheckFmtData(DCE2_SmbSsnData *ssd,
 3761         const uint32_t nb_len, const uint16_t bcc, const uint8_t fmt,
 3762         const uint16_t com_dcnt, const uint16_t fmt_dcnt)
 3763 {
 3764     if (fmt != SMB_FMT__DATA_BLOCK)
 3765         DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BAD_FORMAT, fmt);
 3766 
 3767     if (com_dcnt != fmt_dcnt)
 3768         DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_DCNT_MISMATCH, com_dcnt, fmt_dcnt);
 3769 
 3770     if (com_dcnt != (bcc - 3))
 3771         DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_INVALID_DSIZE, com_dcnt, bcc);
 3772 
 3773     if (nb_len < com_dcnt)
 3774         DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_NB_LT_DSIZE, nb_len, com_dcnt);
 3775 }
 3776 
 3777 /********************************************************************
 3778  * Function: DCE2_SmbCheckTotalCount()
 3779  *
 3780  * Purpose:
 3781  *  Validates the advertised total data/param count.  Makes sure the
 3782  *  current count isn't greater than total count, that the
 3783  *  displacement + count isn't greater than the total data count and
 3784  *  that the total data count isn't zero.  Mainly relevant to Write Raw,
 3785  *  Transaction and Transaction Secondary commands.
 3786  *
 3787  * Arguments:
 3788  *  DCE2_SmbSsnData * - SMB session data structure
 3789  *  const uint32_t    - total data count
 3790  *  const uint32_t    - data count/size
 3791  *  const uint32_t    - data displacement
 3792  *
 3793  * Returns:
 3794  *  DCE2_Ret - DCE2_RET__SUCCESS if all is ok
 3795  *             DCE2_RET__ERROR if any of the checks fail.
 3796  *
 3797  ********************************************************************/
 3798 static inline DCE2_Ret DCE2_SmbCheckTotalCount(DCE2_SmbSsnData *ssd,
 3799         const uint32_t tcnt, const uint32_t cnt, const uint32_t disp)
 3800 {
 3801     DCE2_Ret ret = DCE2_RET__SUCCESS;
 3802 
 3803     if (cnt > tcnt)
 3804     {
 3805         DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_TDCNT_LT_DSIZE, tcnt, cnt);
 3806         ret = DCE2_RET__ERROR;
 3807     }
 3808 
 3809     if (((uint64_t)disp + cnt) > tcnt)
 3810     {
 3811         DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_DSENT_GT_TDCNT, ((uint64_t)disp + cnt), tcnt);
 3812         ret = DCE2_RET__ERROR;
 3813     }
 3814 
 3815     return ret;
 3816 }
 3817 
 3818 /********************************************************************
 3819  * Function: DCE2_SmbCheckAndXOffset()
 3820  *
 3821  * Purpose:
 3822  *  Validates that the AndXOffset is within bounds of the remaining
 3823  *  data we have to work with.
 3824  *
 3825  * Arguments:
 3826  *  uint8_t * - pointer to where the offset would take us.
 3827  *  uint8_t * - pointer to bound offset
 3828  *  uint8_t * - length of data where offset should be within
 3829  *
 3830  * Returns:
 3831  *  DCE2_RET__SUCCESS - Offset is okay.
 3832  *  DCE2_RET__ERROR   - Offset is bad.
 3833  *
 3834  ********************************************************************/
 3835 static inline DCE2_Ret DCE2_SmbCheckAndXOffset(DCE2_SmbSsnData *ssd,
 3836         const uint8_t *off_ptr, const uint8_t *start_bound, const uint32_t length)
 3837 {
 3838     /* Offset should not point within data we just looked at or be equal to
 3839      * or beyond the length of the NBSS length left */
 3840     if ((off_ptr < start_bound) ||
 3841             (off_ptr > (start_bound + length)))
 3842     {
 3843         DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BAD_OFF, off_ptr,
 3844                 start_bound, start_bound + length);
 3845 
 3846         return DCE2_RET__ERROR;
 3847     }
 3848 
 3849     return DCE2_RET__SUCCESS;
 3850 }
 3851 
 3852 /********************************************************************
 3853  * Function: DCE2_SmbInvalidShareCheck()
 3854  *
 3855  * Purpose:
 3856  *  Checks the share reported in a TreeConnect or TreeConnectAndX
 3857  *  against the invalid share list configured in the dcerpc2
 3858  *  configuration in snort.conf.
 3859  *
 3860  * Arguments:
 3861  *  DCE2_SmbSsnData * - SMB session data structure
 3862  *  SmbNtHdr *        - pointer to the SMB header structure
 3863  *  uint8_t *         - current pointer to the share to check
 3864  *  uint32_t          - the remaining length
 3865  *
 3866  * Returns: None
 3867  *  Alerts if there is an invalid share match.
 3868  *
 3869  ********************************************************************/
 3870 static inline void DCE2_SmbInvalidShareCheck(DCE2_SmbSsnData *ssd,
 3871         const SmbNtHdr *smb_hdr, const uint8_t *nb_ptr, uint32_t nb_len)
 3872 {
 3873     DCE2_List *share_list = DCE2_ScSmbInvalidShares(ssd->sd.sconfig);
 3874     DCE2_SmbShare *smb_share;
 3875 
 3876     if (share_list == NULL)
 3877         return;
 3878 
 3879     for (smb_share = (DCE2_SmbShare *)DCE2_ListFirst(share_list);
 3880             smb_share != NULL;
 3881             smb_share = (DCE2_SmbShare *)DCE2_ListNext(share_list))
 3882     {
 3883         unsigned int i;
 3884         const char *share_str;
 3885         unsigned int share_str_len;
 3886 
 3887         if (SmbUnicode(smb_hdr))
 3888         {
 3889             share_str = smb_share->unicode_str;
 3890             share_str_len = smb_share->unicode_str_len;
 3891         }
 3892         else
 3893         {
 3894             share_str = smb_share->ascii_str;
 3895             share_str_len = smb_share->ascii_str_len;
 3896         }
 3897 
 3898         /* Make sure we have enough data */
 3899         if (nb_len < share_str_len)
 3900             continue;
 3901 
 3902         /* Test for share match */
 3903         for (i = 0; i < share_str_len; i++)
 3904         {
 3905             /* All share strings should have been converted to upper case and
 3906              * should include null terminating bytes */
 3907             if ((nb_ptr[i] != share_str[i]) && (nb_ptr[i] != tolower((int)share_str[i])))
 3908                 break;
 3909         }
 3910 
 3911         if (i == share_str_len)
 3912         {
 3913             /* Should only match one share since no duplicate shares in list */
 3914             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_INVALID_SHARE, smb_share->ascii_str);
 3915             break;
 3916         }
 3917     }
 3918 }
 3919 
 3920 /********************************************************************
 3921  * Functions:
 3922  *   DCE2_SmbOpen()
 3923  *   DCE2_SmbCreate()
 3924  *   DCE2_SmbClose()
 3925  *   DCE2_SmbRename()
 3926  *   DCE2_SmbRead()
 3927  *   DCE2_SmbWrite()
 3928  *   DCE2_SmbCreateNew()
 3929  *   DCE2_SmbLockAndRead()
 3930  *   DCE2_SmbWriteAndUnlock()
 3931  *   DCE2_SmbReadRaw()
 3932  *   DCE2_SmbWriteRaw()
 3933  *   DCE2_SmbWriteComplete()
 3934  *   DCE2_SmbTransaction()
 3935  *   DCE2_SmbTransactionSecondary()
 3936  *   DCE2_SmbWriteAndClose()
 3937  *   DCE2_SmbOpenAndX()
 3938  *   DCE2_SmbReadAndX()
 3939  *   DCE2_SmbWriteAndX()
 3940  *   DCE2_SmbTransaction2()
 3941  *   DCE2_SmbTransaction2Secondary()
 3942  *   DCE2_SmbTreeConnect()
 3943  *   DCE2_SmbTreeDisconnect()
 3944  *   DCE2_SmbNegotiate()
 3945  *   DCE2_SmbSessionSetupAndX()
 3946  *   DCE2_SmbLogoffAndX()
 3947  *   DCE2_SmbTreeConnectAndX()
 3948  *   DCE2_SmbNtTransact()
 3949  *   DCE2_SmbNtTransactSecondary()
 3950  *   DCE2_SmbNtCreateAndX()
 3951  *
 3952  * Purpose: Process SMB command
 3953  *
 3954  * Arguments:
 3955  *  DCE2_SmbSsnData *       - SMB session data structure
 3956  *  const SmbNtHdr *        - SMB header structure (packet pointer)
 3957  *  const DCE2_SmbComInfo * - Basic command information structure
 3958  *  uint8_t *               - pointer to start of command (packet pointer)
 3959  *  uint32_t                - remaining NetBIOS length
 3960  *
 3961  * Returns:
 3962  *  DCE2_Ret - DCE2_RET__ERROR if something went wrong and/or processing
 3963  *               should stop
 3964  *             DCE2_RET__SUCCESS if processing should continue
 3965  *
 3966  ********************************************************************/
 3967 
 3968 // SMB_COM_OPEN
 3969 static DCE2_Ret DCE2_SmbOpen(DCE2_SmbSsnData *ssd, const SmbNtHdr *smb_hdr,
 3970         const DCE2_SmbComInfo *com_info, const uint8_t *nb_ptr, uint32_t nb_len)
 3971 {
 3972     if (!DCE2_ComInfoCanProcessCommand(com_info))
 3973         return DCE2_RET__ERROR;
 3974 
 3975     if (DCE2_ComInfoIsResponse(com_info))
 3976     {
 3977         DCE2_SmbFileTracker *ftracker;
 3978 
 3979         if (!DCE2_SmbIsTidIPC(ssd, ssd->cur_rtracker->tid)
 3980                 && (SmbFileAttrsDirectory(SmbOpenRespFileAttrs((SmbOpenResp *)nb_ptr))
 3981                     || SmbOpenForWriting(SmbOpenRespAccessMode((SmbOpenResp *)nb_ptr))))
 3982             return DCE2_RET__SUCCESS;
 3983 
 3984         ftracker = DCE2_SmbNewFileTracker(ssd, ssd->cur_rtracker->uid,
 3985                 ssd->cur_rtracker->tid, SmbOpenRespFid((SmbOpenResp *)nb_ptr));
 3986         if (ftracker == NULL)
 3987             return DCE2_RET__ERROR;
 3988 
 3989         DCE2_Update_Ftracker_from_ReqTracker(ftracker, ssd->cur_rtracker);
 3990 
 3991         if (!ftracker->is_ipc)
 3992         {
 3993             // This command can only be used to open an existing file
 3994             ftracker->ff_file_size = SmbOpenRespFileSize((SmbOpenResp *)nb_ptr);
 3995         }
 3996     }
 3997     else
 3998     {
 3999         // Have at least 2 bytes of data based on byte count check done earlier
 4000 
 4001         DCE2_MOVE(nb_ptr, nb_len, DCE2_ComInfoCommandSize(com_info));
 4002 
 4003         if (!SmbFmtAscii(*nb_ptr))
 4004         {
 4005             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BAD_FORMAT, *nb_ptr);
 4006             return DCE2_RET__ERROR;
 4007         }
 4008 
 4009         DCE2_MOVE(nb_ptr, nb_len, 1);
 4010 
 4011         ssd->cur_rtracker->file_name =
 4012             DCE2_SmbGetString(nb_ptr, nb_len, SmbUnicode(smb_hdr), &ssd->cur_rtracker->file_name_len);
 4013     }
 4014 
 4015 
 4016     return DCE2_RET__SUCCESS;
 4017 }
 4018 
 4019 // SMB_COM_CREATE
 4020 static DCE2_Ret DCE2_SmbCreate(DCE2_SmbSsnData *ssd, const SmbNtHdr *smb_hdr,
 4021         const DCE2_SmbComInfo *com_info, const uint8_t *nb_ptr, uint32_t nb_len)
 4022 {
 4023     if (!DCE2_ComInfoCanProcessCommand(com_info))
 4024         return DCE2_RET__ERROR;
 4025 
 4026     if (DCE2_ComInfoIsResponse(com_info))
 4027     {
 4028         DCE2_SmbFileTracker *ftracker = DCE2_SmbNewFileTracker(
 4029                 ssd, ssd->cur_rtracker->uid, ssd->cur_rtracker->tid,
 4030                 SmbCreateRespFid((SmbCreateResp *)nb_ptr));
 4031 
 4032         if (ftracker == NULL)
 4033             return DCE2_RET__ERROR;
 4034 
 4035         DCE2_Update_Ftracker_from_ReqTracker(ftracker, ssd->cur_rtracker);
 4036 
 4037         // Command creates or opens and truncates file to 0 so assume
 4038         // upload.
 4039         if (!ftracker->is_ipc)
 4040             ftracker->ff_file_direction = DCE2_SMB_FILE_DIRECTION__UPLOAD;
 4041     }
 4042     else
 4043     {
 4044         if (!DCE2_SmbIsTidIPC(ssd, ssd->cur_rtracker->tid))
 4045         {
 4046             uint16_t file_attrs = SmbCreateReqFileAttrs((SmbCreateReq *)nb_ptr);
 4047 
 4048             if (SmbAttrDirectory(file_attrs))
 4049                 return DCE2_RET__IGNORE;
 4050 
 4051             if (SmbEvasiveFileAttrs(file_attrs))
 4052                 DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_EVASIVE_FILE_ATTRS);
 4053         }
 4054 
 4055         // Have at least 2 bytes of data based on byte count check done earlier
 4056 
 4057         DCE2_MOVE(nb_ptr, nb_len, DCE2_ComInfoCommandSize(com_info));
 4058 
 4059         if (!SmbFmtAscii(*nb_ptr))
 4060         {
 4061             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BAD_FORMAT, *nb_ptr);
 4062             return DCE2_RET__ERROR;
 4063         }
 4064 
 4065         DCE2_MOVE(nb_ptr, nb_len, 1);
 4066 
 4067         ssd->cur_rtracker->file_name =
 4068             DCE2_SmbGetString(nb_ptr, nb_len, SmbUnicode(smb_hdr), &ssd->cur_rtracker->file_name_len);
 4069     }
 4070 
 4071     return DCE2_RET__SUCCESS;
 4072 }
 4073 
 4074 // SMB_COM_CLOSE
 4075 static DCE2_Ret DCE2_SmbClose(DCE2_SmbSsnData *ssd, const SmbNtHdr *smb_hdr,
 4076         const DCE2_SmbComInfo *com_info, const uint8_t *nb_ptr, uint32_t nb_len)
 4077 {
 4078     if (!DCE2_ComInfoCanProcessCommand(com_info))
 4079         return DCE2_RET__ERROR;
 4080 
 4081     if (DCE2_ComInfoIsRequest(com_info))
 4082     {
 4083         uint16_t fid = SmbCloseReqFid((SmbCloseReq *)nb_ptr);
 4084 
 4085         // Set this for response
 4086         ssd->cur_rtracker->ftracker = DCE2_SmbGetFileTracker(ssd, fid);
 4087 
 4088 #ifdef ACTIVE_RESPONSE
 4089         if ((ssd->fb_ftracker != NULL) && (ssd->fb_ftracker == ssd->cur_rtracker->ftracker))
 4090         {
 4091             void *ssnptr = ssd->sd.wire_pkt->stream_session;
 4092             void *p = (void *)ssd->sd.wire_pkt;
 4093             File_Verdict verdict = DCE2_SmbGetFileVerdict(p, ssnptr);
 4094             
 4095             if ((verdict == FILE_VERDICT_BLOCK) || (verdict == FILE_VERDICT_REJECT))
 4096                 ssd->block_pdus = true;
 4097         }
 4098 #endif
 4099     }
 4100     else
 4101     {
 4102         return DCE2_SmbRemoveFileTracker(ssd, ssd->cur_rtracker->ftracker);
 4103     }
 4104 
 4105     return DCE2_RET__SUCCESS;
 4106 }
 4107 
 4108 // SMB_COM_RENAME
 4109 static DCE2_Ret DCE2_SmbRename(DCE2_SmbSsnData *ssd, const SmbNtHdr *smb_hdr,
 4110         const DCE2_SmbComInfo *com_info, const uint8_t *nb_ptr, uint32_t nb_len)
 4111 {
 4112     // NOTE: This command is only processed for CVE-2006-4696 where the buffer
 4113     // formats are invalid and has no bearing on DCE/RPC processing.
 4114 
 4115     if (!DCE2_ComInfoCanProcessCommand(com_info))
 4116         return DCE2_RET__ERROR;
 4117 
 4118     if (DCE2_ComInfoIsRequest(com_info))
 4119     {
 4120         // Have at least 4 bytes of data based on byte count check done earlier
 4121 
 4122         uint32_t i;
 4123 
 4124         DCE2_MOVE(nb_ptr, nb_len, DCE2_ComInfoCommandSize(com_info));
 4125 
 4126         if (!SmbFmtAscii(*nb_ptr))
 4127         {
 4128             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BAD_FORMAT, *nb_ptr);
 4129             return DCE2_RET__ERROR;
 4130         }
 4131 
 4132         DCE2_MOVE(nb_ptr, nb_len, 1);
 4133 
 4134         if (SmbUnicode(smb_hdr))
 4135         {
 4136             for (i = 0; i < (nb_len - 1); i += 2)
 4137             {
 4138                 if (*((uint16_t *)(nb_ptr + i)) == 0)
 4139                 {
 4140                     i += 2;  // move past null terminating bytes
 4141                     break;
 4142                 }
 4143             }
 4144         }
 4145         else
 4146         {
 4147             for (i = 0; i < nb_len; i++)
 4148             {
 4149                 if (nb_ptr[i] == 0)
 4150                 {
 4151                     i++;  // move past null terminating byte
 4152                     break;
 4153                 }
 4154             }
 4155         }
 4156 
 4157         // i <= nb_len
 4158         DCE2_MOVE(nb_ptr, nb_len, i);
 4159 
 4160         if ((nb_len > 0) && !SmbFmtAscii(*nb_ptr))
 4161         {
 4162             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BAD_FORMAT, *nb_ptr);
 4163             return DCE2_RET__ERROR;
 4164         }
 4165     }
 4166 
 4167     // Don't care about tracking response
 4168     return DCE2_RET__ERROR;
 4169 }
 4170 
 4171 // SMB_COM_READ
 4172 static DCE2_Ret DCE2_SmbRead(DCE2_SmbSsnData *ssd, const SmbNtHdr *smb_hdr,
 4173         const DCE2_SmbComInfo *com_info, const uint8_t *nb_ptr, uint32_t nb_len)
 4174 {
 4175     if (!DCE2_ComInfoCanProcessCommand(com_info))
 4176         return DCE2_RET__ERROR;
 4177 
 4178     if (DCE2_ComInfoIsRequest(com_info))
 4179     {
 4180         DCE2_SmbFileTracker *ftracker =
 4181             DCE2_SmbGetFileTracker(ssd, SmbReadReqFid((SmbReadReq *)nb_ptr));
 4182 
 4183         // Set this for response since response doesn't have the Fid
 4184         ssd->cur_rtracker->ftracker = ftracker;
 4185         if ((ftracker != NULL) && !ftracker->is_ipc)
 4186             ssd->cur_rtracker->file_offset = SmbReadReqOffset((SmbReadReq *)nb_ptr);
 4187     }
 4188     else
 4189     {
 4190         // Have at least 3 bytes of data based on byte count check done earlier
 4191 
 4192         uint16_t com_size = DCE2_ComInfoCommandSize(com_info);
 4193         uint16_t byte_count = DCE2_ComInfoByteCount(com_info);
 4194         uint16_t com_dcnt = SmbReadRespCount((SmbReadResp *)nb_ptr);
 4195         uint8_t fmt = *(nb_ptr + com_size);
 4196         uint16_t fmt_dcnt = SmbNtohs((uint16_t *)(nb_ptr + com_size + 1));
 4197 
 4198         DCE2_MOVE(nb_ptr, nb_len, (com_size + 3));
 4199 
 4200         DCE2_SmbCheckFmtData(ssd, nb_len, byte_count, fmt, com_dcnt, fmt_dcnt);
 4201 
 4202         if (com_dcnt > nb_len)
 4203             return DCE2_RET__ERROR;
 4204 
 4205         return DCE2_SmbProcessResponseData(ssd, nb_ptr, com_dcnt);
 4206     }
 4207 
 4208     return DCE2_RET__SUCCESS;
 4209 }
 4210 
 4211 // SMB_COM_WRITE
 4212 static DCE2_Ret DCE2_SmbWrite(DCE2_SmbSsnData *ssd, const SmbNtHdr *smb_hdr,
 4213         const DCE2_SmbComInfo *com_info, const uint8_t *nb_ptr, uint32_t nb_len)
 4214 {
 4215     if (!DCE2_ComInfoCanProcessCommand(com_info))
 4216         return DCE2_RET__ERROR;
 4217 
 4218     if (DCE2_ComInfoIsRequest(com_info))
 4219     {
 4220         // Have at least 3 bytes of data based on byte count check done earlier
 4221 
 4222         uint16_t com_size = DCE2_ComInfoCommandSize(com_info);
 4223         uint16_t byte_count = DCE2_ComInfoByteCount(com_info);
 4224         uint8_t fmt = *(nb_ptr + com_size);
 4225         uint16_t com_dcnt = SmbWriteReqCount((SmbWriteReq *)nb_ptr);
 4226         uint16_t fmt_dcnt = SmbNtohs((uint16_t *)(nb_ptr + com_size + 1));
 4227         uint16_t fid = SmbWriteReqFid((SmbWriteReq *)nb_ptr);
 4228         uint32_t offset = SmbWriteReqOffset((SmbWriteReq *)nb_ptr);
 4229 
 4230         DCE2_MOVE(nb_ptr, nb_len, (com_size + 3));
 4231 
 4232         DCE2_SmbCheckFmtData(ssd, nb_len, byte_count, fmt, com_dcnt, fmt_dcnt);
 4233 
 4234         if (com_dcnt == 0)
 4235         {
 4236             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_DCNT_ZERO);
 4237             return DCE2_RET__ERROR;
 4238         }
 4239 
 4240         if (com_dcnt > nb_len)
 4241             com_dcnt = (uint16_t)nb_len;
 4242 
 4243         return DCE2_SmbProcessRequestData(ssd, fid, nb_ptr, com_dcnt, offset);
 4244     }
 4245 
 4246     return DCE2_RET__SUCCESS;
 4247 }
 4248 
 4249 // SMB_COM_CREATE_NEW
 4250 static DCE2_Ret DCE2_SmbCreateNew(DCE2_SmbSsnData *ssd, const SmbNtHdr *smb_hdr,
 4251         const DCE2_SmbComInfo *com_info, const uint8_t *nb_ptr, uint32_t nb_len)
 4252 {
 4253     if (!DCE2_ComInfoCanProcessCommand(com_info))
 4254         return DCE2_RET__ERROR;
 4255 
 4256     if (DCE2_ComInfoIsResponse(com_info))
 4257     {
 4258         DCE2_SmbFileTracker *ftracker = DCE2_SmbNewFileTracker(
 4259                 ssd, ssd->cur_rtracker->uid, ssd->cur_rtracker->tid,
 4260                 SmbCreateNewRespFid((SmbCreateNewResp *)nb_ptr));
 4261 
 4262         if (ftracker == NULL)
 4263             return DCE2_RET__ERROR;
 4264 
 4265         DCE2_Update_Ftracker_from_ReqTracker(ftracker, ssd->cur_rtracker);
 4266 
 4267         // Command creates a new file so assume upload.
 4268         if (!ftracker->is_ipc)
 4269             ftracker->ff_file_direction = DCE2_SMB_FILE_DIRECTION__UPLOAD;
 4270     }
 4271     else
 4272     {
 4273         if (!DCE2_SmbIsTidIPC(ssd, ssd->cur_rtracker->tid))
 4274         {
 4275             uint16_t file_attrs = SmbCreateNewReqFileAttrs((SmbCreateNewReq *)nb_ptr);
 4276 
 4277             if (SmbAttrDirectory(file_attrs))
 4278                 return DCE2_RET__IGNORE;
 4279 
 4280             if (SmbEvasiveFileAttrs(file_attrs))
 4281                 DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_EVASIVE_FILE_ATTRS);
 4282         }
 4283 
 4284         // Have at least 2 bytes of data based on byte count check done earlier
 4285 
 4286         DCE2_MOVE(nb_ptr, nb_len, DCE2_ComInfoCommandSize(com_info));
 4287 
 4288         if (!SmbFmtAscii(*nb_ptr))
 4289         {
 4290             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_BAD_FORMAT, *nb_ptr);
 4291             return DCE2_RET__ERROR;
 4292         }
 4293 
 4294         DCE2_MOVE(nb_ptr, nb_len, 1);
 4295 
 4296         ssd->cur_rtracker->file_name =
 4297             DCE2_SmbGetString(nb_ptr, nb_len, SmbUnicode(smb_hdr), &ssd->cur_rtracker->file_name_len);
 4298     }
 4299 
 4300     return DCE2_RET__SUCCESS;
 4301 }
 4302 
 4303 // SMB_COM_LOCK_AND_READ
 4304 static DCE2_Ret DCE2_SmbLockAndRead(DCE2_SmbSsnData *ssd, const SmbNtHdr *smb_hdr,
 4305         const DCE2_SmbComInfo *com_info, const uint8_t *nb_ptr, uint32_t nb_len)
 4306 {
 4307     if (!DCE2_ComInfoCanProcessCommand(com_info))
 4308         return DCE2_RET__ERROR;
 4309 
 4310     if (DCE2_ComInfoIsRequest(com_info))
 4311     {
 4312         DCE2_SmbFileTracker *ftracker =
 4313             DCE2_SmbFindFileTracker(ssd, ssd->cur_rtracker->uid,
 4314                     ssd->cur_rtracker->tid, SmbLockAndReadReqFid((SmbLockAndReadReq *)nb_ptr));
 4315 
 4316         // No sense in tracking response
 4317         if (ftracker == NULL)
 4318             return DCE2_RET__ERROR;
 4319 
 4320         if (!ftracker->is_ipc)
 4321             ssd->cur_rtracker->file_offset = SmbLockAndReadReqOffset((SmbLockAndReadReq *)nb_ptr);
 4322 
 4323         // Set this for response
 4324         ssd->cur_rtracker->ftracker = ftracker;
 4325     }
 4326     else
 4327     {
 4328         // Have at least 3 bytes of data based on byte count check done earlier
 4329 
 4330         uint16_t com_size = DCE2_ComInfoCommandSize(com_info);
 4331         uint16_t byte_count = DCE2_ComInfoByteCount(com_info);
 4332         uint8_t fmt = *(nb_ptr + com_size);
 4333         uint16_t com_dcnt = SmbLockAndReadRespCount((SmbLockAndReadResp *)nb_ptr);
 4334         uint16_t fmt_dcnt = SmbNtohs((uint16_t *)(nb_ptr + com_size + 1));
 4335 
 4336         DCE2_MOVE(nb_ptr, nb_len, (com_size + 3));
 4337 
 4338         DCE2_SmbCheckFmtData(ssd, nb_len, byte_count, fmt, com_dcnt, fmt_dcnt);
 4339 
 4340         if (com_dcnt == 0)
 4341         {
 4342             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_DCNT_ZERO);
 4343             return DCE2_RET__ERROR;
 4344         }
 4345 
 4346         if (com_dcnt > nb_len)
 4347             com_dcnt = (uint16_t)nb_len;
 4348 
 4349         return DCE2_SmbProcessResponseData(ssd, nb_ptr, com_dcnt);
 4350     }
 4351 
 4352     return DCE2_RET__SUCCESS;
 4353 }
 4354 
 4355 // SMB_COM_WRITE_AND_UNLOCK
 4356 static DCE2_Ret DCE2_SmbWriteAndUnlock(DCE2_SmbSsnData *ssd, const SmbNtHdr *smb_hdr,
 4357         const DCE2_SmbComInfo *com_info, const uint8_t *nb_ptr, uint32_t nb_len)
 4358 {
 4359     if (!DCE2_ComInfoCanProcessCommand(com_info))
 4360     {
 4361         if (DCE2_ComInfoIsBadLength(com_info) || DCE2_ComInfoIsInvalidWordCount(com_info))
 4362             return DCE2_RET__ERROR;
 4363 
 4364         // These are special cases.  The write succeeds but the unlock fails
 4365         // so an error reponse is returned but the data was actually written.
 4366         if (DCE2_ComInfoIsResponse(com_info) && DCE2_ComInfoIsStatusError(com_info))
 4367         {
 4368             if (DCE2_SmbIsTidIPC(ssd, ssd->cur_rtracker->tid))
 4369             {
 4370                 if (!SmbErrorInvalidDeviceRequest(smb_hdr))
 4371                     return DCE2_RET__ERROR;
 4372             }
 4373             else if (!SmbErrorRangeNotLocked(smb_hdr))
 4374             {
 4375                 return DCE2_RET__ERROR;
 4376             }
 4377         }
 4378     }
 4379 
 4380     if (DCE2_ComInfoIsRequest(com_info))
 4381     {
 4382         // Have at least 3 bytes of data based on byte count check done earlier
 4383 
 4384         uint16_t com_size = DCE2_ComInfoCommandSize(com_info);
 4385         uint16_t byte_count = DCE2_ComInfoByteCount(com_info);
 4386         uint8_t fmt = *(nb_ptr + com_size);
 4387         uint16_t com_dcnt = SmbWriteAndUnlockReqCount((SmbWriteAndUnlockReq *)nb_ptr);
 4388         uint16_t fmt_dcnt = SmbNtohs((uint16_t *)(nb_ptr + com_size + 1));
 4389         uint16_t fid = SmbWriteAndUnlockReqFid((SmbWriteAndUnlockReq *)nb_ptr);
 4390         uint32_t offset = SmbWriteAndUnlockReqOffset((SmbWriteAndUnlockReq *)nb_ptr);
 4391 
 4392         DCE2_MOVE(nb_ptr, nb_len, (com_size + 3));
 4393 
 4394         DCE2_SmbCheckFmtData(ssd, nb_len, byte_count, fmt, com_dcnt, fmt_dcnt);
 4395 
 4396         if (com_dcnt == 0)
 4397         {
 4398             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_DCNT_ZERO);
 4399             return DCE2_RET__ERROR;
 4400         }
 4401 
 4402         if (com_dcnt > nb_len)
 4403             com_dcnt = (uint16_t)nb_len;
 4404 
 4405         return DCE2_SmbProcessRequestData(ssd, fid, nb_ptr, com_dcnt, offset);
 4406     }
 4407 
 4408     return DCE2_RET__SUCCESS;
 4409 }
 4410 
 4411 // SMB_COM_READ_RAW
 4412 static DCE2_Ret DCE2_SmbReadRaw(DCE2_SmbSsnData *ssd, const SmbNtHdr *smb_hdr,
 4413         const DCE2_SmbComInfo *com_info, const uint8_t *nb_ptr, uint32_t nb_len)
 4414 {
 4415     if (!DCE2_ComInfoCanProcessCommand(com_info))
 4416         return DCE2_RET__ERROR;
 4417 
 4418     if (DCE2_ComInfoIsRequest(com_info))
 4419     {
 4420         DCE2_SmbFileTracker *ftracker =
 4421             DCE2_SmbFindFileTracker(ssd, ssd->cur_rtracker->uid,
 4422                     ssd->cur_rtracker->tid, SmbReadRawReqFid((SmbReadRawReq *)nb_ptr));
 4423 
 4424         ssd->cur_rtracker->ftracker = ftracker;
 4425         ssd->pdu_state = DCE2_SMB_PDU_STATE__RAW_DATA;
 4426         if ((ftracker != NULL) && !ftracker->is_ipc)
 4427             ssd->cur_rtracker->file_offset = SmbReadRawReqOffset((SmbReadRawExtReq *)nb_ptr);
 4428     }
 4429     else
 4430     {
 4431         // The server response is the raw data.  Supposedly if an error occurs,
 4432         // the server will send a 0 byte read.  Just the NetBIOS header with
 4433         // zero byte length.  Client upon getting the zero read is supposed to issue
 4434         // another read using ReadAndX or Read to get the error.
 4435         return DCE2_RET__ERROR;
 4436     }
 4437 
 4438     return DCE2_RET__SUCCESS;
 4439 }
 4440 
 4441 // SMB_COM_WRITE_RAW
 4442 static DCE2_Ret DCE2_SmbWriteRaw(DCE2_SmbSsnData *ssd, const SmbNtHdr *smb_hdr,
 4443         const DCE2_SmbComInfo *com_info, const uint8_t *nb_ptr, uint32_t nb_len)
 4444 {
 4445     if (!DCE2_ComInfoCanProcessCommand(com_info))
 4446         return DCE2_RET__ERROR;
 4447 
 4448     if (DCE2_ComInfoIsRequest(com_info))
 4449     {
 4450         uint16_t com_size = DCE2_ComInfoCommandSize(com_info);
 4451         uint16_t byte_count = DCE2_ComInfoByteCount(com_info);
 4452         uint16_t fid = SmbWriteRawReqFid((SmbWriteRawReq *)nb_ptr);
 4453         uint16_t tdcnt = SmbWriteRawReqTotalCount((SmbWriteRawReq *)nb_ptr);
 4454         bool writethrough = SmbWriteRawReqWriteThrough((SmbWriteRawReq *)nb_ptr);
 4455         uint16_t doff = SmbWriteRawReqDataOff((SmbWriteRawReq *)nb_ptr);
 4456         uint16_t dcnt = SmbWriteRawReqDataCnt((SmbWriteRawReq *)nb_ptr);
 4457         uint64_t offset = SmbWriteRawReqOffset((SmbWriteRawExtReq *)nb_ptr);
 4458 
 4459         DCE2_MOVE(nb_ptr, nb_len, com_size);
 4460 
 4461         if (DCE2_SmbCheckTotalCount(ssd, tdcnt, dcnt, 0) != DCE2_RET__SUCCESS)
 4462             return DCE2_RET__ERROR;
 4463 
 4464         if (DCE2_SmbCheckData(ssd, (uint8_t *)smb_hdr, nb_ptr, nb_len,
 4465                     byte_count, dcnt, doff) != DCE2_RET__SUCCESS)
 4466             return DCE2_RET__ERROR;
 4467 
 4468         // This may move backwards
 4469         DCE2_MOVE(nb_ptr, nb_len, ((uint8_t *)smb_hdr + doff) - nb_ptr);
 4470 
 4471         if (dcnt > nb_len)
 4472         {
 4473             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_NB_LT_DSIZE, nb_len, dcnt);
 4474             return DCE2_RET__ERROR;
 4475         }
 4476 
 4477         // If all of the data wasn't written in this request, the server will
 4478         // send an interim SMB_COM_WRITE_RAW response and the client will send
 4479         // the rest of the data raw.  In this case if the WriteThrough flag is
 4480         // not set, the server will not send a final SMB_COM_WRITE_COMPLETE
 4481         // response.  If all of the data is in this request the server will
 4482         // send an SMB_COM_WRITE_COMPLETE response regardless of whether or
 4483         // not the WriteThrough flag is set.
 4484         if (dcnt != tdcnt)
 4485         {
 4486             ssd->cur_rtracker->writeraw_writethrough = writethrough;
 4487             ssd->cur_rtracker->writeraw_remaining = tdcnt - dcnt;
 4488         }
 4489 
 4490         return DCE2_SmbProcessRequestData(ssd, fid, nb_ptr, dcnt, offset);
 4491     }
 4492     else
 4493     {
 4494         DCE2_Policy policy = DCE2_SsnGetServerPolicy(&ssd->sd);
 4495 
 4496         // Samba messes this up and sends a request instead of an interim
 4497         // response and a response instead of a Write Complete response.
 4498         switch (policy)
 4499         {
 4500             case DCE2_POLICY__SAMBA:
 4501             case DCE2_POLICY__SAMBA_3_0_37:
 4502             case DCE2_POLICY__SAMBA_3_0_22:
 4503             case DCE2_POLICY__SAMBA_3_0_20:
 4504                 if (SmbType(smb_hdr) != SMB_TYPE__REQUEST)
 4505                     return DCE2_RET__SUCCESS;
 4506                 break;
 4507             default:
 4508                 break;
 4509         }
 4510 
 4511         // If all the data wasn't written initially this interim response will
 4512         // be sent by the server and the raw data will ensue from the client.
 4513         ssd->pdu_state = DCE2_SMB_PDU_STATE__RAW_DATA;
 4514     }
 4515 
 4516     return DCE2_RET__SUCCESS;
 4517 }
 4518 
 4519 // SMB_COM_WRITE_COMPLETE
 4520 static DCE2_Ret DCE2_SmbWriteComplete(DCE2_SmbSsnData *ssd, const SmbNtHdr *smb_hdr,
 4521         const DCE2_SmbComInfo *com_info, const uint8_t *nb_ptr, uint32_t nb_len)
 4522 {
 4523     if (!DCE2_ComInfoCanProcessCommand(com_info))
 4524         return DCE2_RET__ERROR;
 4525 
 4526     return DCE2_RET__SUCCESS;
 4527 }
 4528 
 4529 #define TRANS_NM_PIPE_0       (0)
 4530 #define TRANS_NM_PIPE_1       (TRANS_NM_PIPE_0+7)
 4531 #define TRANS_NM_PIPE_2       (TRANS_NM_PIPE_1+1)
 4532 #define TRANS_NM_PIPE_3       (TRANS_NM_PIPE_2+1)
 4533 #define TRANS_NM_PIPE_4       (TRANS_NM_PIPE_3+5)
 4534 #define TRANS_NM_PIPE_5       (TRANS_NM_PIPE_4+5)
 4535 #define TRANS_NM_PIPE_6       (TRANS_NM_PIPE_5+1)
 4536 #define TRANS_NM_PIPE_7       (TRANS_NM_PIPE_6+5)
 4537 #define TRANS_NM_PIPE_8       (TRANS_NM_PIPE_7+3)
 4538 #define TRANS_NM_PIPE_9       (TRANS_NM_PIPE_8+6)
 4539 #define TRANS_NM_PIPE_FS      (TRANS_NM_PIPE_9+1)
 4540 #define TRANS_NM_PIPE_DONE    (TRANS_NM_PIPE_FS+1)
 4541 
 4542 static DCE2_SmbFsm dce2_samba_pipe_fsm[] =
 4543 {
 4544     // Normal sequence
 4545     {'\\', TRANS_NM_PIPE_0+1, TRANS_NM_PIPE_FS },
 4546     {'P' , TRANS_NM_PIPE_0+2, TRANS_NM_PIPE_FS },
 4547     {'I' , TRANS_NM_PIPE_0+3, TRANS_NM_PIPE_FS },
 4548     {'P' , TRANS_NM_PIPE_0+4, TRANS_NM_PIPE_FS },
 4549     {'E' , TRANS_NM_PIPE_0+5, TRANS_NM_PIPE_FS },
 4550     {'\\', TRANS_NM_PIPE_0+6, TRANS_NM_PIPE_1  },
 4551     {'\0', TRANS_NM_PIPE_DONE, TRANS_NM_PIPE_2 },
 4552 
 4553     // Win98
 4554     {'\0', TRANS_NM_PIPE_DONE, TRANS_NM_PIPE_FS },
 4555 
 4556     {'W' , TRANS_NM_PIPE_2+1, TRANS_NM_PIPE_5  },
 4557 
 4558     {'K' , TRANS_NM_PIPE_3+1, TRANS_NM_PIPE_4  },
 4559     {'S' , TRANS_NM_PIPE_3+2, TRANS_NM_PIPE_FS },
 4560     {'S' , TRANS_NM_PIPE_3+3, TRANS_NM_PIPE_FS },
 4561     {'V' , TRANS_NM_PIPE_3+4, TRANS_NM_PIPE_FS },
 4562     {'C' , TRANS_NM_PIPE_9  , TRANS_NM_PIPE_FS },
 4563 
 4564     {'I' , TRANS_NM_PIPE_4+1, TRANS_NM_PIPE_FS },
 4565     {'N' , TRANS_NM_PIPE_4+2, TRANS_NM_PIPE_FS },
 4566     {'R' , TRANS_NM_PIPE_4+3, TRANS_NM_PIPE_FS },
 4567     {'E' , TRANS_NM_PIPE_4+4, TRANS_NM_PIPE_FS },
 4568     {'G' , TRANS_NM_PIPE_9  , TRANS_NM_PIPE_FS },
 4569 
 4570 
 4571     {'S' , TRANS_NM_PIPE_5+1, TRANS_NM_PIPE_8  },
 4572 
 4573     {'R' , TRANS_NM_PIPE_6+1, TRANS_NM_PIPE_5  },
 4574     {'V' , TRANS_NM_PIPE_6+2, TRANS_NM_PIPE_FS },
 4575     {'S' , TRANS_NM_PIPE_6+3, TRANS_NM_PIPE_FS },
 4576     {'V' , TRANS_NM_PIPE_6+4, TRANS_NM_PIPE_FS },
 4577     {'C' , TRANS_NM_PIPE_9  , TRANS_NM_PIPE_FS },
 4578 
 4579     {'A' , TRANS_NM_PIPE_7+1, TRANS_NM_PIPE_FS },
 4580     {'M' , TRANS_NM_PIPE_7+2, TRANS_NM_PIPE_FS },
 4581     {'R' , TRANS_NM_PIPE_9  , TRANS_NM_PIPE_FS },
 4582 
 4583 
 4584     {'L' , TRANS_NM_PIPE_8+1, TRANS_NM_PIPE_FS },
 4585     {'S' , TRANS_NM_PIPE_8+2, TRANS_NM_PIPE_FS },
 4586     {'A' , TRANS_NM_PIPE_8+3, TRANS_NM_PIPE_FS },
 4587     {'R' , TRANS_NM_PIPE_8+4, TRANS_NM_PIPE_FS },
 4588     {'P' , TRANS_NM_PIPE_8+5, TRANS_NM_PIPE_FS },
 4589     {'C' , TRANS_NM_PIPE_9  , TRANS_NM_PIPE_FS },
 4590 
 4591     {'\0', TRANS_NM_PIPE_DONE, TRANS_NM_PIPE_FS },
 4592 
 4593     {0, TRANS_NM_PIPE_FS, TRANS_NM_PIPE_FS }
 4594 };
 4595 
 4596 // Validates Name for Samba Transaction requests
 4597 static DCE2_Ret DCE2_SmbTransactionGetName(const uint8_t *nb_ptr,
 4598         uint32_t nb_len, uint16_t bcc, bool unicode)
 4599 {
 4600     uint8_t increment = unicode ? 2 : 1;
 4601     int state = TRANS_NM_PIPE_0;
 4602 
 4603     if ((nb_len == 0) || (bcc == 0))
 4604         return DCE2_RET__ERROR;
 4605 
 4606     if (bcc < nb_len)
 4607         nb_len = bcc;
 4608 
 4609     if (unicode)
 4610         DCE2_MOVE(nb_ptr, nb_len, 1);  // One byte pad for unicode
 4611 
 4612     while ((nb_len >= increment) && (state < TRANS_NM_PIPE_FS))
 4613     {
 4614         if (dce2_samba_pipe_fsm[state].input == toupper((int)nb_ptr[0]))
 4615         {
 4616             if (unicode && (nb_ptr[1] != 0))
 4617                 break;
 4618             state = dce2_samba_pipe_fsm[state].next_state;
 4619             DCE2_MOVE(nb_ptr, nb_len, increment);
 4620         }
 4621         else
 4622         {
 4623             state = dce2_samba_pipe_fsm[state].fail_state;
 4624         }
 4625     }
 4626 
 4627     switch (state)
 4628     {
 4629         case TRANS_NM_PIPE_DONE:
 4630             break;
 4631         case TRANS_NM_PIPE_FS:
 4632         default:
 4633             return DCE2_RET__ERROR;
 4634     }
 4635 
 4636     return DCE2_RET__SUCCESS;
 4637 }
 4638 
 4639 // Convenience function to determine whether or not the transaction is complete
 4640 // for one side, i.e. all data and parameters sent.
 4641 static inline bool DCE2_SmbIsTransactionComplete(DCE2_SmbTransactionTracker *ttracker)
 4642 {
 4643     if ((ttracker->tdcnt == ttracker->dsent)
 4644             && (ttracker->tpcnt == ttracker->psent))
 4645         return true;
 4646     return false;
 4647 }
 4648 
 4649 // SMB_COM_TRANSACTION Request
 4650 static inline DCE2_Ret DCE2_SmbTransactionReq(DCE2_SmbSsnData *ssd,
 4651         DCE2_SmbTransactionTracker *ttracker,
 4652         const uint8_t *data_ptr, uint32_t data_len,
 4653         const uint8_t *param_ptr, uint32_t param_len)
 4654 {
 4655     switch (ttracker->subcom)
 4656     {
 4657         case TRANS_TRANSACT_NMPIPE:
 4658         case TRANS_WRITE_NMPIPE:
 4659             if (DCE2_SmbProcessRequestData(ssd, 0,
 4660                         data_ptr, data_len, 0) != DCE2_RET__SUCCESS)
 4661                 return DCE2_RET__ERROR;
 4662             break;
 4663 
 4664         case TRANS_SET_NMPIPE_STATE:
 4665             // Only two parameters but more seems okay
 4666             if (param_len >= 2)
 4667             {
 4668                 if ((SmbNtohs((uint16_t *)param_ptr) & PIPE_STATE_MESSAGE_MODE))
 4669                     ttracker->pipe_byte_mode = false;
 4670                 else
 4671                     ttracker->pipe_byte_mode = true;
 4672 
 4673                 // Won't get a response
 4674                 if (DCE2_SsnIsWindowsPolicy(&ssd->sd) && ttracker->one_way)
 4675                 {
 4676                     DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB,
 4677                                 "Setting pipe to %s mode\n",
 4678                                 ttracker->pipe_byte_mode ? "byte" : "message"));
 4679 
 4680                     ssd->cur_rtracker->ftracker->fp_byte_mode = ttracker->pipe_byte_mode;
 4681                 }
 4682             }
 4683             break;
 4684 
 4685         case TRANS_READ_NMPIPE:
 4686             break;
 4687 
 4688         default:
 4689             return DCE2_RET__IGNORE;
 4690     }
 4691 
 4692     if (DCE2_SsnIsWindowsPolicy(&ssd->sd) && ttracker->one_way && ttracker->disconnect_tid)
 4693         DCE2_SmbRemoveTid(ssd, ssd->cur_rtracker->tid);
 4694 
 4695     return DCE2_RET__SUCCESS;
 4696 }
 4697 
 4698 // SMB_COM_TRANSACTION
 4699 static DCE2_Ret DCE2_SmbTransaction(DCE2_SmbSsnData *ssd, const SmbNtHdr *smb_hdr,
 4700         const DCE2_SmbComInfo *com_info, const uint8_t *nb_ptr, uint32_t nb_len)
 4701 {
 4702     uint16_t com_size = DCE2_ComInfoCommandSize(com_info);
 4703     DCE2_SmbTransactionTracker *ttracker = &ssd->cur_rtracker->ttracker;
 4704 
 4705     // Got a matching request for an in progress transaction - don't process it,
 4706     // but don't want to remove tracker.
 4707     if (DCE2_ComInfoIsRequest(com_info)
 4708             && !DCE2_SmbIsTransactionComplete(ttracker))
 4709     {
 4710         DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Got new transaction request "
 4711                     "that matches an in progress transaction - not inspecting.\n"));
 4712         return DCE2_RET__ERROR;
 4713     }
 4714 
 4715     // Avoid decoding/tracking \PIPE\LANMAN requests
 4716     if (DCE2_ComInfoIsRequest(com_info)
 4717             && (DCE2_ComInfoWordCount(com_info) != 16))
 4718     {
 4719         DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "\\PIPE\\LANMAN request - not inspecting\n"));
 4720         return DCE2_RET__IGNORE;
 4721     }
 4722 
 4723     if (!DCE2_ComInfoCanProcessCommand(com_info))
 4724         return DCE2_RET__ERROR;
 4725 
 4726     // Interim response is sent if client didn't send all data / parameters
 4727     // in initial Transaction request and will have to complete the request
 4728     // with TransactionSecondary commands.
 4729     if (DCE2_ComInfoIsResponse(com_info)
 4730             && (com_size == sizeof(SmbTransactionInterimResp)))
 4731     {
 4732         DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB,
 4733                     "  Server Transaction interim response.\n"));
 4734 
 4735         return DCE2_RET__SUCCESS;
 4736     }
 4737 
 4738     if (DCE2_ComInfoIsRequest(com_info))
 4739     {
 4740         uint16_t doff, dcnt, pcnt, poff;
 4741         const uint8_t *data_ptr, *param_ptr;
 4742         DCE2_Ret status =
 4743             DCE2_SmbUpdateTransRequest(ssd, smb_hdr, com_info, nb_ptr, nb_len);
 4744 
 4745         if (status != DCE2_RET__FULL)
 4746             return status;
 4747 
 4748         ttracker->disconnect_tid = SmbTransactionReqDisconnectTid((SmbTransactionReq *)nb_ptr);
 4749         ttracker->one_way = SmbTransactionReqOneWay((SmbTransactionReq *)nb_ptr);
 4750 
 4751         doff = SmbTransactionReqDataOff((SmbTransactionReq *)nb_ptr);
 4752         dcnt = SmbTransactionReqDataCnt((SmbTransactionReq *)nb_ptr);
 4753         pcnt = SmbTransactionReqParamCnt((SmbTransactionReq *)nb_ptr);
 4754         poff = SmbTransactionReqParamOff((SmbTransactionReq *)nb_ptr);
 4755 
 4756         DCE2_MOVE(nb_ptr, nb_len, ((uint8_t *)smb_hdr + doff) - nb_ptr);
 4757         data_ptr = nb_ptr;
 4758 
 4759         DCE2_MOVE(nb_ptr, nb_len, ((uint8_t *)smb_hdr + poff) - nb_ptr);
 4760         param_ptr = nb_ptr;
 4761 
 4762         status = DCE2_SmbTransactionReq(ssd, ttracker, data_ptr, dcnt, param_ptr, pcnt);
 4763         if (status != DCE2_RET__SUCCESS)
 4764             return status;
 4765     }
 4766     else
 4767     {
 4768         DCE2_Ret status =
 4769             DCE2_SmbUpdateTransResponse(ssd, smb_hdr, com_info, nb_ptr, nb_len);
 4770 
 4771         if (status != DCE2_RET__FULL)
 4772             return status;
 4773 
 4774         switch (ttracker->subcom)
 4775         {
 4776             case TRANS_TRANSACT_NMPIPE:
 4777             case TRANS_READ_NMPIPE:
 4778                 if (!DCE2_BufferIsEmpty(ttracker->dbuf))
 4779                 {
 4780                     const uint8_t *data_ptr = DCE2_BufferData(ttracker->dbuf);
 4781                     uint32_t data_len = DCE2_BufferLength(ttracker->dbuf);
 4782                     SFSnortPacket *rpkt = DCE2_SmbGetRpkt(ssd, &data_ptr,
 4783                             &data_len, DCE2_RPKT_TYPE__SMB_TRANS);
 4784 
 4785                     if (rpkt == NULL)
 4786                         return DCE2_RET__ERROR;
 4787 
 4788                     DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Reassembled Transaction response\n"));
 4789                     DCE2_DEBUG_CODE(DCE2_DEBUG__MAIN, DCE2_PrintPktData(rpkt->payload, rpkt->payload_size););
 4790 
 4791                     status = DCE2_SmbProcessResponseData(ssd, data_ptr, data_len);
 4792 
 4793                     DCE2_SmbReturnRpkt();
 4794 
 4795                     if (status != DCE2_RET__SUCCESS)
 4796                         return status;
 4797                 }
 4798                 else
 4799                 {
 4800                     uint16_t dcnt = SmbTransactionRespDataCnt((SmbTransactionResp *)nb_ptr);
 4801                     uint16_t doff = SmbTransactionRespDataOff((SmbTransactionResp *)nb_ptr);
 4802 
 4803                     DCE2_MOVE(nb_ptr, nb_len, ((uint8_t *)smb_hdr + doff) - nb_ptr);
 4804 
 4805                     if (DCE2_SmbProcessResponseData(ssd, nb_ptr, dcnt) != DCE2_RET__SUCCESS)
 4806                         return DCE2_RET__ERROR;
 4807                 }
 4808                 break;
 4809 
 4810             case TRANS_SET_NMPIPE_STATE:
 4811                 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Setting pipe "
 4812                             "to %s mode\n", ttracker->pipe_byte_mode ? "byte" : "message"));
 4813                 ssd->cur_rtracker->ftracker->fp_byte_mode = ttracker->pipe_byte_mode;
 4814                 break;
 4815 
 4816             case TRANS_WRITE_NMPIPE:
 4817                 break;
 4818 
 4819             default:
 4820                 return DCE2_RET__ERROR;
 4821         }
 4822 
 4823         if (ttracker->disconnect_tid)
 4824             DCE2_SmbRemoveTid(ssd, ssd->cur_rtracker->tid);
 4825     }
 4826 
 4827     return DCE2_RET__SUCCESS;
 4828 }
 4829 
 4830 // SMB_COM_TRANSACTION_SECONDARY
 4831 static DCE2_Ret DCE2_SmbTransactionSecondary(DCE2_SmbSsnData *ssd, const SmbNtHdr *smb_hdr,
 4832         const DCE2_SmbComInfo *com_info, const uint8_t *nb_ptr, uint32_t nb_len)
 4833 {
 4834     DCE2_SmbTransactionTracker *ttracker = &ssd->cur_rtracker->ttracker;
 4835     DCE2_Ret status;
 4836     SFSnortPacket *rpkt = NULL;
 4837 
 4838     if (!DCE2_ComInfoCanProcessCommand(com_info))
 4839         return DCE2_RET__ERROR;
 4840 
 4841     status = DCE2_SmbUpdateTransSecondary(ssd, smb_hdr, com_info, nb_ptr, nb_len);
 4842     if (status != DCE2_RET__FULL)
 4843         return status;
 4844 
 4845     switch (ttracker->subcom)
 4846     {
 4847         case TRANS_TRANSACT_NMPIPE:
 4848         case TRANS_WRITE_NMPIPE:
 4849             {
 4850                 const uint8_t *data_ptr = DCE2_BufferData(ttracker->dbuf);
 4851                 uint32_t data_len = DCE2_BufferLength(ttracker->dbuf);
 4852                 rpkt = DCE2_SmbGetRpkt(ssd, &data_ptr, &data_len, DCE2_RPKT_TYPE__SMB_TRANS);
 4853 
 4854                 if (rpkt == NULL)
 4855                     return DCE2_RET__ERROR;
 4856 
 4857                 DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB, "Reassembled Transaction request\n"));
 4858                 DCE2_DEBUG_CODE(DCE2_DEBUG__MAIN, DCE2_PrintPktData(rpkt->payload, rpkt->payload_size););
 4859 
 4860                 status = DCE2_SmbTransactionReq(ssd, ttracker, data_ptr, data_len,
 4861                         DCE2_BufferData(ttracker->pbuf), DCE2_BufferLength(ttracker->pbuf));
 4862 
 4863                 DCE2_SmbReturnRpkt();
 4864             }
 4865             break;
 4866 
 4867         default:
 4868             status = DCE2_SmbTransactionReq(ssd, ttracker,
 4869                     DCE2_BufferData(ttracker->dbuf), DCE2_BufferLength(ttracker->dbuf),
 4870                     DCE2_BufferData(ttracker->pbuf), DCE2_BufferLength(ttracker->pbuf));
 4871             break;
 4872     }
 4873 
 4874     return status;
 4875 }
 4876 
 4877 // SMB_COM_WRITE_AND_CLOSE
 4878 static DCE2_Ret DCE2_SmbWriteAndClose(DCE2_SmbSsnData *ssd, const SmbNtHdr *smb_hdr,
 4879         const DCE2_SmbComInfo *com_info, const uint8_t *nb_ptr, uint32_t nb_len)
 4880 {
 4881     if (!DCE2_ComInfoCanProcessCommand(com_info))
 4882         return DCE2_RET__ERROR;
 4883 
 4884     if (DCE2_ComInfoIsRequest(com_info))
 4885     {
 4886         // Have at least one byte based on byte count check done earlier
 4887 
 4888         uint16_t com_size = DCE2_ComInfoCommandSize(com_info);
 4889         uint16_t byte_count = DCE2_ComInfoByteCount(com_info);
 4890         uint16_t dcnt = SmbWriteAndCloseReqCount((SmbWriteAndCloseReq *)nb_ptr);
 4891         uint16_t fid = SmbWriteAndCloseReqFid((SmbWriteAndCloseReq *)nb_ptr);
 4892         uint32_t offset = SmbWriteAndCloseReqOffset((SmbWriteAndCloseReq *)nb_ptr);
 4893 
 4894         DCE2_MOVE(nb_ptr, nb_len, (com_size + 1));
 4895 
 4896         if (DCE2_SmbCheckData(ssd, (uint8_t *)smb_hdr, nb_ptr, nb_len,
 4897                     byte_count, dcnt,
 4898                     (uint16_t)(sizeof(SmbNtHdr) + com_size + 1)) != DCE2_RET__SUCCESS)
 4899             return DCE2_RET__ERROR;
 4900 
 4901         if (dcnt == 0)
 4902         {
 4903             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_DCNT_ZERO);
 4904             return DCE2_RET__ERROR;
 4905         }
 4906 
 4907         // WriteAndClose has a 1 byte pad after the byte count
 4908         if ((uint32_t)(dcnt + 1) != (uint32_t)byte_count)
 4909             DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_INVALID_DSIZE, (dcnt + 1), byte_count);
 4910 
 4911         if (dcnt > nb_len)
 4912             dcnt = (uint16_t)nb_len;
 4913 
 4914         return DCE2_SmbProcessRequestData(ssd, fid, nb_ptr, dcnt, offset);
 4915     }
 4916     else
 4917     {
 4918         DCE2_SmbRemoveFileTracker(ssd, ssd->cur_rtracker->ftracker);
 4919     }
 4920 
 4921     return DCE2_RET__SUCCESS;
 4922 }
 4923 
 4924 // SMB_COM_OPEN_ANDX
 4925 static DCE2_Ret DCE2_SmbOpenAndX(DCE2_SmbSsnData *ssd, const SmbNtHdr *smb_hdr,
 4926         const DCE2_SmbComInfo *com_info, const uint8_t *nb_ptr, uint32_t nb_len)
 4927 {
 4928     if (!DCE2_ComInfoCanProcessCommand(com_info))
 4929         return DCE2_RET__ERROR;
 4930 
 4931     if (DCE2_ComInfoIsResponse(com_info))
 4932     {
 4933         const uint16_t fid = SmbOpenAndXRespFid((SmbOpenAndXResp *)nb_ptr);
 4934         const uint16_t file_attrs = SmbOpenAndXRespFileAttrs((SmbOpenAndXResp *)nb_ptr);
 4935         const uint16_t resource_type = SmbOpenAndXRespResourceType((SmbOpenAndXResp *)nb_ptr);
 4936         DCE2_SmbFileTracker *ftracker = NULL;
 4937 
 4938         // Set request tracker's current file tracker in case of chained commands
 4939         switch (SmbAndXCom2((SmbAndXCommon *)nb_ptr))
 4940         {
 4941             // This is in case in the request a write was chained to an open
 4942             // in which case the write will be to the newly opened file
 4943             case SMB_COM_WRITE:
 4944             case SMB_COM_WRITE_ANDX:
 4945             case SMB_COM_TRANSACTION:
 4946             case SMB_COM_READ_ANDX:
 4947                 ftracker = DCE2_SmbDequeueTmpFileTracker(ssd, ssd->cur_rtracker, fid);
 4948                 break;
 4949             default:
 4950                 break;
 4951         }
 4952 
 4953         if (!DCE2_SmbIsTidIPC(ssd, ssd->cur_rtracker->tid)
 4954                 && (SmbFileAttrsDirectory(file_attrs)
 4955                     || !SmbResourceTypeDisk(resource_type)))
 4956         {
 4957             if (ftracker != NULL)
 4958                 DCE2_SmbRemoveFileTracker(ssd, ftracker);
 4959             return DCE2_RET__SUCCESS;
 4960         }
 4961 
 4962         if (ftracker == NULL)
 4963         {
 4964             ftracker = DCE2_SmbNewFileTracker(ssd,
 4965                     ssd->cur_rtracker->uid, ssd->cur_rtracker->tid, fid);
 4966             if (ftracker == NULL)
 4967                 return DCE2_RET__ERROR;
 4968         }
 4969 
 4970         DCE2_Update_Ftracker_from_ReqTracker(ftracker, ssd->cur_rtracker);
 4971 
 4972         if (!ftracker->is_ipc)
 4973         {
 4974             const uint16_t open_results = SmbOpenAndXRespOpenResults((SmbOpenAndXResp *)nb_ptr);
 4975 
 4976             if (SmbOpenResultRead(open_results))
 4977             {
 4978                 ftracker->ff_file_size = SmbOpenAndXRespFileSize((SmbOpenAndXResp *)nb_ptr);
 4979             }
 4980             else
 4981             {
 4982                 ftracker->ff_file_size = ssd->cur_rtracker->file_size;
 4983                 ftracker->ff_file_direction = DCE2_SMB_FILE_DIRECTION__UPLOAD;
 4984             }
 4985         }
 4986 
 4987         ssd->cur_rtracker->ftracker = ftracker;
 4988     }
 4989     else
 4990     {
 4991         uint32_t pad = 0;
 4992         const bool unicode = SmbUnicode(smb_hdr);
 4993         uint8_t null_bytes = unicode ? 2 : 1;
 4994 
 4995         if (!DCE2_SmbIsTidIPC(ssd, ssd->cur_rtracker->tid))
 4996         {
 4997             uint16_t file_attrs = SmbOpenAndXReqFileAttrs((SmbOpenAndXReq *)nb_ptr);
 4998 
 4999             if (SmbEvasiveFileAttrs(file_attrs))
 5000                 DCE2_Alert(&ssd->sd, DCE2_EVENT__SMB_EVASIVE_FILE_ATTRS);
 5001 
 5002             ssd->cur_rtracker->file_size = SmbOpenAndXReqAllocSize((SmbOpenAndXReq *)nb_ptr);
 5003         }
 5004 
 5005         DCE2_MOVE(nb_ptr, nb_len, DCE2_ComInfoCommandSize(com_info));
 5006 
 5007         if (unicode)
 5008             pad = (nb_ptr - (const uint8_t *)smb_hdr) & 1;
 5009 
 5010         if (nb_len < (pad + null_bytes))
 5011             return DCE2_RET__ERROR;
 5012 
 5013         DCE2_MOVE(nb_ptr, nb_len, pad);
 5014 
 5015         // Samba allows chaining OpenAndX/NtCreateAndX so might have
 5016         // already been set.
 5017         if (ssd->cur_rtracker->file_name == NULL)
 5018         {
 5019             ssd->cur_rtracker->file_name =
 5020                 DCE2_SmbGetString(nb_ptr, nb_len, unicode, &ssd->cur_rtracker->file_name_len);
 5021         }
 5022     }
 5023 
 5024     return DCE2_RET__SUCCESS;
 5025 }
 5026 
 5027 // SMB_COM_READ_ANDX
 5028 static DCE2_Ret DCE2_SmbReadAndX(DCE2_SmbSsnData *ssd, const SmbNtHdr *smb_hdr,
 5029         const DCE2_SmbComInfo *com_info, const uint8_t *nb_ptr, uint32_t nb_len)
 5030 {
 5031     if (!DCE2_ComInfoCanProcessCommand(com_info))
 5032         return DCE2_RET__ERROR;
 5033 
 5034     if (DCE2_ComInfoIsRequest(com_info))
 5035     {
 5036         DCE2_SmbFileTracker *ftracker =
 5037             DCE2_SmbGetFileTracker(ssd, SmbReadAndXReqFid((SmbReadAndXReq *)nb_ptr));
 5038 
 5039         // No sense in tracking response
 5040         if (ftracker == NULL)
 5041             return DCE2_RET__ERROR;
 5042 
 5043         if (!ftracker->is_ipc)
 5044             ssd->cur_rtracker->file_offset = SmbReadAndXReqOffset((SmbReadAndXExtReq *)nb_ptr);
 5045 
 5046         // Set this for response
 5047         ssd->cur_rtracker->ftracker = ftracker;
 5048     }
 5049     else
 5050     {
 5051         uint16_t com_size = DCE2_ComInfoCommandSize(com_info);
 5052         uint16_t byte_count = DCE2_ComInfoByteCount(com_info);
 5053         uint16_t doff = SmbReadAndXRespDataOff((SmbReadAndXResp *)nb_ptr);
 5054         uint32_t dcnt = SmbReadAndXRespDataCnt((SmbReadAndXResp *)nb_ptr);
 5055 
 5056         DCE2_MOVE(nb_ptr, nb_len, com_size);
 5057 
 5058         if (DCE2_SmbCheckData(ssd, (uint8_t *)smb_hdr, nb_ptr, nb_len,
 5059                     byte_count, dcnt, doff) != DCE2_RET__SUCCESS)
 5060             return DCE2_RET__ERROR;
 5061 
 5062         // This may move backwards
 5063         DCE2_MOVE(nb_ptr, nb_len, ((uint8_t *)smb_hdr + doff) - nb_ptr);
 5064 
 5065         if (dcnt > nb_len)
 5066             dcnt = nb_len;
 5067 
 5068         return DCE2_SmbProcessResponseData(ssd, nb_ptr, dcnt);
 5069     }
 5070 
 5071     return DCE2_RET__SUCCESS;
 5072 }
 5073 
 5074 // SMB_COM_WRITE_ANDX
 5075 static DCE2_Ret DCE2_SmbWriteAndX(DCE2_SmbSsnData *ssd, const SmbNtHdr *smb_hdr,
 5076         const DCE2_SmbComInfo *com_info, const uint8_t *nb_ptr, uint32_t nb_len)
 5077 {
 5078     if (!DCE2_ComInfoCanProcessCommand(com_info))
 5079     {
 5080         DCE2_SmbFileTracker *ftracker = ssd->cur_rtracker->ftracker;
 5081 
 5082         if ((ftracker != NULL) && ftracker->is_ipc
 5083                 && (ftracker->fp_writex_raw != NULL))
 5084         {
 5085             ftracker->fp_writex_raw->remaining = 0;
 5086             DCE2_BufferEmpty(ftracker->fp_writex_raw->buf);
 5087         }
 5088 
 5089         return DCE2_RET__ERROR;
 5090     }
 5091 
 5092     if (DCE2_ComInfoIsRequest(com_info)
 5093             && (SmbWriteAndXReqStartRaw((SmbWriteAndXReq *)nb_ptr)
 5094                 || SmbWriteAndXReqRaw((SmbWriteAndXReq *)nb_ptr)))
 5095     {
 5096         DCE2_SmbFileTracker *ftracker =
 5097             DCE2_SmbGetFileTracker(ssd, SmbWriteAndXReqFid((SmbWriteAndXReq *)nb_ptr));
 5098 
 5099         // Raw mode is only applicable to named pipes.
 5100         if ((ftracker != NULL) && ftracker->is_ipc)
 5101             return DCE2_SmbWriteAndXRawRequest(ssd, smb_hdr, com_info, nb_ptr, nb_len);
 5102     }
 5103 
 5104     if (DCE2_ComInfoIsRequest(com_info))
 5105     {
 5106         uint16_t com_size = DCE2_ComInfoCommandSize(com_info);
 5107         uint16_t byte_count = DCE2_ComInfoByteCount(com_info);
 5108         uint16_t fid = SmbWriteAndXReqFid((SmbWriteAndXReq *)nb_ptr);
 5109         uint16_t doff = SmbWriteAndXReqDataOff((SmbWriteAndXReq *)nb_ptr);
 5110         uint32_t dcnt = SmbWriteAndXReqDataCnt((SmbWriteAndXReq *)nb_ptr);
 5111         uint64_t offset = SmbWriteAndXReqOffset((SmbWriteAndXExtReq *)nb_ptr);
 5112 
 5113         DCE2_MOVE(nb_ptr, nb_len, com_size);
 5114 
 5115         if (DCE2_SmbCheckData(ssd, (uint8_t *)smb_hdr, nb_ptr, nb_len,
 5116                     byte_count, dcnt, doff) != DCE2_RET__SUCCESS)
 5117             return DCE2_RET__ERROR;
 5118 
 5119         // This may move backwards
 5120         DCE2_MOVE(nb_ptr, nb_len, ((uint8_t *)smb_hdr + doff) - nb_ptr);
 5121 
 5122         if (dcnt > nb_len)
 5123         {
 5124             // Current Samba errors if data count is greater than data left
 5125             if (DCE2_SsnGetPolicy(&ssd->sd) == DCE2_POLICY__SAMBA)
 5126                 return DCE2_RET__ERROR;
 5127 
 5128             // Windows and early Samba just use what's left
 5129             dcnt = nb_len;
 5130         }
 5131 
 5132         return DCE2_SmbProcessRequestData(ssd, fid, nb_ptr, dcnt, offset);
 5133     }
 5134 
 5135     return DCE2_RET__SUCCESS;
 5136 }
 5137 
 5138 // SMB_COM_WRITE_ANDX - raw mode
 5139 static DCE2_Ret DCE2_SmbWriteAndXRawRequest(DCE2_SmbSsnData *ssd, const SmbNtHdr *smb_hdr,
 5140         const DCE2_SmbComInfo *com_info, const uint8_t *nb_ptr, uint32_t nb_len)
 5141 {
 5142     uint16_t com_size = DCE2_ComInfoCommandSize(com_info);
 5143     uint16_t byte_count = DCE2_ComInfoByteCount(com_info);
 5144     uint16_t fid = SmbWriteAndXReqFid((SmbWriteAndXReq *)nb_ptr);
 5145     uint16_t doff = SmbWriteAndXReqDataOff((SmbWriteAndXReq *)nb_ptr);
 5146     uint32_t dcnt = SmbWriteAndXReqDataCnt((SmbWriteAndXReq *)nb_ptr);
 5147     bool start_write_raw = SmbWriteAndXReqStartRaw((SmbWriteAndXReq *)nb_ptr);
 5148     bool continue_write_raw = SmbWriteAndXReqRaw((SmbWriteAndXReq *)nb_ptr);
 5149     uint16_t remaining = SmbWriteAndXReqRemaining((SmbWriteAndXReq *)nb_ptr);
 5150     DCE2_Policy policy = DCE2_SsnGetServerPolicy(&ssd->sd);
 5151     DCE2_SmbFileTracker *ftracker = DCE2_SmbGetFileTracker(ssd, fid);
 5152 
 5153     DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB,
 5154                 "Processing WriteAndX with raw mode flags\n"));
 5155 
 5156     // Set this now for possible reassembled packet
 5157     ssd->cur_rtracker->ftracker = ftracker;
 5158 
 5159     if (ftracker == NULL)
 5160         return DCE2_RET__ERROR;
 5161 
 5162     // Got request to write in raw mode without having gotten the initial
 5163     // raw mode request or got initial raw mode request and then another
 5164     // without having finished the first.
 5165     if ((start_write_raw && (ftracker->fp_writex_raw != NULL)
 5166                 && (ftracker->fp_writex_raw->remaining != 0))
 5167             || (continue_write_raw && ((ftracker->fp_writex_raw == NULL)
 5168                     || (ftracker->fp_writex_raw->remaining == 0))))
 5169     {
 5170         switch (policy)
 5171         {
 5172             case DCE2_POLICY__WIN2000:
 5173             case DCE2_POLICY__WINXP:
 5174             case DCE2_POLICY__WINVISTA:
 5175             case DCE2_POLICY__WIN2003:
 5176             case DCE2_POLICY__WIN2008:
 5177             case DCE2_POLICY__WIN7:
 5178                 if (ftracker->fp_writex_raw != NULL)
 5179                 {
 5180                     ftracker->fp_writex_raw->remaining = 0;
 5181                     DCE2_BufferEmpty(ftracker->fp_writex_raw->buf);
 5182                 }
 5183                 return DCE2_RET__ERROR;
 5184             case DCE2_POLICY__SAMBA:
 5185             case DCE2_POLICY__SAMBA_3_0_37:
 5186             case DCE2_POLICY__SAMBA_3_0_22:
 5187             case DCE2_POLICY__SAMBA_3_0_20:
 5188                 // Samba doesn't do anything special here except if the two
 5189                 // flags are set it walks past the two "length" bytes.
 5190                 // See below.
 5191                 break;
 5192             default:
 5193                 DCE2_Log(DCE2_LOG_TYPE__ERROR, "%s(%d) Invalid policy: %d",
 5194                         __FILE__, __LINE__, policy);
 5195                 break;
 5196         }
 5197     }
 5198 
 5199     DCE2_MOVE(nb_ptr, nb_len, com_size);
 5200 
 5201     if (DCE2_SmbCheckData(ssd, (uint8_t *)smb_hdr, nb_ptr, nb_len,
 5202                 byte_count, dcnt, doff) != DCE2_RET__SUCCESS)
 5203         return DCE2_RET__ERROR;
 5204 
 5205     // This may move backwards
 5206     DCE2_MOVE(nb_ptr, nb_len, ((uint8_t *)smb_hdr + doff) - nb_ptr);
 5207 
 5208     // If a "raw" write is requested there will be two bytes after the
 5209     // header/pad and before the data which is supposed to represent a
 5210     // length but everyone ignores it.  However we need to move past it.
 5211     // This is the one situation where the remaining field matters and
 5212     // should be equal to the total amount of data to be written.
 5213     if (start_write_raw)
 5214     {
 5215         if (dcnt < 2)
 5216             return DCE2_RET__ERROR;
 5217 
 5218         // From data size check above, nb_len >= dsize
 5219         dcnt -= 2;
 5220         DCE2_MOVE(nb_ptr, nb_len, 2);
 5221     }
 5222 
 5223     if (dcnt > nb_len)
 5224         dcnt = nb_len;
 5225 
 5226     // File tracker already validated
 5227     switch (policy)
 5228     {
 5229         case DCE2_POLICY__WIN2000:
 5230         case DCE2_POLICY__WINXP:
 5231         case DCE2_POLICY__WINVISTA:
 5232         case DCE2_POLICY__WIN2003:
 5233         case DCE2_POLICY__WIN2008:
 5234         case DCE2_POLICY__WIN7:
 5235             if (start_write_raw)
 5236             {
 5237                 if (ftracker->fp_writex_raw == NULL)
 5238                 {
 5239                     ftracker->fp_writex_raw = (DCE2_SmbWriteAndXRaw *)
 5240                         DCE2_Alloc(sizeof(DCE2_SmbWriteAndXRaw), DCE2_MEM_TYPE__SMB_FID);
 5241                     if (ftracker->fp_writex_raw == NULL)
 5242                         return DCE2_RET__ERROR;
 5243 
 5244                     ftracker->fp_writex_raw->remaining = (int)remaining;
 5245                 }
 5246             }
 5247 
 5248             ftracker->fp_writex_raw->remaining -= (int)dcnt;
 5249             if (ftracker->fp_writex_raw->remaining < 0)
 5250             {
 5251                 ftracker->fp_writex_raw->remaining = 0;
 5252                 DCE2_BufferEmpty(ftracker->fp_writex_raw->buf);
 5253                 return DCE2_RET__ERROR;
 5254             }
 5255 
 5256             // If the "raw" write isn't finished in the first request
 5257             // and haven't allocated a buffer yet.
 5258             if (start_write_raw && (ftracker->fp_writex_raw->remaining != 0)
 5259                     && (ftracker->fp_writex_raw->buf == NULL))
 5260             {
 5261                 ftracker->fp_writex_raw->buf =
 5262                     DCE2_BufferNew(remaining, 0, DCE2_MEM_TYPE__SMB_FID);
 5263                 if (ftracker->fp_writex_raw->buf == NULL)
 5264                 {
 5265                     ftracker->fp_writex_raw->remaining = 0;
 5266                     return DCE2_RET__ERROR;
 5267                 }
 5268             }
 5269 
 5270             // If data has to be added to buffer, i.e. not a start raw
 5271             // or a start raw and more raw requests to come.
 5272             if (!start_write_raw || (ftracker->fp_writex_raw->remaining != 0))
 5273             {
 5274                 if (DCE2_BufferAddData(ftracker->fp_writex_raw->buf, nb_ptr,
 5275                             dcnt, DCE2_BufferLength(ftracker->fp_writex_raw->buf),
 5276                             DCE2_BUFFER_MIN_ADD_FLAG__IGNORE) != DCE2_RET__SUCCESS)
 5277                 {
 5278                     ftracker->fp_writex_raw->remaining = 0;
 5279                     DCE2_BufferEmpty(ftracker->fp_writex_raw->buf);
 5280                     return DCE2_RET__ERROR;
 5281                 }
 5282 
 5283                 if (ftracker->fp_writex_raw->remaining == 0)
 5284                 {
 5285                     // Create reassembled packet
 5286                     const uint8_t *data_ptr = DCE2_BufferData(ftracker->fp_writex_raw->buf);
 5287                     uint32_t data_len = DCE2_BufferLength(ftracker->fp_writex_raw->buf);
 5288                     SFSnortPacket *rpkt = DCE2_SmbGetRpkt(ssd,
 5289                             &data_ptr, &data_len, DCE2_RPKT_TYPE__SMB_TRANS);
 5290 
 5291                     if (rpkt == NULL)
 5292                     {
 5293                         DCE2_BufferEmpty(ftracker->fp_writex_raw->buf);
 5294                         return DCE2_RET__ERROR;
 5295                     }
 5296 
 5297                     DEBUG_WRAP(DCE2_DebugMsg(DCE2_DEBUG__SMB,
 5298                                 "Reassembled WriteAndX raw mode request\n"));
 5299                     DCE2_DEBUG_CODE(DCE2_DEBUG__MAIN, DCE2_PrintPktData(rpkt->payload, rpkt->payload_size););
 5300 
 5301                     (void)DCE2_SmbProcessRequestData(ssd, fid, data_ptr, data_len, 0);
 5302 
 5303                     DCE2_SmbReturnRpkt();
 5304                     DCE2_BufferEmpty(ftracker->fp_writex_raw->buf);
 5305                 }
 5306             }
 5307             else
 5308             {
 5309                 (void)DCE2_SmbProcessRequestData(ssd, fid, nb_ptr, dcnt, 0);
 5310             }
 5311 
 5312             // Windows doesn't process chained commands to raw WriteAndXs
 5313             // so return error so it exits the loop.
 5314             return DCE2_RET__ERROR;
 5315 
 5316         case DCE2_POLICY__SAMBA:
 5317         case DCE2_POLICY__SAMBA_3_0_37:
 5318         case DCE2_POLICY__SAMBA_3_0_22:
 5319         case DCE2_POLICY__SAMBA_3_0_20:
 5320             // All Samba cares about is skipping the 2 byte "length"
 5321             // if both flags are set.
 5322             break;
 5323         default:
 5324             DCE2_Log(DCE2_LOG_TYPE__ERROR, "%s(%d) Invalid policy: %d",
 5325                     __FILE__, __LINE__, policy);
 5326             break;
 5327     }
 5328 
 5329     return DCE2_SmbProcessRequestData(ssd, fid, nb_ptr, dcnt, 0);