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