1 //--------------------------------------------------------------------------
2 // Copyright (C) 2016-2021 Cisco and/or its affiliates. All rights reserved.
3 //
4 // This program is free software; you can redistribute it and/or modify it
5 // under the terms of the GNU General Public License Version 2 as published
6 // by the Free Software Foundation.  You may not use, modify or distribute
7 // this program under any other version of the GNU General Public License.
8 //
9 // This program is distributed in the hope that it will be useful, but
10 // WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License along
15 // with this program; if not, write to the Free Software Foundation, Inc.,
16 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 //--------------------------------------------------------------------------
18 
19 // smb_message.cc author Rashmi Pitre <rrp@cisco.com>
20 
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include "smb_message.h"
26 
27 #include "dce_smb_commands.h"
28 #include "dce_smb_module.h"
29 #include "dce_smb_paf.h"
30 #include "dce_smb_transaction.h"
31 #include "detection/detect.h"
32 #include "file_api/file_service.h"
33 #include "main/snort_debug.h"
34 #include "memory/memory_cap.h"
35 #include "packet_io/active.h"
36 #include "protocols/packet.h"
37 #include "utils/util.h"
38 
39 using namespace snort;
40 
41 /********************************************************************
42  * Global variables
43  ********************************************************************/
44 typedef DCE2_Ret (* DCE2_SmbComFunc)(DCE2_SmbSsnData*, const SmbNtHdr*,
45     const DCE2_SmbComInfo*, const uint8_t*, uint32_t);
46 
47 static DCE2_SmbComFunc smb_com_funcs[SMB_MAX_NUM_COMS];
48 static uint8_t smb_wcts[SMB_MAX_NUM_COMS][2][32];
49 static uint16_t smb_bccs[SMB_MAX_NUM_COMS][2][2];
50 static DCE2_SmbComFunc smb_chain_funcs[DCE2_POLICY__MAX][SMB_ANDX_COM__MAX][SMB_MAX_NUM_COMS];
51 static bool smb_deprecated_coms[SMB_MAX_NUM_COMS];
52 static bool smb_unusual_coms[SMB_MAX_NUM_COMS];
53 static SmbAndXCom smb_chain_map[SMB_MAX_NUM_COMS];
54 
55 /********************************************************************
56  * Function: DCE2_SmbIsRawData()
57  *
58  * Purpose:
59  *  To determine if the current state is such that a raw read or
60  *  write is expected.
61  *
62  * Arguments:
63  *  DCE2_SmbSsnData * - Pointer to SMB session data.
64  *
65  * Returns:
66  *  bool -  True if expecting raw data.
67  *          False if not.
68  *
69  ********************************************************************/
DCE2_SmbIsRawData(DCE2_SmbSsnData * ssd)70 static inline bool DCE2_SmbIsRawData(DCE2_SmbSsnData* ssd)
71 {
72     return (ssd->pdu_state == DCE2_SMB_PDU_STATE__RAW_DATA);
73 }
74 
75 /********************************************************************
76  * Function: DCE2_SmbCheckAndXOffset()
77  *
78  * Purpose:
79  *  Validates that the AndXOffset is within bounds of the remaining
80  *  data we have to work with.
81  *
82  * Arguments:
83  *  DCE2_SmbSsnData * - pointer to SMB flow data
84  *  uint8_t * - pointer to where the offset would take us.
85  *  uint8_t * - pointer to bound offset
86  *  uint8_t * - length of data where offset should be within
87  *
88  * Returns:
89  *  DCE2_RET__SUCCESS - Offset is okay.
90  *  DCE2_RET__ERROR   - Offset is bad.
91  *
92  ********************************************************************/
DCE2_SmbCheckAndXOffset(DCE2_SmbSsnData * ssd,const uint8_t * off_ptr,const uint8_t * start_bound,const uint32_t length)93 static inline DCE2_Ret DCE2_SmbCheckAndXOffset(DCE2_SmbSsnData* ssd, const uint8_t* off_ptr,
94     const uint8_t* start_bound, const uint32_t length)
95 {
96     /* Offset should not point within data we just looked at or be equal to
97      * or beyond the length of the NBSS length left */
98     if ((off_ptr < start_bound) ||
99         (off_ptr > (start_bound + length)))
100     {
101         dce_alert(GID_DCE2, DCE2_SMB_BAD_OFF, (dce2CommonStats*)&dce2_smb_stats, ssd->sd);
102 
103         return DCE2_RET__ERROR;
104     }
105 
106     return DCE2_RET__SUCCESS;
107 }
108 
109 /********************************************************************
110  * Function: DCE2_SmbGetIgnorePtr()
111  *
112  * Returns a pointer to the bytes we are ignoring on client or
113  * server side.  Bytes are ignored if they are associated with
114  * data we are not interested in.
115  *
116  * Arguments:
117  *  DCE2_SmbSsnData * - Pointer to SMB session data.
118  *
119  * Returns:
120  *  uint32_t *
121  *      Pointer to the client or server ignore bytes.
122  *
123  ********************************************************************/
DCE2_SmbGetIgnorePtr(DCE2_SmbSsnData * ssd)124 static inline uint32_t* DCE2_SmbGetIgnorePtr(DCE2_SmbSsnData* ssd)
125 {
126     if ( DetectionEngine::get_current_packet()->is_from_server() )
127         return &ssd->srv_ignore_bytes;
128     return &ssd->cli_ignore_bytes;
129 }
130 
131 /********************************************************************
132  * Function: DCE2_SmbGetDataState()
133  *
134  * Returns a pointer to the data state of client or server
135  *
136  * Arguments:
137  *  DCE2_SmbSsnData * - Pointer to SMB session data.
138  *
139  * Returns:
140  *  DCE2_SmbDataState *
141  *      Pointer to the client or server data state.
142  *
143  ********************************************************************/
DCE2_SmbGetDataState(DCE2_SmbSsnData * ssd)144 static inline DCE2_SmbDataState* DCE2_SmbGetDataState(DCE2_SmbSsnData* ssd)
145 {
146     if ( DetectionEngine::get_current_packet()->is_from_server() )
147         return &ssd->srv_data_state;
148     return &ssd->cli_data_state;
149 }
150 
151 /********************************************************************
152  * Function: DCE2_SmbSetValidWordCount()
153  *
154  * Purpose:
155  *  Initializes global data for valid word counts for supported
156  *  SMB command requests and responses.
157  *
158  * Arguments:
159  *  uint8_t - the SMB command code
160  *  uint8_t - SMB_TYPE__REQUEST or SMB_TYPE__RESPONSE
161  *  uint8_t - the valid word count
162  *
163  * Returns: None
164  *
165  ********************************************************************/
DCE2_SmbSetValidWordCount(uint8_t com,uint8_t resp,uint8_t wct)166 static inline void DCE2_SmbSetValidWordCount(uint8_t com,
167     uint8_t resp, uint8_t wct)
168 {
169     smb_wcts[com][resp][wct/8] |= (1 << (wct % 8));
170 }
171 
172 /********************************************************************
173  * Function: DCE2_SmbIsValidWordCount()
174  *
175  * Purpose:
176  *  Checks if a word count is valid for a given command request
177  *  or response.
178  *
179  * Arguments:
180  *  uint8_t - the SMB command code
181  *  uint8_t - SMB_TYPE__REQUEST or SMB_TYPE__RESPONSE
182  *  uint8_t - the word count to validate
183  *
184  * Returns:
185  *  bool - true if valid, false if not valid.
186  *
187  ********************************************************************/
DCE2_SmbIsValidWordCount(uint8_t com,uint8_t resp,uint8_t wct)188 static inline bool DCE2_SmbIsValidWordCount(uint8_t com,
189     uint8_t resp, uint8_t wct)
190 {
191     return (smb_wcts[com][resp][wct/8] & (1 << (wct % 8))) ? true : false;
192 }
193 
194 /********************************************************************
195  * Function: DCE2_SmbSetValidByteCount()
196  *
197  * Purpose:
198  *  Initializes global data for valid byte counts as a range for
199  *  supported SMB command requests and responses.
200  *  Since a byte count is 2 bytes, a 4 byte type is used to store
201  *  the range.  The maximum is in the most significant 2 bytes and
202  *  the minimum in the least significant 2 bytes.
203  *
204  * Arguments:
205  *  uint8_t - the SMB command code
206  *  uint8_t - SMB_TYPE__REQUEST or SMB_TYPE__RESPONSE
207  *  uint8_t - the minimum word count that is valid
208  *  uint8_t - the maximum word count that is valid
209  *
210  * Returns: None
211  *
212  ********************************************************************/
DCE2_SmbSetValidByteCount(uint8_t com,uint8_t resp,uint16_t min,uint16_t max)213 static inline void DCE2_SmbSetValidByteCount(uint8_t com,
214     uint8_t resp, uint16_t min, uint16_t max)
215 {
216     smb_bccs[com][resp][0] = min;
217     smb_bccs[com][resp][1] = max;
218 }
219 
220 /********************************************************************
221  * Function: DCE2_SmbIsValidByteCount()
222  *
223  * Purpose:
224  *  Checks if a byte count is valid for a given command request
225  *  or response.
226  *
227  * Arguments:
228  *  uint8_t - the SMB command code
229  *  uint8_t - SMB_TYPE__REQUEST or SMB_TYPE__RESPONSE
230  *  uint8_t - the byte count to validate
231  *
232  * Returns:
233  *  bool - true if valid, false if not valid.
234  *
235  ********************************************************************/
DCE2_SmbIsValidByteCount(uint8_t com,uint8_t resp,uint16_t bcc)236 static inline bool DCE2_SmbIsValidByteCount(uint8_t com,
237     uint8_t resp, uint16_t bcc)
238 {
239     return ((bcc < smb_bccs[com][resp][0])
240            || (bcc > smb_bccs[com][resp][1])) ? false : true;
241 }
242 
243 // This function is obviously deficient.  Need to do a lot more
244 // testing, research and reading MS-CIFS, MS-SMB and MS-ERREF.
SmbError(const SmbNtHdr * hdr)245 static bool SmbError(const SmbNtHdr* hdr)
246 {
247     if (SmbStatusNtCodes(hdr))
248     {
249         /* Nt status codes are being used.  First 2 bits indicate
250          * severity. */
251         switch (SmbNtStatusSeverity(hdr))
252         {
253         case SMB_NT_STATUS_SEVERITY__SUCCESS:
254         case SMB_NT_STATUS_SEVERITY__INFORMATIONAL:
255         case SMB_NT_STATUS_SEVERITY__WARNING:
256             return false;
257         case SMB_NT_STATUS_SEVERITY__ERROR:
258         default:
259             break;
260         }
261     }
262     else
263     {
264         switch (SmbStatusClass(hdr))
265         {
266         case SMB_ERROR_CLASS__SUCCESS:
267             return false;
268         case SMB_ERROR_CLASS__ERRDOS:
269             if (SmbStatusCode(hdr) == SMB_ERRDOS__MORE_DATA)
270                 return false;
271             break;
272         case SMB_ERROR_CLASS__ERRSRV:
273         case SMB_ERROR_CLASS__ERRHRD:
274         case SMB_ERROR_CLASS__ERRCMD:
275         default:
276             break;
277         }
278     }
279 
280     return true;
281 }
282 
SmbBrokenPipe(const SmbNtHdr * hdr)283 static bool SmbBrokenPipe(const SmbNtHdr* hdr)
284 {
285     if (SmbStatusNtCodes(hdr))
286     {
287         uint32_t nt_status = SmbNtStatus(hdr);
288         if ((nt_status == SMB_NT_STATUS__PIPE_BROKEN)
289             || (nt_status == SMB_NT_STATUS__PIPE_DISCONNECTED))
290             return true;
291     }
292     else
293     {
294         if (SmbStatusClass(hdr) == SMB_ERROR_CLASS__ERRDOS)
295         {
296             uint16_t smb_status = SmbStatusCode(hdr);
297             if ((smb_status == SMB_ERRDOS__BAD_PIPE)
298                 || (smb_status == SMB_ERRDOS__PIPE_NOT_CONNECTED))
299                 return true;
300         }
301     }
302 
303     return false;
304 }
305 
306 /********************************************************************
307  * Function: DCE2_IgnoreJunkData()
308  *
309  * Purpose:
310  *   An evasion technique can be to put a bunch of junk data before
311  *   the actual SMB request and it seems the MS implementation has
312  *   no problem with it and seems to just ignore the data.  This
313  *   function attempts to move past all the junk to get to the
314  *   actual NetBIOS message request.
315  *
316  * Arguments:
317  *   const uint8_t *  - pointer to the current position in the data
318  *      being inspected
319  *   uint16_t  -  the amount of data left to look at
320  *   uint32_t  -  the amount of data to ignore if there doesn't seem
321  *      to be any junk data.  Just use the length as if the bad
322  *      NetBIOS header was good.
323  *
324  * Returns:
325  *    uint32_t - the amount of bytes to ignore as junk.
326  *
327  ********************************************************************/
DCE2_IgnoreJunkData(const uint8_t * data_ptr,uint16_t data_len,uint32_t assumed_nb_len)328 static uint32_t DCE2_IgnoreJunkData(const uint8_t* data_ptr, uint16_t data_len,
329     uint32_t assumed_nb_len)
330 {
331     const uint8_t* tmp_ptr = data_ptr;
332     uint32_t ignore_bytes = 0;
333 
334     /* Try to find \xffSMB and go back 8 bytes to beginning
335      * of what should be a Netbios header with type Session
336      * Message (\x00) - do appropriate buffer checks to make
337      * sure the index is in bounds. Ignore all intervening
338      * bytes */
339 
340     while ((tmp_ptr + sizeof(uint32_t)) <= (data_ptr + data_len))
341     {
342         if ((SmbId((const SmbNtHdr*)tmp_ptr) == DCE2_SMB_ID)
343             || (SmbId((const SmbNtHdr*)tmp_ptr) == DCE2_SMB2_ID))
344         {
345             break;
346         }
347 
348         tmp_ptr++;
349     }
350 
351     if ((tmp_ptr + sizeof(uint32_t)) > (data_ptr + data_len))
352     {
353         ignore_bytes = data_len;
354     }
355     else
356     {
357         if ((tmp_ptr - sizeof(NbssHdr)) > data_ptr)
358             ignore_bytes = (tmp_ptr - data_ptr) - sizeof(NbssHdr);
359         else  /* Just ignore whatever the bad NB header had as a length */
360             ignore_bytes = assumed_nb_len;
361     }
362 
363     return ignore_bytes;
364 }
365 
366 /********************************************************************
367  * Function: DCE2_SmbHdrChecks()
368  *
369  * Checks some relevant fields in the header to make sure they're
370  * sane.
371  * Side effects are potential alerts for anomalous behavior.
372  *
373  * Arguments:
374  *  DCE2_SmbSsnData *
375  *      Pointer to the session data structure.
376  *  SmbNtHdr *
377  *      Pointer to the header struct laid over the packet data.
378  *
379  * Returns:
380  *  DCE2_Ret
381  *      DCE2_RET__IGNORE if we should continue processing, but
382  *          ignore data because of the error.
383  *      DCE2_RET__SUCCESS if we should continue processing.
384  *
385  ********************************************************************/
DCE2_SmbHdrChecks(DCE2_SmbSsnData * ssd,const SmbNtHdr * smb_hdr)386 static DCE2_Ret DCE2_SmbHdrChecks(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr)
387 {
388     Packet* p = DetectionEngine::get_current_packet();
389     bool is_seg_buf = DCE2_SmbIsSegBuffer(ssd, (const uint8_t*)smb_hdr);
390 
391     if ((p->is_from_server() && (SmbType(smb_hdr) == SMB_TYPE__REQUEST)) ||
392         (p->is_from_client() && (SmbType(smb_hdr) == SMB_TYPE__RESPONSE)))
393     {
394         if (is_seg_buf)
395             DCE2_SmbSegAlert(ssd, DCE2_SMB_BAD_TYPE);
396         else
397             dce_alert(GID_DCE2, DCE2_SMB_BAD_TYPE, (dce2CommonStats*)&dce2_smb_stats,
398                 ssd->sd);
399 
400         // Continue looking at traffic.  Neither Windows nor Samba seem
401         // to care, or even look at this flag
402     }
403 
404     if ((SmbId(smb_hdr) != DCE2_SMB_ID)
405         && (SmbId(smb_hdr) != DCE2_SMB2_ID))
406     {
407         if (is_seg_buf)
408             DCE2_SmbSegAlert(ssd, DCE2_SMB_BAD_ID);
409         else
410             dce_alert(GID_DCE2, DCE2_SMB_BAD_ID, (dce2CommonStats*)&dce2_smb_stats,
411                 ssd->sd);
412 
413         return DCE2_RET__IGNORE;
414     }
415 
416     return DCE2_RET__SUCCESS;
417 }
418 
419 /********************************************************************
420  * Function: DCE2_SmbGetMinByteCount()
421  *
422  * Purpose:
423  *  Returns the minimum byte count for the given command request
424  *  or response.
425  *
426  * Arguments:
427  *  uint8_t - the SMB command code
428  *  uint8_t - SMB_TYPE__REQUEST or SMB_TYPE__RESPONSE
429  *
430  * Returns:
431  *  uint16_t - the minimum byte count
432  *
433  ********************************************************************/
DCE2_SmbGetMinByteCount(uint8_t com,uint8_t resp)434 static inline uint16_t DCE2_SmbGetMinByteCount(uint8_t com, uint8_t resp)
435 {
436     return smb_bccs[com][resp][0];
437 }
438 
DCE2_SmbFindRequestTracker(DCE2_SmbSsnData * ssd,const SmbNtHdr * smb_hdr)439 static DCE2_SmbRequestTracker* DCE2_SmbFindRequestTracker(DCE2_SmbSsnData* ssd,
440     const SmbNtHdr* smb_hdr)
441 {
442     uint16_t uid = SmbUid(smb_hdr);
443     uint16_t tid = SmbTid(smb_hdr);
444     uint16_t pid = SmbPid(smb_hdr);
445     uint16_t mid = SmbMid(smb_hdr);
446 
447     DCE2_SmbRequestTracker* tmp_rtracker = &ssd->rtracker;
448     int smb_com = SmbCom(smb_hdr);
449     switch (smb_com)
450     {
451     case SMB_COM_TRANSACTION_SECONDARY:
452         smb_com = SMB_COM_TRANSACTION;
453         break;
454     case SMB_COM_TRANSACTION2_SECONDARY:
455         smb_com = SMB_COM_TRANSACTION2;
456         break;
457     case SMB_COM_NT_TRANSACT_SECONDARY:
458         smb_com = SMB_COM_NT_TRANSACT;
459         break;
460     case SMB_COM_WRITE_COMPLETE:
461         smb_com = SMB_COM_WRITE_RAW;
462         break;
463     default:
464         break;
465     }
466 
467     DCE2_SmbRequestTracker* first_rtracker = nullptr;
468     DCE2_SmbRequestTracker* win_rtracker = nullptr;
469     DCE2_SmbRequestTracker* first_mid_rtracker = nullptr;
470     DCE2_SmbRequestTracker* ret_rtracker = nullptr;
471     while (tmp_rtracker != nullptr)
472     {
473         if ((tmp_rtracker->mid == (int)mid) && (tmp_rtracker->smb_com == smb_com))
474         {
475             // This is the normal case except for SessionSetupAndX and
476             // TreeConnect/TreeConnectAndX which will fall into the
477             // default case below.
478             if ((tmp_rtracker->pid == pid) && (tmp_rtracker->uid == uid)
479                 && (tmp_rtracker->tid == tid))
480             {
481                 ret_rtracker = tmp_rtracker;
482             }
483             else
484             {
485                 switch (smb_com)
486                 {
487                 case SMB_COM_TRANSACTION:
488                 case SMB_COM_TRANSACTION2:
489                 case SMB_COM_NT_TRANSACT:
490                 case SMB_COM_TRANSACTION_SECONDARY:
491                 case SMB_COM_TRANSACTION2_SECONDARY:
492                 case SMB_COM_NT_TRANSACT_SECONDARY:
493                     // These should conform to above
494                     break;
495                 default:
496                     if (tmp_rtracker->pid == pid)
497                         ret_rtracker = tmp_rtracker;
498                     break;
499                 }
500             }
501 
502             if (ret_rtracker != nullptr)
503             {
504                 return ret_rtracker;
505             }
506 
507             // Take the first one where the PIDs also match
508             // in the case of the Transacts above
509             if ((tmp_rtracker->pid == pid) && (win_rtracker == nullptr))
510                 win_rtracker = tmp_rtracker;
511 
512             // Set this to the first matching request in the queue
513             // where the Mid matches.  Don't set for Windows if from
514             // client since PID/MID are necessary
515             if (((DCE2_SmbType() == SMB_TYPE__RESPONSE)
516                 || !DCE2_SsnIsWindowsPolicy(&ssd->sd))
517                 && first_mid_rtracker == nullptr)
518             {
519                 first_mid_rtracker = tmp_rtracker;
520             }
521         }
522 
523         // Set the first one we see for early Samba versions
524         if ((first_rtracker == nullptr) && (tmp_rtracker->mid != DCE2_SENTINEL)
525             && (tmp_rtracker->smb_com == smb_com))
526             first_rtracker = tmp_rtracker;
527 
528         // Look at the next request in the queue
529         if (tmp_rtracker == &ssd->rtracker)
530             tmp_rtracker = (DCE2_SmbRequestTracker*)DCE2_QueueFirst(ssd->rtrackers);
531         else
532             tmp_rtracker = (DCE2_SmbRequestTracker*)DCE2_QueueNext(ssd->rtrackers);
533     }
534 
535     DCE2_Policy policy = DCE2_SsnGetPolicy(&ssd->sd);
536     switch (policy)
537     {
538     case DCE2_POLICY__SAMBA_3_0_20:
539     case DCE2_POLICY__SAMBA_3_0_22:
540         ret_rtracker = first_rtracker;
541         break;
542     case DCE2_POLICY__SAMBA:
543     case DCE2_POLICY__SAMBA_3_0_37:
544         ret_rtracker = first_mid_rtracker;
545         break;
546     case DCE2_POLICY__WIN2000:
547     case DCE2_POLICY__WINXP:
548     case DCE2_POLICY__WINVISTA:
549     case DCE2_POLICY__WIN2003:
550     case DCE2_POLICY__WIN2008:
551     case DCE2_POLICY__WIN7:
552         if (win_rtracker != nullptr)
553             ret_rtracker = win_rtracker;
554         else
555             ret_rtracker = first_mid_rtracker;
556         break;
557     default:
558         assert(false);
559         break;
560     }
561 
562     return ret_rtracker;
563 }
564 
565 /********************************************************************
566  * Function: DCE2_SmbCheckCommand()
567  *
568  * Purpose:
569  *  Checks basic validity of an SMB command.
570  *
571  * Arguments:
572  *  DCE2_SmbSsnData * - pointer to session data structure
573  *  SmbNtHdr *        - pointer to the SMB header structure
574  *  uint8_t           - the SMB command code, i.e. SMB_COM_*
575  *  uint8_t *         - current pointer to data, i.e. the command
576  *  uint32_t          - the remaining length
577  *  DCE2_SmbComInfo & -
578  *      Populated structure for command processing
579  *
580  * Returns: None
581  *
582  ********************************************************************/
DCE2_SmbCheckCommand(DCE2_SmbSsnData * ssd,const SmbNtHdr * smb_hdr,const uint8_t smb_com,const uint8_t * nb_ptr,uint32_t nb_len,DCE2_SmbComInfo & com_info)583 static void DCE2_SmbCheckCommand(DCE2_SmbSsnData* ssd,
584     const SmbNtHdr* smb_hdr, const uint8_t smb_com,
585     const uint8_t* nb_ptr, uint32_t nb_len, DCE2_SmbComInfo& com_info)
586 {
587     // Check for server error response
588     if (com_info.smb_type == SMB_TYPE__RESPONSE)
589     {
590         const SmbEmptyCom* ec = (const SmbEmptyCom*)nb_ptr;
591 
592         // Verify there is enough data to do checks
593         if (nb_len < sizeof(SmbEmptyCom))
594         {
595             dce_alert(GID_DCE2, DCE2_SMB_NB_LT_COM, (dce2CommonStats*)&dce2_smb_stats,
596                 ssd->sd);
597             com_info.cmd_error |= DCE2_SMB_COM_ERROR__BAD_LENGTH;
598             return;
599         }
600 
601         // If word and byte counts are zero and there is an error
602         // the server didn't accept client request
603         if ((SmbEmptyComWct(ec) == 0)
604             && (SmbEmptyComBcc(ec) == 0) && SmbError(smb_hdr))
605         {
606             // If broken pipe, clean up data associated with open named pipe
607             if (SmbBrokenPipe(smb_hdr))
608             {
609                 DCE2_SmbRemoveFileTracker(ssd, ssd->cur_rtracker->ftracker);
610             }
611 
612             com_info.cmd_error |= DCE2_SMB_COM_ERROR__STATUS_ERROR;
613             return;
614         }
615     }
616 
617     // Set the header size to the minimum size the command can be
618     // without the byte count to make sure there is enough data to
619     // get the word count.
620     SmbAndXCom andx_com = smb_chain_map[smb_com];
621     int chk_com_size;
622     if (andx_com == SMB_ANDX_COM__NONE)
623         chk_com_size = sizeof(SmbCommon);
624     else
625         chk_com_size = sizeof(SmbAndXCommon);
626 
627     // Verify there is enough data to do checks
628     if (nb_len < (uint32_t)chk_com_size)
629     {
630         dce_alert(GID_DCE2, DCE2_SMB_NB_LT_COM, (dce2CommonStats*)&dce2_smb_stats,
631             ssd->sd);
632         com_info.cmd_error |= DCE2_SMB_COM_ERROR__BAD_LENGTH;
633         return;
634     }
635 
636     const SmbCommon* sc = (const SmbCommon*)nb_ptr;
637     com_info.word_count = SmbWct(sc);
638 
639     // Make sure the word count is a valid one for the command.  If not
640     // testing shows an error will be returned.  And command structures
641     // won't lie on data correctly and out of bounds data accesses are possible.
642     if (!DCE2_SmbIsValidWordCount(smb_com, (uint8_t)com_info.smb_type, com_info.word_count))
643     {
644         dce_alert(GID_DCE2, DCE2_SMB_BAD_WCT, (dce2CommonStats*)&dce2_smb_stats, ssd->sd);
645         com_info.cmd_error |= DCE2_SMB_COM_ERROR__INVALID_WORD_COUNT;
646         return;
647     }
648 
649     // This gets the size of the SMB command from word count through byte count
650     // using the advertised value in the word count field.
651     com_info.cmd_size = (uint16_t)SMB_COM_SIZE(com_info.word_count);
652     if (nb_len < com_info.cmd_size)
653     {
654         dce_alert(GID_DCE2, DCE2_SMB_NB_LT_COM, (dce2CommonStats*)&dce2_smb_stats,
655             ssd->sd);
656         com_info.cmd_error |= DCE2_SMB_COM_ERROR__BAD_LENGTH;
657         return;
658     }
659 
660     uint16_t smb_bcc = SmbBcc(nb_ptr, com_info.cmd_size);
661 
662     // SMB_COM_NT_CREATE_ANDX is a special case.  Who know what's going
663     // on with the word count (see MS-CIFS and MS-SMB).  A 42 word count
664     // command seems to actually have 50 words, so who knows where the
665     // byte count is.  Just set to zero since it's not needed.
666     if ((smb_com == SMB_COM_NT_CREATE_ANDX)
667         && (com_info.smb_type == SMB_TYPE__RESPONSE))
668         smb_bcc = 0;
669 
670     // If byte count is deemed invalid, alert but continue processing
671     switch (smb_com)
672     {
673     // Interim responses
674     case SMB_COM_TRANSACTION:
675     case SMB_COM_TRANSACTION2:
676     case SMB_COM_NT_TRANSACT:
677         // If word count is 0, byte count must be 0
678         if ((com_info.word_count == 0) && (com_info.smb_type == SMB_TYPE__RESPONSE))
679         {
680             if (smb_bcc != 0)
681             {
682                 dce_alert(GID_DCE2, DCE2_SMB_BAD_BCC, (dce2CommonStats*)&dce2_smb_stats,
683                     ssd->sd);
684                 com_info.cmd_error |= DCE2_SMB_COM_ERROR__INVALID_BYTE_COUNT;
685             }
686             break;
687         }
688     // Fall through
689     default:
690         if (!DCE2_SmbIsValidByteCount(smb_com, (uint8_t)com_info.smb_type, smb_bcc))
691         {
692             dce_alert(GID_DCE2, DCE2_SMB_BAD_BCC, (dce2CommonStats*)&dce2_smb_stats,
693                 ssd->sd);
694             com_info.cmd_error |= DCE2_SMB_COM_ERROR__INVALID_BYTE_COUNT;
695         }
696         break;
697     }
698 
699     // Move just past byte count field which is the end of the command
700     nb_len -= com_info.cmd_size;
701 
702     // Validate that there is enough data to be able to process the command
703     if (nb_len < DCE2_SmbGetMinByteCount(smb_com, (uint8_t)com_info.smb_type))
704     {
705         dce_alert(GID_DCE2, DCE2_SMB_NB_LT_BCC, (dce2CommonStats*)&dce2_smb_stats,
706             ssd->sd);
707         com_info.cmd_error |= DCE2_SMB_COM_ERROR__BAD_LENGTH;
708     }
709 
710     // The byte count seems to be ignored by Windows and current Samba (3.5.4)
711     // as long as it is less than the amount of data left.  If more, an error
712     // is returned.
713     // !!!WARNING!!! the byte count should probably never be used.
714     if (smb_bcc > nb_len)
715     {
716         dce_alert(GID_DCE2, DCE2_SMB_NB_LT_BCC, (dce2CommonStats*)&dce2_smb_stats,
717             ssd->sd);
718         // Large byte count doesn't seem to matter for early Samba
719         switch (DCE2_SsnGetPolicy(&ssd->sd))
720         {
721         case DCE2_POLICY__SAMBA_3_0_20:
722         case DCE2_POLICY__SAMBA_3_0_22:
723         case DCE2_POLICY__SAMBA_3_0_37:
724             break;
725         default:
726             com_info.cmd_error |= DCE2_SMB_COM_ERROR__BAD_LENGTH;
727             break;
728         }
729     }
730     else if ((smb_bcc == 0) && (SmbCom(smb_hdr) == SMB_COM_TRANSACTION)
731         && (DCE2_SmbType() == SMB_TYPE__REQUEST)
732         && (DCE2_SsnGetPolicy(&ssd->sd) == DCE2_POLICY__SAMBA))
733     {
734         // Current Samba errors on a zero byte count Transaction because it
735         // uses it to get the Name string and if zero Name will be null and
736         // it won't process it.
737         com_info.cmd_error |= DCE2_SMB_COM_ERROR__BAD_LENGTH;
738     }
739 
740     com_info.byte_count = smb_bcc;
741 }
742 
743 /********************************************************************
744  * Function: DCE2_SmbProcessCommand()
745  *
746  * Purpose:
747  *  This is the main function for handling SMB commands and command
748  *  chaining.
749  *  It does an initial check of the command to determine validity
750  *  and gets basic information about the command.  Then it calls the
751  *  specific command function (setup in DCE2_SmbInitGlobals).
752  *  If there is command chaining, it will do the chaining foo to
753  *  get to the next command.
754  *
755  * Arguments:
756  *  DCE2_SmbSsnData * - pointer to session data structure
757  *  SmbNtHdr *        - pointer to the SMB header structure
758  *  uint8_t *         - current pointer to data, i.e. the command
759  *  uint32_t          - the remaining length
760  *
761  * Returns: None
762  *
763  ********************************************************************/
DCE2_SmbProcessCommand(DCE2_SmbSsnData * ssd,const SmbNtHdr * smb_hdr,const uint8_t * nb_ptr,uint32_t nb_len)764 static void DCE2_SmbProcessCommand(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
765     const uint8_t* nb_ptr, uint32_t nb_len)
766 {
767     uint8_t smb_com = SmbCom(smb_hdr);
768     DCE2_Ret status = DCE2_RET__ERROR;
769     bool sess_chain = false;
770     bool tree_chain = false;
771     bool open_chain = false;
772     int num_chained = 0;
773 
774     while (nb_len > 0)
775     {
776         if (ssd->block_pdus && (DCE2_SmbType() == SMB_TYPE__REQUEST))
777         {
778             Packet* p = DetectionEngine::get_current_packet();
779             p->active->drop_packet(p);
780             status = DCE2_RET__IGNORE;
781             break;
782         }
783         // Break out if command not supported
784         if (smb_com_funcs[smb_com] == nullptr)
785             break;
786 
787         if (smb_deprecated_coms[smb_com])
788         {
789             dce_alert(GID_DCE2, DCE2_SMB_DEPR_COMMAND_USED, (dce2CommonStats*)&dce2_smb_stats,
790                 ssd->sd);
791         }
792 
793         if (smb_unusual_coms[smb_com])
794         {
795             dce_alert(GID_DCE2, DCE2_SMB_UNUSUAL_COMMAND_USED, (dce2CommonStats*)&dce2_smb_stats,
796                 ssd->sd);
797         }
798 
799         DCE2_SmbComInfo com_info;
800         com_info.smb_type = DCE2_SmbType();
801         com_info.cmd_error = DCE2_SMB_COM_ERROR__COMMAND_OK;
802         com_info.word_count = 0;
803         com_info.smb_com = smb_com;
804         com_info.cmd_size = 0;
805         com_info.byte_count = 0;
806         DCE2_SmbCheckCommand(ssd, smb_hdr, smb_com, nb_ptr, nb_len, com_info);
807 	    SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
808 	        DetectionEngine::get_current_packet(),
809 	        "Processing command: %s (0x%02X)\n", get_smb_com_string(smb_com), smb_com);
810 
811         // Note that even if the command shouldn't be processed, some of
812         // the command functions need to know and do cleanup or some other
813         // processing.
814         status = smb_com_funcs[smb_com](ssd, smb_hdr,
815                 &com_info, nb_ptr, nb_len);
816 
817         if (status != DCE2_RET__SUCCESS)
818             break;
819 
820         // This command is not chainable
821         SmbAndXCom andx_com = smb_chain_map[smb_com];
822         if (andx_com == SMB_ANDX_COM__NONE)
823             break;
824 
825         /**********************************************************
826          * AndX Chaining
827          **********************************************************/
828         const SmbAndXCommon* andx_ptr = (const SmbAndXCommon*)nb_ptr;
829         uint8_t smb_com2 = SmbAndXCom2(andx_ptr);
830         if (smb_com2 == SMB_COM_NO_ANDX_COMMAND)
831             break;
832 
833         SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_DEBUG_LEVEL,
834 	    DetectionEngine::get_current_packet(),
835 	    "Chained SMB command: %s\n", get_smb_com_string(smb_com2));
836 
837         num_chained++;
838         if (DCE2_ScSmbMaxChain((dce2SmbProtoConf*)ssd->sd.config) &&
839             (num_chained >= DCE2_ScSmbMaxChain((dce2SmbProtoConf*)ssd->sd.config)))
840         {
841             dce_alert(GID_DCE2, DCE2_SMB_EXCESSIVE_CHAINING, (dce2CommonStats*)&dce2_smb_stats,
842                 ssd->sd);
843         }
844 
845         // Multiple SessionSetupAndX, TreeConnectAndX, OpenAndX and NtCreateAndX
846         // are only allowed by Samba.
847         if (smb_com == SMB_COM_SESSION_SETUP_ANDX)
848             sess_chain = true;
849 
850         // Check for multiple chained SessionSetupAndX
851         if ((smb_com2 == SMB_COM_SESSION_SETUP_ANDX) && sess_chain)
852         {
853             // There is only one place to return a uid.
854             dce_alert(GID_DCE2, DCE2_SMB_MULT_CHAIN_SS, (dce2CommonStats*)&dce2_smb_stats,
855                 ssd->sd);
856             // FIXIT-L Should we continue processing?
857             break;
858         }
859 
860         // Check for chained SessionSetupAndX => .? => LogoffAndX
861         if ((smb_com2 == SMB_COM_LOGOFF_ANDX) && sess_chain)
862         {
863             // This essentially deletes the uid created by the login
864             // and doesn't make any sense.
865             dce_alert(GID_DCE2, DCE2_SMB_CHAIN_SS_LOGOFF, (dce2CommonStats*)&dce2_smb_stats,
866                 ssd->sd);
867         }
868 
869         if (smb_com == SMB_COM_TREE_CONNECT_ANDX)
870             tree_chain = true;
871 
872         // Check for multiple chained TreeConnects
873         if (((smb_com2 == SMB_COM_TREE_CONNECT_ANDX)
874             || (smb_com2 == SMB_COM_TREE_CONNECT)) && tree_chain)
875         {
876             // There is only one place to return a tid.
877             dce_alert(GID_DCE2, DCE2_SMB_MULT_CHAIN_TC, (dce2CommonStats*)&dce2_smb_stats,
878                 ssd->sd);
879             // FIXIT-L Should we continue processing?
880             break;
881         }
882 
883         // Check for chained TreeConnectAndX => .? => TreeDisconnect
884         if ((smb_com2 == SMB_COM_TREE_DISCONNECT) && tree_chain)
885         {
886             // This essentially deletes the tid created by the tree connect
887             // and doesn't make any sense.
888             dce_alert(GID_DCE2, DCE2_SMB_CHAIN_TC_TDIS, (dce2CommonStats*)&dce2_smb_stats,
889                 ssd->sd);
890         }
891 
892         if ((smb_com == SMB_COM_OPEN_ANDX) || (smb_com == SMB_COM_NT_CREATE_ANDX))
893             open_chain = true;
894 
895         // Check for chained OpenAndX/NtCreateAndX => .? => Close
896         if ((smb_com2 == SMB_COM_CLOSE) && open_chain)
897         {
898             // This essentially deletes the fid created by the open command
899             // and doesn't make any sense.
900             dce_alert(GID_DCE2, DCE2_SMB_CHAIN_OPEN_CLOSE, (dce2CommonStats*)&dce2_smb_stats,
901                 ssd->sd);
902         }
903 
904         // Check that policy allows for such chaining
905         DCE2_Policy policy = DCE2_SsnGetServerPolicy(&ssd->sd);
906         if (smb_chain_funcs[policy][andx_com][smb_com2] == nullptr)
907             break;
908 
909         dce2_move(nb_ptr, nb_len, DCE2_ComInfoCommandSize(&com_info));
910 
911         // FIXIT-L Need to test out of order chaining
912         const uint8_t* off2_ptr = (const uint8_t*)smb_hdr + SmbAndXOff2(andx_ptr);
913         if (DCE2_SmbCheckAndXOffset(ssd, off2_ptr, nb_ptr, nb_len) != DCE2_RET__SUCCESS)
914             break;
915 
916         dce2_move(nb_ptr, nb_len, (off2_ptr - nb_ptr));
917 
918         // FIXIT-L Need to test more.
919         switch (smb_com)
920         {
921         case SMB_COM_SESSION_SETUP_ANDX:
922         case SMB_COM_TREE_CONNECT_ANDX:
923         case SMB_COM_OPEN_ANDX:
924         case SMB_COM_NT_CREATE_ANDX:
925             switch (smb_com2)
926             {
927             case SMB_COM_WRITE:
928             case SMB_COM_WRITE_ANDX:
929             case SMB_COM_TRANSACTION:
930             case SMB_COM_READ_ANDX:
931                 if ( DetectionEngine::get_current_packet()->is_from_client() && open_chain)
932                 {
933                     DCE2_SmbQueueTmpFileTracker(ssd, ssd->cur_rtracker,
934                         SmbUid(smb_hdr), SmbTid(smb_hdr));
935                 }
936                 break;
937             default:
938                 break;
939             }
940             break;
941         default:
942             break;
943         }
944 
945         smb_com = smb_com2;
946     }
947 
948     int smb_type = DCE2_SmbType();
949     if (smb_type == SMB_TYPE__RESPONSE)
950     {
951         switch (smb_com)
952         {
953         case SMB_COM_TRANSACTION:
954         case SMB_COM_TRANSACTION2:
955         case SMB_COM_NT_TRANSACT:
956         case SMB_COM_TRANSACTION_SECONDARY:
957         case SMB_COM_TRANSACTION2_SECONDARY:
958         case SMB_COM_NT_TRANSACT_SECONDARY:
959             // This case means there was an error with the initial response
960             // so the tracker isn't yet officially in response mode
961             if (ssd->cur_rtracker->ttracker.smb_type == SMB_TYPE__REQUEST)
962             {
963                 // Samba throws out entire transaction and Windows just this request
964                 if (DCE2_SsnIsServerSambaPolicy(&ssd->sd) && (status != DCE2_RET__SUCCESS))
965                     break;
966 
967                 if (!DCE2_SmbIsTransactionComplete(&ssd->cur_rtracker->ttracker))
968                     return;
969             }
970             else
971             {
972                 if ((status == DCE2_RET__SUCCESS)
973                     && !DCE2_SmbIsTransactionComplete(&ssd->cur_rtracker->ttracker))
974                     return;
975             }
976             break;
977         case SMB_COM_WRITE_RAW:
978             if ((status == DCE2_RET__SUCCESS)
979                 && (ssd->cur_rtracker->writeraw_remaining != 0))
980                 return;
981             break;
982         default:
983             break;
984         }
985     }
986     else if (status != DCE2_RET__IGNORE)
987     {
988         switch (smb_com)
989         {
990         case SMB_COM_TRANSACTION:
991         case SMB_COM_TRANSACTION_SECONDARY:
992             if (DCE2_SsnIsWindowsPolicy(&ssd->sd))
993             {
994                 if (!ssd->cur_rtracker->ttracker.one_way
995                     || !DCE2_SmbIsTransactionComplete(&ssd->cur_rtracker->ttracker))
996                     return;
997 
998                 // Remove the request tracker if transaction is one-way and
999                 // all data and parameters have been sent
1000                 break;
1001             }
1002         default:
1003             // Anything else, keep the request tracker
1004             return;
1005         }
1006     }
1007 
1008     DCE2_SmbRemoveRequestTracker(ssd, ssd->cur_rtracker);
1009     ssd->cur_rtracker = nullptr;
1010 }
1011 
1012 /********************************************************************
1013  * Function: DCE2_SmbInspect()
1014  *
1015  * Purpose:
1016  *  Determines whether the SMB command is something the inspector
1017  *  needs to inspect.
1018  *  This function returns a DCE2_SmbRequestTracker which tracks command
1019  *  requests / responses.
1020  *
1021  * Arguments:
1022  *  DCE2_SmbSsnData * - the session data structure.
1023  *  const SmbNtHdr *  - pointer to the SMB header.
1024  *
1025  * Returns:
1026  *  DCE2_SmbRequestTracker * - nullptr if it's not something we want to or can
1027  *                     inspect.
1028  *                     Otherwise an initialized structure if request
1029  *                     and the found structure if response.
1030  *
1031  ********************************************************************/
DCE2_SmbInspect(DCE2_SmbSsnData * ssd,const SmbNtHdr * smb_hdr)1032 static DCE2_SmbRequestTracker* DCE2_SmbInspect(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr)
1033 {
1034     int smb_com = SmbCom(smb_hdr);
1035 
1036     if (smb_com < 0 or smb_com > 255) return nullptr;
1037 
1038     SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
1039         DetectionEngine::get_current_packet(),
1040 	"SMB command: %s (0x%02X)\n", get_smb_com_string(smb_com), smb_com);
1041 
1042     if (smb_com_funcs[smb_com] == nullptr)
1043     {
1044         return nullptr;
1045     }
1046 
1047     // See if this is something we need to inspect
1048     DCE2_Policy policy = DCE2_SsnGetServerPolicy(&ssd->sd);
1049     DCE2_SmbRequestTracker* rtracker = nullptr;
1050     if (DCE2_SmbType() == SMB_TYPE__REQUEST)
1051     {
1052         switch (smb_com)
1053         {
1054         case SMB_COM_NEGOTIATE:
1055             if (ssd->ssn_state_flags & DCE2_SMB_SSN_STATE__NEGOTIATED)
1056             {
1057                 dce_alert(GID_DCE2, DCE2_SMB_MULTIPLE_NEGOTIATIONS,
1058                     (dce2CommonStats*)&dce2_smb_stats, ssd->sd);
1059                 return nullptr;
1060             }
1061             break;
1062         case SMB_COM_SESSION_SETUP_ANDX:
1063             break;
1064         case SMB_COM_TREE_CONNECT:
1065         case SMB_COM_TREE_CONNECT_ANDX:
1066         case SMB_COM_RENAME:
1067         case SMB_COM_LOGOFF_ANDX:
1068             if (DCE2_SmbFindUid(ssd, SmbUid(smb_hdr)) != DCE2_RET__SUCCESS)
1069                 return nullptr;
1070             break;
1071         default:
1072             if (DCE2_SmbFindTid(ssd, SmbTid(smb_hdr)) != DCE2_RET__SUCCESS)
1073                 return nullptr;
1074 
1075             if (DCE2_SmbIsTidIPC(ssd, SmbTid(smb_hdr)))
1076             {
1077                 switch (smb_com)
1078                 {
1079                 case SMB_COM_OPEN:
1080                 case SMB_COM_CREATE:
1081                 case SMB_COM_CREATE_NEW:
1082                 case SMB_COM_WRITE_AND_CLOSE:
1083                 case SMB_COM_WRITE_AND_UNLOCK:
1084                 case SMB_COM_READ:
1085                     // Samba doesn't allow these commands under an IPC tree
1086                     switch (policy)
1087                     {
1088                     case DCE2_POLICY__SAMBA:
1089                     case DCE2_POLICY__SAMBA_3_0_37:
1090                     case DCE2_POLICY__SAMBA_3_0_22:
1091                     case DCE2_POLICY__SAMBA_3_0_20:
1092                         return nullptr;
1093                     default:
1094                         break;
1095                     }
1096                     break;
1097                 case SMB_COM_READ_RAW:
1098                 case SMB_COM_WRITE_RAW:
1099                     // Samba and Windows Vista on don't allow these commands
1100                     // under an IPC tree, whether or not the raw read/write
1101                     // flag is set in the Negotiate capabilities.
1102                     // Windows RSTs the connection and Samba FINs it.
1103                     switch (policy)
1104                     {
1105                     case DCE2_POLICY__WINVISTA:
1106                     case DCE2_POLICY__WIN2008:
1107                     case DCE2_POLICY__WIN7:
1108                     case DCE2_POLICY__SAMBA:
1109                     case DCE2_POLICY__SAMBA_3_0_37:
1110                     case DCE2_POLICY__SAMBA_3_0_22:
1111                     case DCE2_POLICY__SAMBA_3_0_20:
1112                         return nullptr;
1113                     default:
1114                         break;
1115                     }
1116                     break;
1117                 case SMB_COM_LOCK_AND_READ:
1118                     // The lock will fail so the read won't happen
1119                     return nullptr;
1120                 default:
1121                     break;
1122                 }
1123             }
1124             else      // Not IPC
1125             {
1126                 switch (smb_com)
1127                 {
1128                 // These commands are only used for IPC
1129                 case SMB_COM_TRANSACTION:
1130                 case SMB_COM_TRANSACTION_SECONDARY:
1131                     return nullptr;
1132                 case SMB_COM_READ_RAW:
1133                 case SMB_COM_WRITE_RAW:
1134                     // Windows Vista on don't seem to support these
1135                     // commands, whether or not the raw read/write
1136                     // flag is set in the Negotiate capabilities.
1137                     // Windows RSTs the connection.
1138                     switch (policy)
1139                     {
1140                     case DCE2_POLICY__WINVISTA:
1141                     case DCE2_POLICY__WIN2008:
1142                     case DCE2_POLICY__WIN7:
1143                         return nullptr;
1144                     default:
1145                         break;
1146                     }
1147                     break;
1148                 default:
1149                     break;
1150                 }
1151             }
1152             break;
1153         }
1154 
1155         switch (smb_com)
1156         {
1157         case SMB_COM_TRANSACTION_SECONDARY:
1158         case SMB_COM_TRANSACTION2_SECONDARY:
1159         case SMB_COM_NT_TRANSACT_SECONDARY:
1160             rtracker = DCE2_SmbFindRequestTracker(ssd, smb_hdr);
1161             break;
1162         case SMB_COM_TRANSACTION:
1163         case SMB_COM_TRANSACTION2:
1164         case SMB_COM_NT_TRANSACT:
1165             // If there is already and existing request tracker
1166             // and the transaction is not complete, server will
1167             // return an error.
1168             rtracker = DCE2_SmbFindRequestTracker(ssd, smb_hdr);
1169             if (rtracker != nullptr)
1170                 break;
1171         // Fall through
1172         default:
1173             rtracker = DCE2_SmbNewRequestTracker(ssd, smb_hdr);
1174             break;
1175         }
1176     }
1177     else
1178     {
1179         rtracker = DCE2_SmbFindRequestTracker(ssd, smb_hdr);
1180     }
1181 
1182     return rtracker;
1183 }
1184 
DCE2_SmbProcessRawData(DCE2_SmbSsnData * ssd,const uint8_t * nb_ptr,uint32_t nb_len)1185 static void DCE2_SmbProcessRawData(DCE2_SmbSsnData* ssd, const uint8_t* nb_ptr, uint32_t nb_len)
1186 {
1187     DCE2_SmbFileTracker* ftracker = ssd->cur_rtracker->ftracker;
1188     bool remove_rtracker = false;
1189 
1190     if (ftracker == nullptr)
1191     {
1192         DCE2_SmbRemoveRequestTracker(ssd, ssd->cur_rtracker);
1193         ssd->cur_rtracker = nullptr;
1194         return;
1195     }
1196 
1197     if ( DetectionEngine::get_current_packet()->is_from_client() )
1198     {
1199         if (nb_len > ssd->cur_rtracker->writeraw_remaining)
1200         {
1201             dce_alert(GID_DCE2, DCE2_SMB_TDCNT_LT_DSIZE, (dce2CommonStats*)&dce2_smb_stats,
1202                 ssd->sd);
1203 
1204             // If this happens, Windows never responds regardless of
1205             // WriteThrough flag, so get rid of request tracker
1206             remove_rtracker = true;
1207         }
1208         else if (!ssd->cur_rtracker->writeraw_writethrough)
1209         {
1210             // If WriteThrough flag was not set on initial request, a
1211             // SMB_COM_WRITE_COMPLETE will not be sent so need to get
1212             // rid of request tracker.
1213             remove_rtracker = true;
1214         }
1215         else
1216         {
1217             ssd->cur_rtracker->writeraw_writethrough = false;
1218             ssd->cur_rtracker->writeraw_remaining = 0;
1219         }
1220     }
1221     else
1222     {
1223         remove_rtracker = true;
1224     }
1225 
1226     // Only one raw read/write allowed
1227     ssd->pdu_state = DCE2_SMB_PDU_STATE__COMMAND;
1228 
1229     if (ftracker->is_ipc)
1230     {
1231         // Maximum possible fragment length is 16 bit
1232         if (nb_len > UINT16_MAX)
1233             nb_len = UINT16_MAX;
1234 
1235         DCE2_CoProcess(&ssd->sd, ftracker->fp_co_tracker, nb_ptr, (uint16_t)nb_len);
1236     }
1237     else
1238     {
1239         bool upload = DetectionEngine::get_current_packet()->is_from_client();
1240         DCE2_SmbProcessFileData(ssd, ftracker, nb_ptr, nb_len, upload);
1241     }
1242 
1243     if (remove_rtracker)
1244     {
1245         DCE2_SmbRemoveRequestTracker(ssd, ssd->cur_rtracker);
1246         ssd->cur_rtracker = nullptr;
1247     }
1248 }
1249 
DCE2_SmbDataFree(DCE2_SmbSsnData * ssd)1250 void DCE2_SmbDataFree(DCE2_SmbSsnData* ssd)
1251 {
1252     if (ssd == nullptr)
1253         return;
1254 
1255     // FIXIT This tries to account for the situation where we never knew the file
1256     // size and the TCP session was shutdown before an SMB_COM_CLOSE on the file.
1257     // Possibly need to add callback to fileAPI since it may have already
1258     // released it's resources.
1259     //DCE2_SmbFinishFileAPI(ssd);
1260 
1261     if (ssd->uids != nullptr)
1262     {
1263         DCE2_ListDestroy(ssd->uids);
1264         ssd->uids = nullptr;
1265     }
1266 
1267     if (ssd->tids != nullptr)
1268     {
1269         DCE2_ListDestroy(ssd->tids);
1270         ssd->tids = nullptr;
1271     }
1272 
1273     DCE2_SmbCleanFileTracker(&ssd->ftracker);
1274     if (ssd->ftrackers != nullptr)
1275     {
1276         DCE2_ListDestroy(ssd->ftrackers);
1277         ssd->ftrackers = nullptr;
1278     }
1279 
1280     DCE2_SmbCleanRequestTracker(&ssd->rtracker);
1281     if (ssd->rtrackers != nullptr)
1282     {
1283         DCE2_QueueDestroy(ssd->rtrackers);
1284         ssd->rtrackers = nullptr;
1285     }
1286 
1287     if (ssd->cli_seg != nullptr)
1288     {
1289         DCE2_BufferDestroy(ssd->cli_seg);
1290         ssd->cli_seg = nullptr;
1291     }
1292 
1293     if (ssd->srv_seg != nullptr)
1294     {
1295         DCE2_BufferDestroy(ssd->srv_seg);
1296         ssd->srv_seg = nullptr;
1297     }
1298 }
1299 
1300 /********************************************************************
1301  * Function: DCE2_NbssHdrChecks()
1302  *
1303  * Purpose:
1304  *  Does validation of the NetBIOS header.  SMB will only run over
1305  *  the Session Message type.  On port 139, there is always an
1306  *  initial Session Request / Session Positive/Negative response
1307  *  followed by the normal SMB conversation, i.e. Negotiate,
1308  *  SessionSetupAndX, etc.
1309  *  Side effects are potential alerts for anomalous behavior.
1310  *
1311  * Arguments:
1312  *  DCE2_SmbSsnData * - the session data structure.
1313  *  const NbssHdr *   - pointer to the NetBIOS Session Service
1314  *                      header structure.  Size is already validated.
1315  *
1316  * Returns:
1317  *  DCE2_Ret  -  DCE2_RET__SUCCESS if all goes well and processing
1318  *               should continue.
1319  *               DCE2_RET__IGNORE if it's not something we need to
1320  *               look at.
1321  *               DCE2_RET__ERROR if an invalid NetBIOS Session
1322  *               Service type is found.
1323  *
1324  ********************************************************************/
DCE2_NbssHdrChecks(DCE2_SmbSsnData * ssd,const NbssHdr * nb_hdr)1325 static DCE2_Ret DCE2_NbssHdrChecks(DCE2_SmbSsnData* ssd, const NbssHdr* nb_hdr)
1326 {
1327     Packet* p = DetectionEngine::get_current_packet();
1328     bool is_seg_buf = DCE2_SmbIsSegBuffer(ssd, (const uint8_t*)nb_hdr);
1329 
1330     switch (NbssType(nb_hdr))
1331     {
1332     case NBSS_SESSION_TYPE__MESSAGE:
1333         /* Only want to look at session messages */
1334         if (!DCE2_SmbIsRawData(ssd))
1335         {
1336             uint32_t nb_len = NbssLen(nb_hdr);
1337 
1338             if (nb_len == 0)
1339                 return DCE2_RET__IGNORE;
1340 
1341             if (nb_len < sizeof(SmbNtHdr))
1342             {
1343                 if (is_seg_buf)
1344                     DCE2_SmbSegAlert(ssd, DCE2_SMB_NB_LT_SMBHDR);
1345                 else
1346                     dce_alert(GID_DCE2, DCE2_SMB_NB_LT_SMBHDR, (dce2CommonStats*)&dce2_smb_stats,
1347                         ssd->sd);
1348 
1349                 return DCE2_RET__IGNORE;
1350             }
1351         }
1352 
1353         return DCE2_RET__SUCCESS;
1354 
1355     case NBSS_SESSION_TYPE__REQUEST:
1356         if ( p->is_from_server() )
1357         {
1358             if (is_seg_buf)
1359                 DCE2_SmbSegAlert(ssd, DCE2_SMB_BAD_NBSS_TYPE);
1360             else
1361                 dce_alert(GID_DCE2, DCE2_SMB_BAD_NBSS_TYPE, (dce2CommonStats*)&dce2_smb_stats,
1362                     ssd->sd);
1363         }
1364 
1365         break;
1366 
1367     case NBSS_SESSION_TYPE__POS_RESPONSE:
1368     case NBSS_SESSION_TYPE__NEG_RESPONSE:
1369     case NBSS_SESSION_TYPE__RETARGET_RESPONSE:
1370         if ( p->is_from_client() )
1371         {
1372             if (is_seg_buf)
1373                 DCE2_SmbSegAlert(ssd, DCE2_SMB_BAD_NBSS_TYPE);
1374             else
1375                 dce_alert(GID_DCE2, DCE2_SMB_BAD_NBSS_TYPE, (dce2CommonStats*)&dce2_smb_stats,
1376                     ssd->sd);
1377         }
1378 
1379         break;
1380 
1381     case NBSS_SESSION_TYPE__KEEP_ALIVE:
1382         break;
1383 
1384     default:
1385         if (is_seg_buf)
1386             DCE2_SmbSegAlert(ssd, DCE2_SMB_BAD_NBSS_TYPE);
1387         else
1388             dce_alert(GID_DCE2, DCE2_SMB_BAD_NBSS_TYPE, (dce2CommonStats*)&dce2_smb_stats,
1389                 ssd->sd);
1390 
1391         return DCE2_RET__ERROR;
1392     }
1393 
1394     return DCE2_RET__IGNORE;
1395 }
1396 
1397 // This is the main entry point for SMB1 processing.
DCE2_Smb1Process(DCE2_SmbSsnData * ssd)1398 void DCE2_Smb1Process(DCE2_SmbSsnData* ssd)
1399 {
1400     dce2_smb_stats.smb_pkts++;
1401 
1402     Packet* p = DetectionEngine::get_current_packet();
1403     const uint8_t* data_ptr = p->data;
1404     uint16_t data_len = p->dsize;
1405     DCE2_Buffer** seg_buf = DCE2_SmbGetSegBuffer(ssd);
1406 
1407     /* Have to account for segmentation.  Even though stream will give
1408      * us larger chunks, we might end up in the middle of something */
1409     while (data_len > 0)
1410     {
1411         // We are ignoring an entire PDU or junk data so state should be NETBIOS_HEADER
1412         // Note that it could be TCP segmented so ignore_bytes could be greater than
1413         // the amount of data we have
1414         uint32_t* ignore_bytes = DCE2_SmbGetIgnorePtr(ssd);
1415         if (*ignore_bytes)
1416         {
1417             if (data_len <= *ignore_bytes)
1418             {
1419                 *ignore_bytes -= data_len;
1420                 return;
1421             }
1422             else
1423             {
1424                 /* ignore bytes is less than UINT16_MAX */
1425                 dce2_move(data_ptr, data_len, (uint16_t)*ignore_bytes);
1426                 *ignore_bytes = 0;
1427             }
1428         }
1429 
1430         DCE2_SmbDataState* data_state = DCE2_SmbGetDataState(ssd);
1431         DCE2_SmbRequestTracker* rtracker = nullptr;
1432         switch (*data_state)
1433         {
1434         // This state is to verify it's a NetBIOS Session Message packet
1435         // and to get the length of the SMB PDU.  Also does the SMB junk
1436         // data check.  If it's not a Session Message the data isn't
1437         // processed since it won't be carrying SMB.
1438         case DCE2_SMB_DATA_STATE__NETBIOS_HEADER:
1439         {
1440             uint32_t data_need = sizeof(NbssHdr);
1441 
1442             // See if there is enough data to process the NetBIOS header
1443             if (data_len < data_need)
1444             {
1445                 if (DCE2_SmbHandleSegmentation(seg_buf, data_ptr,
1446                     data_len, sizeof(NbssHdr)) != DCE2_RET__SUCCESS)
1447                 {
1448                     DCE2_BufferEmpty(*seg_buf);
1449                 }
1450 
1451                 return;
1452             }
1453 
1454             // Set the NetBIOS header structure
1455             const NbssHdr* nb_hdr;
1456             if (DCE2_BufferIsEmpty(*seg_buf))
1457             {
1458                 nb_hdr = (const NbssHdr*)data_ptr;
1459             }
1460             else
1461             {
1462                 // If data already buffered add the remainder for the
1463                 // size of the NetBIOS header
1464                 if (DCE2_SmbHandleSegmentation(seg_buf, data_ptr,
1465                     data_need, sizeof(NbssHdr)) != DCE2_RET__SUCCESS)
1466                 {
1467                     DCE2_BufferEmpty(*seg_buf);
1468                     return;
1469                 }
1470 
1471                 nb_hdr = (const NbssHdr*)DCE2_BufferData(*seg_buf);
1472             }
1473 
1474             uint32_t nb_len = NbssLen(nb_hdr);
1475             DCE2_Ret status = DCE2_NbssHdrChecks(ssd, nb_hdr);
1476             if (status != DCE2_RET__SUCCESS)
1477             {
1478                 if (status == DCE2_RET__IGNORE)
1479                 {
1480                     // Valid NetBIOS header type so ignoring NetBIOS length bytes
1481                     *ignore_bytes = data_need + nb_len;
1482                 }
1483                 else      // nb_ret == DCE2_RET__ERROR, i.e. invalid NetBIOS type
1484                 {
1485                     // Trying to find \\xffSMB to determine how many bytes to ignore
1486                     *ignore_bytes = DCE2_IgnoreJunkData(data_ptr, data_len, data_need + nb_len);
1487                 }
1488 
1489                 DCE2_BufferEmpty(*seg_buf);
1490                 dce2_smb_stats.smb_ignored_bytes += *ignore_bytes;
1491                 continue;
1492             }
1493 
1494             if (!DCE2_BufferIsEmpty(*seg_buf))
1495                 dce2_move(data_ptr, data_len, (uint16_t)data_need);
1496 
1497             switch (ssd->pdu_state)
1498             {
1499             case DCE2_SMB_PDU_STATE__COMMAND:
1500                 *data_state = DCE2_SMB_DATA_STATE__SMB_HEADER;
1501                 break;
1502             case DCE2_SMB_PDU_STATE__RAW_DATA:
1503                 *data_state = DCE2_SMB_DATA_STATE__NETBIOS_PDU;
1504                 // Continue here because of fall through below
1505                 continue;
1506             default:
1507                 return;
1508             }
1509         }
1510 
1511         // Fall through
1512         // This is the normal progression without segmentation.
1513 
1514         // This state is to do validation checks on the SMB header and
1515         // more importantly verify it's data that needs to be inspected.
1516         // If the TID in the SMB header is not referring to the IPC share
1517         // there won't be any DCE/RPC traffic associated with it.
1518         case DCE2_SMB_DATA_STATE__SMB_HEADER:
1519         {
1520             uint32_t data_need = (sizeof(NbssHdr) + sizeof(SmbNtHdr)) - DCE2_BufferLength(
1521                 *seg_buf);
1522 
1523             // See if there is enough data to process the SMB header
1524             if (data_len < data_need)
1525             {
1526                 if (DCE2_SmbHandleSegmentation(seg_buf, data_ptr, data_len,
1527                     sizeof(NbssHdr) + sizeof(SmbNtHdr)) != DCE2_RET__SUCCESS)
1528                 {
1529                     DCE2_BufferEmpty(*seg_buf);
1530                     *data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
1531                 }
1532 
1533                 return;
1534             }
1535 
1536             // Set the SMB header structure
1537             const SmbNtHdr* smb_hdr;
1538             if (DCE2_BufferIsEmpty(*seg_buf))
1539             {
1540                 smb_hdr = (const SmbNtHdr*)(data_ptr + sizeof(NbssHdr));
1541             }
1542             else
1543             {
1544                 if (DCE2_SmbHandleSegmentation(seg_buf, data_ptr, data_need,
1545                     sizeof(NbssHdr) + sizeof(SmbNtHdr)) != DCE2_RET__SUCCESS)
1546                 {
1547                     DCE2_BufferEmpty(*seg_buf);
1548                     *data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
1549                     return;
1550                 }
1551 
1552                 smb_hdr = (const SmbNtHdr*)(DCE2_BufferData(*seg_buf) + sizeof(NbssHdr));
1553             }
1554 
1555             if (SmbId(smb_hdr) == DCE2_SMB2_ID)
1556             {
1557                 if (!DCE2_GcIsLegacyMode((dce2SmbProtoConf*)ssd->sd.config))
1558                 {
1559                     // Upgrade connection to SMBv2
1560 		            SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
1561 		                p, "upgrading to smb2 session\n");
1562                     Dce2SmbFlowData* fd = (Dce2SmbFlowData*)p->flow->get_flow_data(
1563                         Dce2SmbFlowData::inspector_id);
1564                     if (fd)
1565                     {
1566                         Dce2SmbSessionData* dce2_smb2_sess = fd->upgrade(p);
1567                         dce2_smb2_sess->process();
1568                     }
1569                 }
1570                 else
1571                     ssd->sd.flags |= DCE2_SSN_FLAG__SMB2;
1572                 return;
1573             }
1574 
1575             // See if this is something we need to inspect
1576             rtracker = DCE2_SmbInspect(ssd, smb_hdr);
1577             if (rtracker == nullptr)
1578             {
1579 		        SMB_DEBUG(dce_smb_trace, DEFAULT_TRACE_OPTION_ID, TRACE_INFO_LEVEL,
1580 		            p, "Not inspecting SMB packet.\n");
1581 
1582                 if (DCE2_BufferIsEmpty(*seg_buf))
1583                 {
1584                     *ignore_bytes = sizeof(NbssHdr) + NbssLen((const NbssHdr*)data_ptr);
1585                 }
1586                 else
1587                 {
1588                     *ignore_bytes = (NbssLen((NbssHdr*)DCE2_BufferData(*seg_buf))
1589                         - sizeof(SmbNtHdr)) + data_need;
1590                     DCE2_BufferEmpty(*seg_buf);
1591                 }
1592 
1593                 *data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
1594                 dce2_smb_stats.smb_ignored_bytes += *ignore_bytes;
1595                 continue;
1596             }
1597 
1598             // Check the SMB header for anomalies
1599             if (DCE2_SmbHdrChecks(ssd, smb_hdr) != DCE2_RET__SUCCESS)
1600             {
1601                 if (DCE2_BufferIsEmpty(*seg_buf))
1602                 {
1603                     *ignore_bytes = sizeof(NbssHdr) + NbssLen((const NbssHdr*)data_ptr);
1604                 }
1605                 else
1606                 {
1607                     *ignore_bytes = (NbssLen((NbssHdr*)DCE2_BufferData(*seg_buf))
1608                         - sizeof(SmbNtHdr)) + data_need;
1609                     DCE2_BufferEmpty(*seg_buf);
1610                 }
1611 
1612                 *data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
1613 
1614                 dce2_smb_stats.smb_ignored_bytes += *ignore_bytes;
1615                 continue;
1616             }
1617 
1618             if (!DCE2_BufferIsEmpty(*seg_buf))
1619                 dce2_move(data_ptr, data_len, (uint16_t)data_need);
1620 
1621             *data_state = DCE2_SMB_DATA_STATE__NETBIOS_PDU;
1622         }
1623 
1624         // Fall through
1625 
1626         // This state ensures that we have the entire PDU before continuing
1627         // to process.
1628         case DCE2_SMB_DATA_STATE__NETBIOS_PDU:
1629         {
1630             uint32_t nb_len;
1631             uint32_t data_need;
1632 
1633             if (DCE2_BufferIsEmpty(*seg_buf))
1634             {
1635                 nb_len = NbssLen((const NbssHdr*)data_ptr);
1636                 data_need = sizeof(NbssHdr) + nb_len;
1637             }
1638             else
1639             {
1640                 nb_len = NbssLen((NbssHdr*)DCE2_BufferData(*seg_buf));
1641                 data_need = (sizeof(NbssHdr) + nb_len) - DCE2_BufferLength(*seg_buf);
1642             }
1643 
1644             /* It's something we want to inspect so make sure we have the full NBSS packet */
1645             if (data_len < data_need)
1646             {
1647                 if (DCE2_SmbHandleSegmentation(seg_buf, data_ptr, data_len,
1648                     sizeof(NbssHdr) + nb_len) != DCE2_RET__SUCCESS)
1649                 {
1650                     DCE2_BufferEmpty(*seg_buf);
1651                     *data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
1652                 }
1653 
1654                 return;
1655             }
1656 
1657             // data_len >= data_need which means data_need <= UINT16_MAX
1658             // So casts below of data_need to uint16_t are okay.
1659 
1660             *data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
1661 
1662             const uint8_t* nb_ptr;
1663             if (DCE2_BufferIsEmpty(*seg_buf))
1664             {
1665                 nb_ptr = data_ptr;
1666                 nb_len = data_need;
1667                 dce2_move(data_ptr, data_len, (uint16_t)data_need);
1668             }
1669             else
1670             {
1671                 if (DCE2_SmbHandleSegmentation(seg_buf, data_ptr, data_need,
1672                     sizeof(NbssHdr) + nb_len) != DCE2_RET__SUCCESS)
1673                 {
1674                     DCE2_BufferEmpty(*seg_buf);
1675                     dce2_move(data_ptr, data_len, (uint16_t)data_need);
1676                     continue;
1677                 }
1678 
1679                 dce2_move(data_ptr, data_len, (uint16_t)data_need);
1680 
1681                 nb_ptr = DCE2_BufferData(*seg_buf);
1682                 nb_len = DCE2_BufferLength(*seg_buf);
1683 
1684                 // Get reassembled packet
1685                 Packet* rpkt = DCE2_SmbGetRpkt(ssd, &nb_ptr, &nb_len,
1686                     DCE2_RPKT_TYPE__SMB_SEG);
1687                 if (rpkt == nullptr)
1688                 {
1689                     DCE2_BufferEmpty(*seg_buf);
1690                     continue;
1691                 }
1692 
1693                 nb_ptr = DCE2_BufferData(*seg_buf);
1694                 nb_len = DCE2_BufferLength(*seg_buf);
1695 
1696                 if ( p->is_from_client() )
1697                     dce2_smb_stats.smb_cli_seg_reassembled++;
1698                 else
1699                     dce2_smb_stats.smb_srv_seg_reassembled++;
1700             }
1701 
1702             switch (ssd->pdu_state)
1703             {
1704             case DCE2_SMB_PDU_STATE__COMMAND:
1705             {
1706                 const SmbNtHdr* smb_hdr = (const SmbNtHdr*)(nb_ptr + sizeof(NbssHdr));
1707                 dce2_move(nb_ptr, nb_len, (sizeof(NbssHdr) + sizeof(SmbNtHdr)));
1708                 ssd->cur_rtracker = (rtracker != nullptr)
1709                     ? rtracker : DCE2_SmbFindRequestTracker(ssd, smb_hdr);
1710                 if (ssd->cur_rtracker != nullptr)
1711                     DCE2_SmbProcessCommand(ssd, smb_hdr, nb_ptr, nb_len);
1712                 break;
1713             }
1714 
1715             case DCE2_SMB_PDU_STATE__RAW_DATA:
1716                 dce2_move(nb_ptr, nb_len, sizeof(NbssHdr));
1717                 if (ssd->cur_rtracker != nullptr)
1718                     DCE2_SmbProcessRawData(ssd, nb_ptr, nb_len);
1719                 // Only one raw read or write
1720                 ssd->pdu_state = DCE2_SMB_PDU_STATE__COMMAND;
1721                 break;
1722             default:
1723                 return;
1724             }
1725 
1726             if (!DCE2_BufferIsEmpty(*seg_buf))
1727             {
1728                 DCE2_BufferDestroy(*seg_buf);
1729                 *seg_buf = nullptr;
1730             }
1731 
1732             break;
1733         }
1734 
1735         default:
1736             return;
1737         }
1738     }
1739 }
1740 
1741 //-------------------------------------------------------------------------
1742 // public methods
1743 //-------------------------------------------------------------------------
1744 
1745 /********************************************************************
1746  * Function: DCE2_SmbInitGlobals()
1747  *
1748  * Purpose:
1749  *  Initializes global variables for SMB processing.
1750  *  Sets up the functions and valid word and byte counts for SMB
1751  *  commands.
1752  *  Sets up AndX chain mappings and valid command chaining for
1753  *  supported policies.
1754  *
1755  * Arguments: None
1756  *
1757  * Returns: None
1758  *
1759  ********************************************************************/
DCE2_SmbInitGlobals()1760 void DCE2_SmbInitGlobals()
1761 {
1762     memset(&smb_wcts, 0, sizeof(smb_wcts));
1763     memset(&smb_bccs, 0, sizeof(smb_bccs));
1764 
1765     // Sets up the function to call for the command and valid word and byte
1766     // counts for the command.  Ensuring valid word and byte counts is very
1767     // important to processing the command as it will assume the command is
1768     // legitimate and can access data that is actually there.  Note that
1769     // commands with multiple word counts indicate a different command
1770     // structure, however most, if not all just have an extended version
1771     // of the structure for which the extended part isn't used.  If the
1772     // extended part of a command structure needs to be used, be sure to
1773     // check the word count in the command function before accessing data
1774     // in the extended version of the command structure.
1775     for (int com = 0; com < SMB_MAX_NUM_COMS; com++)
1776     {
1777         switch (com)
1778         {
1779         case SMB_COM_OPEN:
1780             smb_com_funcs[com] = DCE2_SmbOpen;
1781 
1782             smb_deprecated_coms[com] = true;
1783             smb_unusual_coms[com] = false;
1784 
1785             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 2);
1786             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 7);
1787 
1788             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 2, UINT16_MAX);
1789             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
1790             break;
1791         case SMB_COM_CREATE:
1792             smb_com_funcs[com] = DCE2_SmbCreate;
1793 
1794             smb_deprecated_coms[com] = true;
1795             smb_unusual_coms[com] = false;
1796 
1797             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 3);
1798             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
1799 
1800             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 2, UINT16_MAX);
1801             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
1802             break;
1803         case SMB_COM_CLOSE:
1804             smb_com_funcs[com] = DCE2_SmbClose;
1805             smb_deprecated_coms[com] = false;
1806             smb_unusual_coms[com] = false;
1807 
1808             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 3);
1809             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 0);
1810 
1811             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
1812             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
1813             break;
1814         case SMB_COM_RENAME:
1815             smb_com_funcs[com] = DCE2_SmbRename;
1816             smb_deprecated_coms[com] = false;
1817             smb_unusual_coms[com] = false;
1818 
1819             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 1);
1820             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 0);
1821 
1822             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 4, UINT16_MAX);
1823             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
1824             break;
1825         case SMB_COM_READ:
1826             smb_com_funcs[com] = DCE2_SmbRead;
1827             smb_deprecated_coms[com] = true;
1828             smb_unusual_coms[com] = false;
1829 
1830             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 5);
1831             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 5);
1832 
1833             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
1834             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 3, UINT16_MAX);
1835             break;
1836         case SMB_COM_WRITE:
1837             smb_com_funcs[com] = DCE2_SmbWrite;
1838             smb_deprecated_coms[com] = true;
1839             smb_unusual_coms[com] = false;
1840 
1841             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 5);
1842             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
1843 
1844             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 3, UINT16_MAX);
1845             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
1846             break;
1847         case SMB_COM_CREATE_NEW:
1848             smb_com_funcs[com] = DCE2_SmbCreateNew;
1849             smb_deprecated_coms[com] = true;
1850             smb_unusual_coms[com] = false;
1851 
1852             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 3);
1853             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
1854 
1855             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 2, UINT16_MAX);
1856             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
1857             break;
1858         case SMB_COM_LOCK_AND_READ:
1859             smb_com_funcs[com] = DCE2_SmbLockAndRead;
1860             smb_deprecated_coms[com] = true;
1861             smb_unusual_coms[com] = false;
1862 
1863             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 5);
1864             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 5);
1865 
1866             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
1867             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 3, UINT16_MAX);
1868             break;
1869         case SMB_COM_WRITE_AND_UNLOCK:
1870             smb_com_funcs[com] = DCE2_SmbWriteAndUnlock;
1871             smb_deprecated_coms[com] = true;
1872             smb_unusual_coms[com] = false;
1873 
1874             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 5);
1875             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
1876 
1877             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 3, UINT16_MAX);
1878             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
1879             break;
1880         case SMB_COM_READ_RAW:
1881             smb_com_funcs[com] = DCE2_SmbReadRaw;
1882             smb_deprecated_coms[com] = true;
1883             smb_unusual_coms[com] = false;
1884 
1885             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 8);
1886             // With optional OffsetHigh
1887             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 10);
1888 
1889             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
1890             // Response is raw data, i.e. without SMB
1891             break;
1892         case SMB_COM_WRITE_RAW:
1893             smb_com_funcs[com] = DCE2_SmbWriteRaw;
1894             smb_deprecated_coms[com] = true;
1895             smb_unusual_coms[com] = false;
1896 
1897             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 12);
1898             // With optional OffsetHigh
1899             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 14);
1900             // Interim server response
1901             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
1902 
1903             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
1904             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
1905             break;
1906         case SMB_COM_WRITE_COMPLETE:
1907             // Final server response to SMB_COM_WRITE_RAW
1908             smb_com_funcs[com] = DCE2_SmbWriteComplete;
1909             smb_deprecated_coms[com] = true;
1910             smb_unusual_coms[com] = false;
1911 
1912             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
1913 
1914             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
1915             break;
1916         case SMB_COM_TRANSACTION:
1917             smb_com_funcs[com] = DCE2_SmbTransaction;
1918             smb_deprecated_coms[com] = false;
1919             smb_unusual_coms[com] = false;
1920 
1921             // Word count depends on setup count
1922             //for (i = 14; i < 256; i++)
1923             //    DCE2_SmbSetValidWordCount(com, SMB_TYPE__REQUEST, i);
1924             // In reality, all subcommands of SMB_COM_TRANSACTION requests
1925             // have a setup count of 2 words.
1926             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 16);
1927 
1928             // \PIPE\LANMAN
1929             // Not something the inspector is looking at as it
1930             // doesn't carry DCE/RPC but don't want to false positive
1931             // on the inspector event.
1932             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 14);
1933 
1934             // Word count depends on setup count
1935             //for (i = 10; i < 256; i++)
1936             //    DCE2_SmbSetValidWordCount(com, SMB_TYPE__RESPONSE, i);
1937             // In reality, all subcommands of SMB_COM_TRANSACTION responses
1938             // have a setup count of 0 words.
1939             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 10);
1940 
1941             // Interim server response
1942             // When client sends an incomplete transaction and needs to
1943             // send TransactionSecondary requests to complete request.
1944             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 0);
1945 
1946             // Exception will be made for Interim responses when
1947             // byte count is checked.
1948             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
1949             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
1950             break;
1951         case SMB_COM_TRANSACTION_SECONDARY:
1952             smb_com_funcs[com] = DCE2_SmbTransactionSecondary;
1953             smb_deprecated_coms[com] = false;
1954             smb_unusual_coms[com] = false;
1955 
1956             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 8);
1957             // Response is an SMB_COM_TRANSACTION
1958 
1959             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
1960             break;
1961         case SMB_COM_WRITE_AND_CLOSE:
1962             smb_com_funcs[com] = DCE2_SmbWriteAndClose;
1963             smb_deprecated_coms[com] = true;
1964             smb_unusual_coms[com] = false;
1965 
1966             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 6);
1967             // For some reason MS-CIFS specifies a version of this command
1968             // with 6 extra words (12 bytes) of reserved, i.e. useless data.
1969             // Maybe had intentions of extending and defining the data at
1970             // some point, but there is no documentation that I could find
1971             // that does.
1972             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 12);
1973             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
1974 
1975             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 1, UINT16_MAX);
1976             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
1977             break;
1978         case SMB_COM_OPEN_ANDX:
1979             smb_com_funcs[com] = DCE2_SmbOpenAndX;
1980             smb_deprecated_coms[com] = true;
1981             smb_unusual_coms[com] = false;
1982 
1983             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 15);
1984             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 15);
1985             // Extended response
1986             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 19);
1987 
1988             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 2, UINT16_MAX);
1989             // MS-SMB says that Windows 2000, XP and Vista set this to
1990             // some arbitrary value that is ignored on receipt.
1991             //DCE2_SmbSetValidByteCount(com, SMB_TYPE__RESPONSE, 0, 0);
1992             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
1993             break;
1994         case SMB_COM_READ_ANDX:
1995             smb_com_funcs[com] = DCE2_SmbReadAndX;
1996             smb_deprecated_coms[com] = false;
1997             smb_unusual_coms[com] = false;
1998 
1999             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 10);
2000             // With optional OffsetHigh
2001             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 12);
2002             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 12);
2003 
2004             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
2005             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
2006             break;
2007         case SMB_COM_WRITE_ANDX:
2008             smb_com_funcs[com] = DCE2_SmbWriteAndX;
2009             smb_deprecated_coms[com] = false;
2010             smb_unusual_coms[com] = false;
2011 
2012             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 12);
2013             // With optional OffsetHigh
2014             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 14);
2015             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 6);
2016 
2017             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 1, UINT16_MAX);
2018             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
2019             break;
2020         case SMB_COM_TRANSACTION2:
2021             smb_com_funcs[com] = DCE2_SmbTransaction2;
2022             smb_deprecated_coms[com] = false;
2023             smb_unusual_coms[com] = false;
2024 
2025             // Word count depends on setup count
2026             //for (i = 14; i < 256; i++)
2027             //    DCE2_SmbSetValidWordCount(com, SMB_TYPE__REQUEST, i);
2028             // In reality, all subcommands of SMB_COM_TRANSACTION2
2029             // requests have a setup count of 1 word.
2030             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 15);
2031 
2032             // Word count depends on setup count
2033             //for (i = 10; i < 256; i++)
2034             //    DCE2_SmbSetValidWordCount(com, SMB_TYPE__RESPONSE, i);
2035             // In reality, all subcommands of SMB_COM_TRANSACTION2
2036             // responses have a setup count of 0 or 1 word.
2037             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 10);
2038             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 11);
2039 
2040             // Interim server response
2041             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 0);
2042 
2043             // Exception will be made for Interim responses when
2044             // byte count is checked.
2045             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
2046             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
2047             break;
2048         case SMB_COM_TRANSACTION2_SECONDARY:
2049             smb_com_funcs[com] = DCE2_SmbTransaction2Secondary;
2050             smb_deprecated_coms[com] = false;
2051             smb_unusual_coms[com] = false;
2052 
2053             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 9);
2054             // Response is an SMB_COM_TRANSACTION2
2055 
2056             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
2057             break;
2058         case SMB_COM_TREE_CONNECT:
2059             smb_com_funcs[com] = DCE2_SmbTreeConnect;
2060             smb_deprecated_coms[com] = true;
2061             smb_unusual_coms[com] = false;
2062 
2063             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 0);
2064             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 2);
2065 
2066             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 6, UINT16_MAX);
2067             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
2068             break;
2069         case SMB_COM_TREE_DISCONNECT:
2070             smb_com_funcs[com] = DCE2_SmbTreeDisconnect;
2071             smb_deprecated_coms[com] = false;
2072             smb_unusual_coms[com] = false;
2073 
2074             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 0);
2075             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 0);
2076 
2077             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
2078             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
2079             break;
2080         case SMB_COM_NEGOTIATE:
2081             smb_com_funcs[com] = DCE2_SmbNegotiate;
2082             smb_deprecated_coms[com] = false;
2083             smb_unusual_coms[com] = false;
2084 
2085             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 0);
2086             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
2087             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 13);
2088             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 17);
2089 
2090             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 2, UINT16_MAX);
2091             // This can vary depending on dialect so just set wide.
2092             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
2093             break;
2094         case SMB_COM_SESSION_SETUP_ANDX:
2095             smb_com_funcs[com] = DCE2_SmbSessionSetupAndX;
2096             smb_deprecated_coms[com] = false;
2097             smb_unusual_coms[com] = false;
2098 
2099             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 10);
2100             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 12);
2101             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 13);
2102             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 3);
2103             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 4);
2104 
2105             // These can vary so just set wide.
2106             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
2107             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
2108             break;
2109         case SMB_COM_LOGOFF_ANDX:
2110             smb_com_funcs[com] = DCE2_SmbLogoffAndX;
2111             smb_deprecated_coms[com] = false;
2112             smb_unusual_coms[com] = false;
2113 
2114             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 2);
2115             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 2);
2116             // Windows responds to a LogoffAndX => SessionSetupAndX with just a
2117             // LogoffAndX and with the word count field containing 3, but only
2118             // has 2 words
2119             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 3);
2120 
2121             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
2122             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
2123             break;
2124         case SMB_COM_TREE_CONNECT_ANDX:
2125             smb_com_funcs[com] = DCE2_SmbTreeConnectAndX;
2126             smb_deprecated_coms[com] = false;
2127             smb_unusual_coms[com] = false;
2128 
2129             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 4);
2130             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 2);
2131             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 3);
2132             // Extended response
2133             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 7);
2134 
2135             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 3, UINT16_MAX);
2136             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 2, UINT16_MAX);
2137             break;
2138         case SMB_COM_NT_TRANSACT:
2139             smb_com_funcs[com] = DCE2_SmbNtTransact;
2140             smb_deprecated_coms[com] = false;
2141             smb_unusual_coms[com] = false;
2142 
2143             // Word count depends on setup count
2144             // In reality, all subcommands of SMB_COM_NT_TRANSACT
2145             // requests have a setup count of 0 or 4 words.
2146             //for (i = 19; i < 256; i++)
2147             //    DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, i);
2148             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 19);
2149             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 23);
2150 
2151             // Word count depends on setup count
2152             // In reality, all subcommands of SMB_COM_NT_TRANSACT
2153             // responses have a setup count of 0 or 1 word.
2154             //for (i = 18; i < 256; i++)
2155             //    DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, i);
2156             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 18);
2157             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 19);
2158 
2159             // Interim server response
2160             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 0);
2161 
2162             // Exception will be made for Interim responses when
2163             // byte count is checked.
2164             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
2165             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
2166             break;
2167         case SMB_COM_NT_TRANSACT_SECONDARY:
2168             smb_com_funcs[com] = DCE2_SmbNtTransactSecondary;
2169             smb_deprecated_coms[com] = false;
2170             smb_unusual_coms[com] = false;
2171 
2172             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 18);
2173             // Response is an SMB_COM_NT_TRANSACT
2174 
2175             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
2176             break;
2177         case SMB_COM_NT_CREATE_ANDX:
2178             smb_com_funcs[com] = DCE2_SmbNtCreateAndX;
2179             smb_deprecated_coms[com] = false;
2180             smb_unusual_coms[com] = false;
2181 
2182             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 24);
2183             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 34);
2184             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 26);
2185             // Extended response - though there are actually 50 words
2186             DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 42);
2187 
2188             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 2, UINT16_MAX);
2189             // MS-SMB indicates that this field should be 0 but may be
2190             // sent uninitialized so basically ignore it.
2191             //DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
2192             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
2193             break;
2194         default:
2195             smb_com_funcs[com] = nullptr;
2196             smb_deprecated_coms[com] = false;
2197             smb_unusual_coms[com] = false;
2198             // Just set to all valid since the specific command won't
2199             // be processed.  Don't want to false positive on these.
2200             for (int i = 0; i < 256; i++)
2201             {
2202                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, (uint8_t)i);
2203                 DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, (uint8_t)i);
2204             }
2205             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
2206             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
2207             break;
2208         }
2209     }
2210 
2211     // Maps commands for use in quickly determining if a command
2212     // is chainable and what command it is.
2213     for (int com = 0; com < SMB_MAX_NUM_COMS; com++)
2214     {
2215         switch (com)
2216         {
2217         case SMB_COM_SESSION_SETUP_ANDX:
2218             smb_chain_map[com] = SMB_ANDX_COM__SESSION_SETUP_ANDX;
2219             break;
2220         case SMB_COM_LOGOFF_ANDX:
2221             smb_chain_map[com] = SMB_ANDX_COM__LOGOFF_ANDX;
2222             break;
2223         case SMB_COM_TREE_CONNECT_ANDX:
2224             smb_chain_map[com] = SMB_ANDX_COM__TREE_CONNECT_ANDX;
2225             break;
2226         case SMB_COM_OPEN_ANDX:
2227             smb_chain_map[com] = SMB_ANDX_COM__OPEN_ANDX;
2228             break;
2229         case SMB_COM_NT_CREATE_ANDX:
2230             smb_chain_map[com] = SMB_ANDX_COM__NT_CREATE_ANDX;
2231             break;
2232         case SMB_COM_WRITE_ANDX:
2233             smb_chain_map[com] = SMB_ANDX_COM__WRITE_ANDX;
2234             break;
2235         case SMB_COM_READ_ANDX:
2236             smb_chain_map[com] = SMB_ANDX_COM__READ_ANDX;
2237             break;
2238         default:
2239             smb_chain_map[com] = SMB_ANDX_COM__NONE;
2240             break;
2241         }
2242     }
2243 
2244     // Sets up the valid command chaining combinations per policy
2245     for (int policy = 0; policy < DCE2_POLICY__MAX; policy++)
2246     {
2247         for (int andx = SMB_ANDX_COM__NONE; andx < SMB_ANDX_COM__MAX; andx++)
2248         {
2249             /* com is the chained command or com2 */
2250             for (int com = 0; com < SMB_MAX_NUM_COMS; com++)
2251             {
2252                 DCE2_SmbComFunc com_func = nullptr;
2253 
2254                 switch (policy)
2255                 {
2256                 case DCE2_POLICY__WIN2000:
2257                 case DCE2_POLICY__WINXP:
2258                 case DCE2_POLICY__WINVISTA:
2259                 case DCE2_POLICY__WIN2003:
2260                 case DCE2_POLICY__WIN2008:
2261                 case DCE2_POLICY__WIN7:
2262                     switch (andx)
2263                     {
2264                     case SMB_ANDX_COM__SESSION_SETUP_ANDX:
2265                         switch (com)
2266                         {
2267                         case SMB_COM_TREE_CONNECT_ANDX:
2268                         case SMB_COM_OPEN:
2269                         case SMB_COM_OPEN_ANDX:
2270                         case SMB_COM_CREATE:
2271                         case SMB_COM_CREATE_NEW:
2272                             com_func = smb_com_funcs[com];
2273                             break;
2274                         case SMB_COM_TRANSACTION:
2275                             if (policy == DCE2_POLICY__WIN2000)
2276                                 com_func = smb_com_funcs[com];
2277                             break;
2278                         default:
2279                             break;
2280                         }
2281                         break;
2282                     case SMB_ANDX_COM__LOGOFF_ANDX:
2283                         switch (com)
2284                         {
2285                         case SMB_COM_SESSION_SETUP_ANDX:
2286                         case SMB_COM_TREE_CONNECT_ANDX:               // Only for responses
2287                             com_func = smb_com_funcs[com];
2288                             break;
2289                         default:
2290                             break;
2291                         }
2292                         break;
2293                     case SMB_ANDX_COM__TREE_CONNECT_ANDX:
2294                         switch (com)
2295                         {
2296                         case SMB_COM_OPEN:
2297                         case SMB_COM_CREATE:
2298                         case SMB_COM_CREATE_NEW:
2299                             com_func = smb_com_funcs[com];
2300                             break;
2301                         case SMB_COM_TRANSACTION:
2302                             if (policy == DCE2_POLICY__WIN2000)
2303                                 com_func = smb_com_funcs[com];
2304                             break;
2305                         default:
2306                             break;
2307                         }
2308                         break;
2309                     case SMB_ANDX_COM__OPEN_ANDX:
2310                         break;
2311                     case SMB_ANDX_COM__NT_CREATE_ANDX:
2312                         switch (com)
2313                         {
2314                         case SMB_COM_READ_ANDX:              // Only for normal files
2315                             com_func = smb_com_funcs[com];
2316                             break;
2317                         default:
2318                             break;
2319                         }
2320                         break;
2321                     case SMB_ANDX_COM__WRITE_ANDX:
2322                         switch (com)
2323                         {
2324                         case SMB_COM_CLOSE:
2325                         case SMB_COM_WRITE_ANDX:
2326                         case SMB_COM_READ:
2327                         case SMB_COM_READ_ANDX:
2328                             com_func = smb_com_funcs[com];
2329                             break;
2330                         default:
2331                             break;
2332                         }
2333                         break;
2334                     case SMB_ANDX_COM__READ_ANDX:
2335                         break;
2336                     default:
2337                         break;
2338                     }
2339                     break;
2340                 case DCE2_POLICY__SAMBA:
2341                 case DCE2_POLICY__SAMBA_3_0_37:
2342                 case DCE2_POLICY__SAMBA_3_0_22:
2343                 case DCE2_POLICY__SAMBA_3_0_20:
2344                     switch (andx)
2345                     {
2346                     case SMB_ANDX_COM__SESSION_SETUP_ANDX:
2347                         switch (com)
2348                         {
2349                         case SMB_COM_LOGOFF_ANDX:
2350                         case SMB_COM_TREE_CONNECT:
2351                         case SMB_COM_TREE_CONNECT_ANDX:
2352                         case SMB_COM_TREE_DISCONNECT:
2353                         case SMB_COM_OPEN_ANDX:
2354                         case SMB_COM_NT_CREATE_ANDX:
2355                         case SMB_COM_CLOSE:
2356                         case SMB_COM_READ_ANDX:
2357                             com_func = smb_com_funcs[com];
2358                             break;
2359                         case SMB_COM_WRITE:
2360                             if ((policy == DCE2_POLICY__SAMBA_3_0_22)
2361                                 || (policy == DCE2_POLICY__SAMBA_3_0_20))
2362                                 com_func = smb_com_funcs[com];
2363                             break;
2364                         default:
2365                             break;
2366                         }
2367                         break;
2368                     case SMB_ANDX_COM__LOGOFF_ANDX:
2369                         switch (com)
2370                         {
2371                         case SMB_COM_SESSION_SETUP_ANDX:
2372                         case SMB_COM_TREE_DISCONNECT:
2373                             com_func = smb_com_funcs[com];
2374                             break;
2375                         default:
2376                             break;
2377                         }
2378                         break;
2379                     case SMB_ANDX_COM__TREE_CONNECT_ANDX:
2380                         switch (com)
2381                         {
2382                         case SMB_COM_SESSION_SETUP_ANDX:
2383                         case SMB_COM_LOGOFF_ANDX:
2384                         case SMB_COM_TREE_DISCONNECT:
2385                         case SMB_COM_OPEN_ANDX:
2386                         case SMB_COM_NT_CREATE_ANDX:
2387                         case SMB_COM_CLOSE:
2388                         case SMB_COM_WRITE:
2389                         case SMB_COM_READ_ANDX:
2390                             com_func = smb_com_funcs[com];
2391                             break;
2392                         default:
2393                             break;
2394                         }
2395                         break;
2396                     case SMB_ANDX_COM__OPEN_ANDX:
2397                         switch (com)
2398                         {
2399                         case SMB_COM_SESSION_SETUP_ANDX:
2400                         case SMB_COM_LOGOFF_ANDX:
2401                         case SMB_COM_TREE_CONNECT:
2402                         case SMB_COM_TREE_CONNECT_ANDX:
2403                         case SMB_COM_TREE_DISCONNECT:
2404                         case SMB_COM_OPEN_ANDX:
2405                         case SMB_COM_NT_CREATE_ANDX:
2406                         case SMB_COM_CLOSE:
2407                         case SMB_COM_WRITE:
2408                         case SMB_COM_READ_ANDX:
2409                             com_func = smb_com_funcs[com];
2410                             break;
2411                         default:
2412                             break;
2413                         }
2414                         break;
2415                     case SMB_ANDX_COM__NT_CREATE_ANDX:
2416                         switch (com)
2417                         {
2418                         case SMB_COM_SESSION_SETUP_ANDX:
2419                         case SMB_COM_TREE_CONNECT:
2420                         case SMB_COM_TREE_CONNECT_ANDX:
2421                         case SMB_COM_OPEN_ANDX:
2422                         case SMB_COM_NT_CREATE_ANDX:
2423                         case SMB_COM_WRITE:
2424                         case SMB_COM_READ_ANDX:
2425                             com_func = smb_com_funcs[com];
2426                             break;
2427                         case SMB_COM_LOGOFF_ANDX:
2428                         case SMB_COM_TREE_DISCONNECT:
2429                         case SMB_COM_CLOSE:
2430                             if ((policy == DCE2_POLICY__SAMBA)
2431                                 || (policy == DCE2_POLICY__SAMBA_3_0_37))
2432                                 com_func = smb_com_funcs[com];
2433                             break;
2434                         default:
2435                             break;
2436                         }
2437                         break;
2438                     case SMB_ANDX_COM__WRITE_ANDX:
2439                         switch (com)
2440                         {
2441                         case SMB_COM_SESSION_SETUP_ANDX:
2442                         case SMB_COM_LOGOFF_ANDX:
2443                         case SMB_COM_TREE_CONNECT:
2444                         case SMB_COM_TREE_CONNECT_ANDX:
2445                         case SMB_COM_OPEN_ANDX:
2446                         case SMB_COM_NT_CREATE_ANDX:
2447                         case SMB_COM_CLOSE:
2448                         case SMB_COM_WRITE:
2449                         case SMB_COM_READ_ANDX:
2450                         case SMB_COM_WRITE_ANDX:
2451                             com_func = smb_com_funcs[com];
2452                             break;
2453                         default:
2454                             break;
2455                         }
2456                         break;
2457                     case SMB_ANDX_COM__READ_ANDX:
2458                         switch (com)
2459                         {
2460                         case SMB_COM_SESSION_SETUP_ANDX:
2461                         case SMB_COM_WRITE:
2462                             com_func = smb_com_funcs[com];
2463                             break;
2464                         case SMB_COM_LOGOFF_ANDX:
2465                         case SMB_COM_TREE_CONNECT:
2466                         case SMB_COM_TREE_CONNECT_ANDX:
2467                         case SMB_COM_TREE_DISCONNECT:
2468                         case SMB_COM_OPEN_ANDX:
2469                         case SMB_COM_NT_CREATE_ANDX:
2470                         case SMB_COM_CLOSE:
2471                         case SMB_COM_READ_ANDX:
2472                             if ((policy == DCE2_POLICY__SAMBA)
2473                                 || (policy == DCE2_POLICY__SAMBA_3_0_37))
2474                                 com_func = smb_com_funcs[com];
2475                             break;
2476                         default:
2477                             break;
2478                         }
2479                         break;
2480                     default:
2481                         break;
2482                     }
2483                     break;
2484                 default:
2485                     break;
2486                 }
2487 
2488                 smb_chain_funcs[policy][andx][com] = com_func;
2489             }
2490         }
2491     }
2492 }
2493 
2494