suricata
app-layer-smb.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2010 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Kirby Kuehl <kkuehl@gmail.com>
22  *
23  * \brief SMBv1 parser/decoder
24  */
25 
26 #include "suricata-common.h"
27 
28 #include "debug.h"
29 #include "decode.h"
30 #include "threads.h"
31 
32 #include "util-print.h"
33 #include "util-pool.h"
34 #include "util-debug.h"
35 
36 #include "stream-tcp-private.h"
37 #include "stream-tcp-reassemble.h"
38 #include "stream-tcp.h"
39 #include "stream.h"
40 
41 #include "app-layer.h"
42 #include "app-layer-detect-proto.h"
43 #include "app-layer-protos.h"
44 #include "app-layer-parser.h"
45 #include "app-layer-dcerpc.h"
46 
47 #include "util-spm.h"
48 #include "util-unittest.h"
49 #include "util-memcmp.h"
50 
51 #ifdef HAVE_RUST
52 #include "rust.h"
53 #include "app-layer-smb-tcp-rust.h"
54 void RegisterSMBParsers(void)
55 {
57 }
58 
59 #else // no RUST
60 
61 #include "app-layer-smb.h"
62 
63 enum {
71  /* must be last */
73 };
74 
75 /**
76  * \brief SMB Write AndX Request Parsing
77  */
78 /* For WriteAndX we need to get writeandxdataoffset */
79 static uint32_t SMBParseWriteAndX(Flow *f, void *smb_state,
80  AppLayerParserState *pstate, uint8_t *input, uint32_t input_len)
81 {
82  SCEnter();
83 
84  SMBState *sstate = (SMBState *) smb_state;
85  uint8_t *p = input;
86 
87  switch (sstate->andx.andxbytesprocessed) {
88  case 0:
89  sstate->andx.paddingparsed = 0;
90  if (input_len >= 28) {
91  sstate->andx.andxcommand = *p;
92  sstate->andx.andxoffset = *(p + 2);
93  sstate->andx.andxoffset |= *(p + 3) << 8;
94  sstate->andx.datalengthhigh = *(p + 18);
95  sstate->andx.datalengthhigh |= *(p + 19) << 8;
96  sstate->andx.datalength = *(p + 20);
97  sstate->andx.datalength |= *(p + 21) << 8;
98  sstate->andx.dataoffset = *(p + 22);
99  sstate->andx.dataoffset |= *(p + 23) << 8;
100  sstate->andx.dataoffset |= (uint64_t) *(p + 24) << 56;
101  sstate->andx.dataoffset |= (uint64_t) *(p + 25) << 48;
102  sstate->andx.dataoffset |= (uint64_t) *(p + 26) << 40;
103  sstate->andx.dataoffset |= (uint64_t) *(p + 27) << 32;
104  sstate->bytesprocessed += 28;
105  SCReturnUInt(28U);
106  } else {
107  sstate->andx.andxcommand = *(p++);
108  if (!(--input_len))
109  break;
110  }
111  /* fall through */
112  case 1:
113  p++; // Reserved
114  if (!(--input_len))
115  break;
116  /* fall through */
117  case 2:
118  sstate->andx.andxoffset = *(p++) << 8;
119  if (!(--input_len))
120  break;
121  /* fall through */
122  case 3:
123  sstate->andx.andxoffset |= *(p++);
124  if (!(--input_len))
125  break;
126  /* fall through */
127  case 4:
128  // SMB_COM_WRITE_ANDX Fid 1
129  p++;
130  if (!(--input_len))
131  break;
132  /* fall through */
133  case 5:
134  // SMB_COM_WRITE_ANDX Fid 2
135  p++;
136  if (!(--input_len))
137  break;
138  /* fall through */
139  case 6:
140  // SMB_COM_WRITE_ANDX Offset 1
141  p++;
142  if (!(--input_len))
143  break;
144  /* fall through */
145  case 7:
146  // SMB_COM_WRITE_ANDX Offset 2
147  p++;
148  if (!(--input_len))
149  break;
150  /* fall through */
151  case 8:
152  // SMB_COM_WRITE_ANDX Offset 3
153  p++;
154  if (!(--input_len))
155  break;
156  /* fall through */
157  case 9:
158  // SMB_COM_WRITE_ANDX Offset 4
159  p++;
160  if (!(--input_len))
161  break;
162  /* fall through */
163  case 10:
164  // SMB_COM_WRITE_ANDX Reserved 1
165  p++;
166  if (!(--input_len))
167  break;
168  /* fall through */
169  case 11:
170  // SMB_COM_WRITE_ANDX Reserved 2
171  p++;
172  if (!(--input_len))
173  break;
174  /* fall through */
175  case 12:
176  // SMB_COM_WRITE_ANDX Reserved 3
177  p++;
178  if (!(--input_len))
179  break;
180  /* fall through */
181  case 13:
182  // SMB_COM_WRITE_ANDX Reserved 4
183  p++;
184  if (!(--input_len))
185  break;
186  /* fall through */
187  case 14:
188  // SMB_COM_WRITE_ANDX WriteMode 1
189  p++;
190  if (!(--input_len))
191  break;
192  /* fall through */
193  case 15:
194  // SMB_COM_WRITE_ANDX WriteMode 2
195  p++;
196  if (!(--input_len))
197  break;
198  /* fall through */
199  case 16:
200  // SMB_COM_WRITE_ANDX BytesRemaining 1
201  p++;
202  if (!(--input_len))
203  break;
204  /* fall through */
205  case 17:
206  // SMB_COM_WRITE_ANDX BytesRemaining 2
207  p++;
208  if (!(--input_len))
209  break;
210  /* fall through */
211  case 18:
212  // DataLengthHigh 1
213  sstate->andx.datalengthhigh = *(p++);
214  if (!(--input_len))
215  break;
216  /* fall through */
217  case 19:
218  // DataLengthHigh 2
219  sstate->andx.datalengthhigh |= *(p++) << 8;
220  if (!(--input_len))
221  break;
222  /* fall through */
223  case 20:
224  // DataLength 1
225  sstate->andx.datalength = *(p++);
226  if (!(--input_len))
227  break;
228  /* fall through */
229  case 21:
230  // DataLength 2
231  sstate->andx.datalength |= *(p++) << 8;
232  if (!(--input_len))
233  break;
234  /* fall through */
235  case 22:
236  sstate->andx.dataoffset = *(p++) << 8;
237  if (!(--input_len))
238  break;
239  /* fall through */
240  case 23:
241  sstate->andx.dataoffset |= *(p++);
242  if (!(--input_len))
243  break;
244  /* fall through */
245  case 24:
246  sstate->andx.dataoffset |= (uint64_t) *(p++) << 56;
247  if (!(--input_len))
248  break;
249  /* fall through */
250  case 25:
251  sstate->andx.dataoffset |= (uint64_t) *(p++) << 48;
252  if (!(--input_len))
253  break;
254  /* fall through */
255  case 26:
256  sstate->andx.dataoffset |= (uint64_t) *(p++) << 40;
257  if (!(--input_len))
258  break;
259  /* fall through */
260  case 27:
261  sstate->andx.dataoffset |= (uint64_t) *(p++) << 32;
262  --input_len;
263  break;
264  /* fall through */
265  default:
266  sstate->bytesprocessed++;
267  SCReturnUInt(1);
268  break;
269  }
270  sstate->bytesprocessed += (p - input);
271  SCReturnUInt((uint32_t)(p - input));
272 }
273 
274 /**
275  * \brief SMB Read AndX Response Parsing
276  */
277 static uint32_t SMBParseReadAndX(Flow *f, void *smb_state,
278  AppLayerParserState *pstate, uint8_t *input, uint32_t input_len)
279 {
280  SCEnter();
281 
282  SMBState *sstate = (SMBState *) smb_state;
283  uint8_t *p = input;
284 
285  switch (sstate->andx.andxbytesprocessed) {
286  case 0:
287  sstate->andx.paddingparsed = 0;
288  if (input_len >= 24) {
289  sstate->andx.andxcommand = *p;
290  sstate->andx.andxoffset = *(p + 2);
291  sstate->andx.andxoffset |= *(p + 3) << 8;
292  sstate->andx.datalength = *(p + 10);
293  sstate->andx.datalength |= *(p + 11) << 8;
294  sstate->andx.dataoffset = *(p + 12);
295  sstate->andx.dataoffset |= *(p + 13) << 8;
296  sstate->andx.datalength |= (uint64_t) *(p + 14) << 32;
297  sstate->andx.datalength |= (uint64_t) *(p + 15) << 40;
298  sstate->andx.datalength |= (uint64_t) *(p + 16) << 48;
299  sstate->andx.datalength |= (uint64_t) *(p + 17) << 56;
300  sstate->bytesprocessed += 24;
301  SCReturnUInt(24U);
302  } else {
303  sstate->andx.andxcommand = *(p++);
304  if (!(--input_len))
305  break;
306  }
307  /* fall through */
308  case 1:
309  p++; // Reserved
310  if (!(--input_len))
311  break;
312  /* fall through */
313  case 2:
314  sstate->andx.andxoffset |= *(p++);
315  if (!(--input_len))
316  break;
317  /* fall through */
318  case 3:
319  sstate->andx.andxoffset |= *(p++) << 8;
320  if (!(--input_len))
321  break;
322  /* fall through */
323  case 4:
324  // SMB_COM_READ_ANDX Remaining Reserved must be 0xff
325  p++;
326  if (!(--input_len))
327  break;
328  /* fall through */
329  case 5:
330  // SMB_COM_READ_ANDX Remaining Reserved must be 0xff
331  p++;
332  if (!(--input_len))
333  break;
334  /* fall through */
335  case 6:
336  // SMB_COM_READ_ANDX DataCompactionMode 1
337  p++;
338  if (!(--input_len))
339  break;
340  /* fall through */
341  case 7:
342  // SMB_COM_READ_ANDX DataCompactionMode 1
343  p++;
344  if (!(--input_len))
345  break;
346  /* fall through */
347  case 8:
348  // SMB_COM_READ_ANDX Reserved
349  p++;
350  if (!(--input_len))
351  break;
352  /* fall through */
353  case 9:
354  // SMB_COM_READ_ANDX Reserved
355  p++;
356  if (!(--input_len))
357  break;
358  /* fall through */
359  case 10:
360  sstate->andx.datalength = *(p++);
361  if (!(--input_len))
362  break;
363  /* fall through */
364  case 11:
365  sstate->andx.datalength |= *(p++) << 8;
366  if (!(--input_len))
367  break;
368  /* fall through */
369  case 12:
370  sstate->andx.dataoffset = *(p++);
371  if (!(--input_len))
372  break;
373  /* fall through */
374  case 13:
375  sstate->andx.dataoffset |= *(p++) << 8;
376  if (!(--input_len))
377  break;
378  /* fall through */
379  case 14:
380  sstate->andx.datalength |= *(p++) << 16;
381  if (!(--input_len))
382  break;
383  /* fall through */
384  case 15:
385  sstate->andx.datalength |= *(p++) << 24;
386  if (!(--input_len))
387  break;
388  /* fall through */
389  case 16:
390  // SMB_COM_READ_ANDX Reserved
391  p++;
392  if (!(--input_len))
393  break;
394  /* fall through */
395  case 17:
396  // SMB_COM_READ_ANDX Reserved
397  p++;
398  if (!(--input_len))
399  break;
400  /* fall through */
401  case 18:
402  // SMB_COM_READ_ANDX Reserved
403  p++;
404  --input_len;
405  break;
406  default:
407  sstate->bytesprocessed++;
408  SCReturnUInt(1);
409  break;
410 
411  }
412  sstate->bytesprocessed += (p - input);
413  SCReturnUInt((uint32_t)(p - input));
414 }
415 
416 static uint32_t SMBParseTransact(Flow *f, void *smb_state,
417  AppLayerParserState *pstate, uint8_t *input, uint32_t input_len)
418 {
419  SCEnter();
420 
421  SMBState *sstate = (SMBState *) smb_state;
422  uint8_t *p = input;
423 
424  switch (sstate->andx.andxbytesprocessed) {
425  case 0:
426  sstate->andx.paddingparsed = 0;
427  if (input_len >= 26) {
428  sstate->andx.datalength = *(p + 22);
429  sstate->andx.datalength |= *(p + 23) << 8;
430  sstate->andx.dataoffset = *(p + 24);
431  sstate->andx.dataoffset |= *(p + 25) << 8;
432  sstate->andx.datalength |= (uint64_t) *(p + 14) << 56;
433  sstate->andx.datalength |= (uint64_t) *(p + 15) << 48;
434  sstate->andx.datalength |= (uint64_t) *(p + 16) << 40;
435  sstate->andx.datalength |= (uint64_t) *(p + 17) << 32;
436  sstate->bytesprocessed += 26;
437  sstate->andx.andxbytesprocessed += 26;
439  } else {
440  /* total parameter count 1 */
441  p++;
442  if (!(--input_len))
443  break;
444  }
445  /* fall through */
446  case 1:
447  /* total parameter count 2 */
448  p++;
449  if (!(--input_len))
450  break;
451  /* fall through */
452  case 2:
453  /* total data count 1 */
454  p++;
455  if (!(--input_len))
456  break;
457  /* fall through */
458  case 3:
459  /* total data count 2 */
460  p++;
461  if (!(--input_len))
462  break;
463  /* fall through */
464  case 4:
465  /* max parameter count 1 */
466  p++;
467  if (!(--input_len))
468  break;
469  /* fall through */
470  case 5:
471  /* max parameter count 2 */
472  p++;
473  if (!(--input_len))
474  break;
475  /* fall through */
476  case 6:
477  /* max data count 1 */
478  p++;
479  if (!(--input_len))
480  break;
481  /* fall through */
482  case 7:
483  /* max data count 2 */
484  p++;
485  if (!(--input_len))
486  break;
487  /* fall through */
488  case 8:
489  /* max setup count */
490  p++;
491  if (!(--input_len))
492  break;
493  /* fall through */
494  case 9:
495  /* Reserved */
496  p++;
497  if (!(--input_len))
498  break;
499  /* fall through */
500  case 10:
501  /* Flags */
502  p++;
503  if (!(--input_len))
504  break;
505  /* fall through */
506  case 11:
507  /* Flags */
508  p++;
509  if (!(--input_len))
510  break;
511  /* fall through */
512  case 12:
513  /* Timeout */
514  p++;
515  if (!(--input_len))
516  break;
517  /* fall through */
518  case 13:
519  /* Timeout */
520  p++;
521  if (!(--input_len))
522  break;
523  /* fall through */
524  case 14:
525  /* Timeout */
526  p++;
527  if (!(--input_len))
528  break;
529  /* fall through */
530  case 15:
531  /* Timeout */
532  p++;
533  if (!(--input_len))
534  break;
535  /* fall through */
536  case 16:
537  /* Reserved */
538  p++;
539  if (!(--input_len))
540  break;
541  /* fall through */
542  case 17:
543  /* Reserved */
544  p++;
545  if (!(--input_len))
546  break;
547  /* fall through */
548  case 18:
549  /* Parameter Count */
550  p++;
551  if (!(--input_len))
552  break;
553  /* fall through */
554  case 19:
555  /* Parameter Count */
556  p++;
557  if (!(--input_len))
558  break;
559  /* fall through */
560  case 20:
561  /* Parameter Offset */
562  p++;
563  if (!(--input_len))
564  break;
565  /* fall through */
566  case 21:
567  /* Parameter Offset */
568  p++;
569  if (!(--input_len))
570  break;
571  /* fall through */
572  case 22:
573  /* Data Count */
574  sstate->andx.datalength = *(p++);
575  if (!(--input_len))
576  break;
577  /* fall through */
578  case 23:
579  /* Data Count */
580  sstate->andx.datalength |= *(p++) << 8;
581  if (!(--input_len))
582  break;
583  /* fall through */
584  case 24:
585  /* Data Offset */
586  sstate->andx.dataoffset = *(p++);
587  if (!(--input_len))
588  break;
589  /* fall through */
590  case 25:
591  /* Data Offset */
592  sstate->andx.dataoffset |= *(p++) << 8;
593  if (!(--input_len))
594  break;
595  /* fall through */
596  case 26:
597  /* Setup Count */
598  p++;
599  if (!(--input_len))
600  break;
601  /* fall through */
602  case 27:
603  /* Reserved */
604  p++;
605  if (!(--input_len))
606  break;
607  /* fall through */
608  case 28:
609  p++;
610  if (!(--input_len))
611  break;
612  /* fall through */
613  case 29:
614  p++;
615  if (!(--input_len))
616  break;
617  /* fall through */
618  case 30:
619  p++;
620  if (!(--input_len))
621  break;
622  /* fall through */
623  case 31:
624  p++;
625  --input_len;
626  break;
627  default:
628  SCLogDebug("SMB_COM_TRANSACTION AndX bytes processed is greater than 31 %u", sstate->andx.andxbytesprocessed);
629  sstate->bytesprocessed++;
630  sstate->andx.andxbytesprocessed++;
631  SCReturnUInt(1);
632  break;
633  }
634  sstate->bytesprocessed += (p - input);
635  sstate->andx.andxbytesprocessed += (p - input);
636  SCReturnUInt((uint32_t)(p - input));
637 }
638 
639 /**
640  * Handle variable length padding for WriteAndX and ReadAndX
641  */
642 static uint32_t PaddingParser(void *smb_state, AppLayerParserState *pstate,
643  uint8_t *input, uint32_t input_len)
644 {
645  SCEnter();
646 
647  SMBState *sstate = (SMBState *) smb_state;
648  uint8_t *p = input;
649 
650  /* Check for validity of dataoffset */
651  if ((uint64_t)(sstate->bytesprocessed - NBSS_HDR_LEN) > sstate->andx.dataoffset) {
652  sstate->andx.paddingparsed = 1;
653  SCReturnUInt((uint32_t)(p - input));
654  }
655  while (((uint64_t)(sstate->bytesprocessed - NBSS_HDR_LEN) + (p - input))
656  < sstate->andx.dataoffset && sstate->bytecount.bytecountleft--
657  && input_len--) {
658  SCLogDebug("0x%02x ", *p);
659  p++;
660  }
661  if (((uint64_t)(sstate->bytesprocessed - NBSS_HDR_LEN) + (p - input))
662  == sstate->andx.dataoffset) {
663  sstate->andx.paddingparsed = 1;
664  }
665  sstate->bytesprocessed += (p - input);
666  SCReturnUInt((uint32_t)(p - input));
667 }
668 
669 /**
670  * \brief Parse WriteAndX and ReadAndX Data
671  * \retval -1 f DCERPCParser does not validate
672  * \retval Number of bytes processed
673  */
674 static int32_t DataParser(void *smb_state, AppLayerParserState *pstate,
675  uint8_t *input, uint32_t input_len)
676 {
677  SCEnter();
678 
679  SMBState *sstate = (SMBState *) smb_state;
680  int32_t parsed = 0;
681 
682  if (sstate->andx.paddingparsed) {
683  parsed = DCERPCParser(&sstate->ds.dcerpc, input, input_len);
684  if (parsed == -1 || parsed > sstate->bytecount.bytecountleft || parsed > (int32_t)input_len) {
685  SCReturnInt(-1);
686  } else {
687  sstate->dcerpc_present = 1;
688  sstate->bytesprocessed += parsed;
689  sstate->bytecount.bytecountleft -= parsed;
690  input_len -= parsed;
691  (void)input_len; /* for scan-build */
692  }
693  }
694  SCReturnInt(parsed);
695 }
696 
697 /**
698  * \brief Obtain SMB WordCount which is 2 times the value.
699  * Reset bytecount.bytecountbytes to 0.
700  * Determine if this is an SMB AndX Command
701  */
702 static uint32_t SMBGetWordCount(Flow *f, void *smb_state,
703  AppLayerParserState *pstate, uint8_t *input, uint32_t input_len)
704 {
705  SCEnter();
706 
707  if (input_len > 0) {
708  SMBState *sstate = (SMBState *) smb_state;
709  sstate->wordcount.wordcount = *(input) * 2;
710  sstate->wordcount.wordcountleft = sstate->wordcount.wordcount;
711  sstate->bytesprocessed++;
712  sstate->bytecount.bytecountbytes = 0;
713  sstate->andx.isandx = isAndX(sstate);
714  SCLogDebug("Wordcount (%u):", sstate->wordcount.wordcount);
715  SCReturnUInt(1U);
716  }
717 
718  SCReturnUInt(0);
719 }
720 
721 /*
722  * Obtain SMB Bytecount. Handle the corner obfuscation case where a packet boundary
723  * is after the first bytecount byte.
724  */
725 
726 static uint32_t SMBGetByteCount(Flow *f, void *smb_state,
727  AppLayerParserState *pstate, uint8_t *input, uint32_t input_len)
728 {
729  SCEnter();
730 
731  SMBState *sstate = (SMBState *) smb_state;
732  uint8_t *p = input;
733 
734  if (input_len && sstate->bytesprocessed == NBSS_HDR_LEN + SMB_HDR_LEN + 1
735  + sstate->wordcount.wordcount) {
736  sstate->bytecount.bytecount = *(p++);
737  sstate->bytesprocessed++;
738  --input_len;
739  }
740 
741  if (input_len && sstate->bytesprocessed == NBSS_HDR_LEN + SMB_HDR_LEN + 2
742  + sstate->wordcount.wordcount) {
743  sstate->bytecount.bytecount |= *(p++) << 8;
744  sstate->bytecount.bytecountleft = sstate->bytecount.bytecount;
745  sstate->bytesprocessed++;
746  SCLogDebug("Bytecount %u", sstate->bytecount.bytecount);
747  --input_len;
748  }
749 
750  SCReturnUInt((uint32_t)(p - input));
751 }
752 
753 /**
754  * \brief SMBParseWordCount parses the SMB Wordcount portion of the SMB Transaction.
755  * until sstate->wordcount.wordcount bytes are parsed.
756  */
757 static uint32_t SMBParseWordCount(Flow *f, void *smb_state,
758  AppLayerParserState *pstate, uint8_t *input, uint32_t input_len)
759 {
760  SCEnter();
761 
762  SMBState *sstate = (SMBState *) smb_state;
763  uint8_t *p = input;
764  uint32_t retval = 0;
765 
766  if ((sstate->smb.flags & SMB_FLAGS_SERVER_TO_REDIR) && sstate->smb.command
767  == SMB_COM_READ_ANDX) {
768  retval = SMBParseReadAndX(f, sstate, pstate, input, input_len);
769  if (retval <= sstate->wordcount.wordcountleft) {
770  sstate->wordcount.wordcountleft -= retval;
771  SCLogDebug("SMB_COM_READ_ANDX returned %d - %u bytes at offset %"PRIu64"", retval, sstate->andx.datalength, sstate->andx.dataoffset);
772  SCReturnUInt(retval);
773  } else {
774  SCReturnUInt(0U);
775  }
776 
777  } else if (((sstate->smb.flags & SMB_FLAGS_SERVER_TO_REDIR) == 0)
778  && sstate->smb.command == SMB_COM_WRITE_ANDX) {
779  retval = SMBParseWriteAndX(f, sstate, pstate, input, input_len);
780  if (retval <= sstate->wordcount.wordcountleft) {
781  sstate->wordcount.wordcountleft -= retval;
782  SCLogDebug("SMB_COM_WRITE_ANDX returned %d - %u bytes at offset %"PRIu64"", retval, sstate->andx.datalength, sstate->andx.dataoffset);
783  SCReturnUInt(retval);
784  } else {
785  SCReturnUInt(0U);
786  }
787 
788  } else if (sstate->smb.command == SMB_COM_TRANSACTION) {
789  retval = SMBParseTransact(f, sstate, pstate, input, input_len);
790  if (retval <= sstate->wordcount.wordcountleft) {
791  sstate->wordcount.wordcountleft -= retval;
792  SCLogDebug("SMB_COM_TRANSACTION returned %d - %u bytes at offset %"PRIu64"", retval, sstate->andx.datalength, sstate->andx.dataoffset);
793  SCReturnUInt(retval);
794  } else {
795  SCReturnUInt(0U);
796  }
797 
798  } else { /* Generic WordCount Handler */
799  while (sstate->wordcount.wordcountleft-- && input_len--) {
800  SCLogDebug("0x%02x wordcount %u/%u input_len %u", *p,
801  sstate->wordcount.wordcountleft,
802  sstate->wordcount.wordcount, input_len);
803  p++;
804  }
805  sstate->bytesprocessed += (p - input);
806  SCReturnUInt((uint32_t)(p - input));
807  }
808 }
809 
810 /**
811  * \brief SMBParseByteCount parses the SMB ByteCount portion of the SMB Transaction.
812  * until sstate->bytecount.bytecount bytes are parsed.
813  */
814 static uint32_t SMBParseByteCount(Flow *f, void *smb_state,
815  AppLayerParserState *pstate, uint8_t *input, uint32_t input_len)
816 {
817  SCEnter();
818 
819  SMBState *sstate = (SMBState *) smb_state;
820  uint8_t *p = input;
821  uint32_t ures = 0; /* unsigned */
822  int32_t sres = 0; /* signed */
823  uint32_t parsed = 0;
824 
825  if (((sstate->smb.flags & SMB_FLAGS_SERVER_TO_REDIR) &&
826  sstate->smb.command == SMB_COM_READ_ANDX) ||
827  (((sstate->smb.flags & SMB_FLAGS_SERVER_TO_REDIR) == 0)
828  && sstate->smb.command == SMB_COM_WRITE_ANDX) ||
829  (sstate->smb.command == SMB_COM_TRANSACTION))
830  {
831  if (sstate->andx.paddingparsed == 0) {
832  ures = PaddingParser(sstate, pstate, input + parsed, input_len);
833  if (ures <= input_len) {
834  parsed += ures;
835  input_len -= ures;
836  } else {
837  SCReturnUInt(0U);
838  }
839  }
840 
841  if (sstate->andx.datalength && input_len) {
842  /* Uncomment the next line to help debug DCERPC over SMB */
843  //hexdump(f, input + parsed, input_len);
844  sres = DataParser(sstate, pstate, input + parsed, input_len);
845  if (sres != -1 && sres <= (int32_t)input_len) {
846  parsed += (uint32_t)sres;
847  (void)parsed; /* for scan-build */
848  input_len -= (uint32_t)sres;
849  (void)input_len; /* for scan-build */
850  } else { /* Did not Validate as DCERPC over SMB */
851  while (sstate->bytecount.bytecountleft-- && input_len--) {
852  SCLogDebug("0x%02x bytecount %"PRIu16"/%"PRIu16" input_len %"PRIu32, *p,
853  sstate->bytecount.bytecountleft,
854  sstate->bytecount.bytecount, input_len);
855  p++;
856  }
857  sstate->bytesprocessed += (p - input);
858  SCReturnUInt((p - input));
859  }
860  }
861  SCReturnUInt(ures);
862  }
863 
864  while (sstate->bytecount.bytecountleft-- && input_len--) {
865  SCLogDebug("0x%02x bytecount %u/%u input_len %u", *p,
866  sstate->bytecount.bytecountleft,
867  sstate->bytecount.bytecount, input_len);
868  p++;
869  }
870  sstate->bytesprocessed += (p - input);
871 
872  SCReturnUInt((p - input));
873 }
874 
875 /**
876  * \brief Parse a NBSS header.
877  *
878  * \retval 4 parsing of the header is done
879  * \retval 3 parsing partially done
880  * \retval 2 parsing partially done
881  * \retval 1 parsing partially done
882  * \retval 0 no input or already done
883  */
884 static uint32_t NBSSParseHeader(Flow *f, void *smb_state,
885  AppLayerParserState *pstate, uint8_t *input, uint32_t input_len)
886 {
887  SCEnter();
888 
889  SMBState *sstate = (SMBState *) smb_state;
890  uint8_t *p = input;
891 
892  if (input_len > 0 && sstate->bytesprocessed < (NBSS_HDR_LEN - 1)) {
893  switch (sstate->bytesprocessed) {
894  case 0:
895  /* Initialize */
897  sstate->andx.maxchainedandx = 5;
898 
899  /* fast track for having all bytes (common case) */
900  if (input_len >= NBSS_HDR_LEN) {
901  sstate->nbss.type = *p;
902  sstate->nbss.length = (*(p + 1) & 0x01) << 16;
903  sstate->nbss.length |= *(p + 2) << 8;
904  sstate->nbss.length |= *(p + 3);
905  sstate->bytesprocessed += NBSS_HDR_LEN;
906  SCReturnUInt(4U);
907  } else {
908  sstate->nbss.type = *(p++);
909  if (!(--input_len))
910  break;
911  }
912  /* fall through */
913  case 1:
914  sstate->nbss.length = (*(p++) & 0x01) << 16;
915  if (!(--input_len))
916  break;
917  /* fall through */
918  case 2:
919  sstate->nbss.length |= *(p++) << 8;
920  if (!(--input_len))
921  break;
922  /* fall through */
923  case 3:
924  sstate->nbss.length |= *(p++);
925  --input_len;
926  break;
927  }
928  sstate->bytesprocessed += (p - input);
929  }
930 
931  SCReturnUInt((uint32_t)(p - input));
932 }
933 
934 /**
935  * \brief parse and validate the 32 byte SMB Header
936  *
937  * \retval 32 parsing done
938  * \retval >0<32 parsing in progress
939  * \retval 0 no input or already fully parsed
940  * \retval -1 error
941  */
942 static int SMBParseHeader(Flow *f, void *smb_state,
943  AppLayerParserState *pstate, uint8_t *input, uint32_t input_len)
944 {
945  SCEnter();
946 
947  SMBState *sstate = (SMBState *) smb_state;
948  uint8_t *p = input;
949 
950  if (input_len > 0) {
951  switch (sstate->bytesprocessed) {
952  case 4:
953  // fallthrough
954  /* above statement to prevent coverity FPs from the switch
955  * fall through */
956  if (input_len >= SMB_HDR_LEN) {
957  if (SCMemcmp(p, "\xff\x53\x4d\x42", 4) != 0) {
958  SCLogDebug("SMB Header did not validate");
959  SCReturnInt(-1);
960  }
961  sstate->smb.command = *(p + 4);
962  sstate->smb.status = (uint32_t) *(p + 5) << 24;
963  sstate->smb.status |= (uint32_t) *(p + 6) << 16;
964  sstate->smb.status |= (uint32_t) *(p + 7) << 8;
965  sstate->smb.status |= (uint32_t) *(p + 8);
966  sstate->smb.flags = *(p + 9);
967  sstate->smb.flags2 = *(p + 10) << 8;
968  sstate->smb.flags2 |= *(p + 11);
969  sstate->smb.pidhigh = *(p + 12) << 8;
970  sstate->smb.pidhigh |= *(p + 13);
971  sstate->smb.securitysignature = (uint64_t) *(p + 14) << 56;
972  sstate->smb.securitysignature |= (uint64_t) *(p + 15) << 48;
973  sstate->smb.securitysignature |= (uint64_t) *(p + 16) << 40;
974  sstate->smb.securitysignature |= (uint64_t) *(p + 17) << 32;
975  sstate->smb.securitysignature |= (uint64_t) *(p + 18) << 24;
976  sstate->smb.securitysignature |= (uint64_t) *(p + 19) << 16;
977  sstate->smb.securitysignature |= (uint64_t) *(p + 20) << 8;
978  sstate->smb.securitysignature |= (uint64_t) *(p + 21);
979  sstate->smb.tid = *(p + 24) << 8;
980  sstate->smb.tid |= *(p + 25);
981  sstate->smb.pid = *(p + 26) << 8;
982  sstate->smb.pid |= *(p + 27);
983  sstate->smb.uid = *(p + 28) << 8;
984  sstate->smb.uid |= *(p + 29);
985  sstate->smb.mid = *(p + 30) << 8;
986  sstate->smb.mid |= *(p + 31);
987  sstate->bytesprocessed += SMB_HDR_LEN;
988  SCReturnInt(32);
989  break;
990  } else {
991  if (*(p++) != 0xff) {
992  SCLogDebug("SMB Header did not validate");
993  SCReturnInt(-1);
994  }
995  if (!(--input_len))
996  break;
997  /* We fall through to the next case if we still have input.
998  * Same applies for other cases as well */
999  }
1000  /* fall through */
1001  case 5:
1002  if (*(p++) != 'S') {
1003  SCLogDebug("SMB Header did not validate");
1004  SCReturnInt(-1);
1005  }
1006  if (!(--input_len))
1007  break;
1008  /* fall through */
1009  case 6:
1010  if (*(p++) != 'M') {
1011  SCLogDebug("SMB Header did not validate");
1012  SCReturnInt(-1);
1013  }
1014  if (!(--input_len))
1015  break;
1016  /* fall through */
1017  case 7:
1018  if (*(p++) != 'B') {
1019  SCLogDebug("SMB Header did not validate");
1020  SCReturnInt(-1);
1021  }
1022  if (!(--input_len))
1023  break;
1024  /* fall through */
1025  case 8:
1026  sstate->smb.command = *(p++);
1027  if (!(--input_len))
1028  break;
1029  /* fall through */
1030  case 9:
1031  sstate->smb.status = *(p++) << 24;
1032  if (!(--input_len))
1033  break;
1034  /* fall through */
1035  case 10:
1036  sstate->smb.status |= *(p++) << 16;
1037  if (!(--input_len))
1038  break;
1039  /* fall through */
1040  case 11:
1041  sstate->smb.status |= *(p++) << 8;
1042  if (!(--input_len))
1043  break;
1044  /* fall through */
1045  case 12:
1046  sstate->smb.status |= *(p++);
1047  if (!(--input_len))
1048  break;
1049  /* fall through */
1050  case 13:
1051  sstate->smb.flags = *(p++);
1052  if (!(--input_len))
1053  break;
1054  /* fall through */
1055  case 14:
1056  sstate->smb.flags2 = *(p++) << 8;
1057  if (!(--input_len))
1058  break;
1059  /* fall through */
1060  case 15:
1061  sstate->smb.flags2 |= *(p++);
1062  if (!(--input_len))
1063  break;
1064  /* fall through */
1065  case 16:
1066  sstate->smb.pidhigh = *(p++) << 8;
1067  if (!(--input_len))
1068  break;
1069  /* fall through */
1070  case 17:
1071  sstate->smb.pidhigh |= *(p++);
1072  if (!(--input_len))
1073  break;
1074  /* fall through */
1075  case 18:
1076  sstate->smb.securitysignature = (uint64_t) *(p++) << 56;
1077  if (!(--input_len))
1078  break;
1079  /* fall through */
1080  case 19:
1081  sstate->smb.securitysignature |= (uint64_t) *(p++) << 48;
1082  if (!(--input_len))
1083  break;
1084  /* fall through */
1085  case 20:
1086  sstate->smb.securitysignature |= (uint64_t) *(p++) << 40;
1087  if (!(--input_len))
1088  break;
1089  /* fall through */
1090  case 21:
1091  sstate->smb.securitysignature |= (uint64_t) *(p++) << 32;
1092  if (!(--input_len))
1093  break;
1094  /* fall through */
1095  case 22:
1096  sstate->smb.securitysignature |= (uint64_t) *(p++) << 24;
1097  if (!(--input_len))
1098  break;
1099  /* fall through */
1100  case 23:
1101  sstate->smb.securitysignature |= (uint64_t) *(p++) << 16;
1102  if (!(--input_len))
1103  break;
1104  /* fall through */
1105  case 24:
1106  sstate->smb.securitysignature |= (uint64_t) *(p++) << 8;
1107  if (!(--input_len))
1108  break;
1109  /* fall through */
1110  case 25:
1111  sstate->smb.securitysignature |= (uint64_t) *(p++);
1112  if (!(--input_len))
1113  break;
1114  /* fall through */
1115  case 26:
1116  p++; // UNUSED
1117  if (!(--input_len))
1118  break;
1119  /* fall through */
1120  case 27:
1121  p++; // UNUSED
1122  if (!(--input_len))
1123  break;
1124  /* fall through */
1125  case 28:
1126  sstate->smb.tid = *(p++) << 8;
1127  if (!(--input_len))
1128  break;
1129  /* fall through */
1130  case 29:
1131  sstate->smb.tid |= *(p++);
1132  if (!(--input_len))
1133  break;
1134  /* fall through */
1135  case 30:
1136  sstate->smb.pid = *(p++) << 8;
1137  if (!(--input_len))
1138  break;
1139  /* fall through */
1140  case 31:
1141  sstate->smb.pid |= *(p++);
1142  if (!(--input_len))
1143  break;
1144  /* fall through */
1145  case 32:
1146  sstate->smb.uid = *(p++) << 8;
1147  if (!(--input_len))
1148  break;
1149  /* fall through */
1150  case 33:
1151  sstate->smb.uid |= *(p++);
1152  if (!(--input_len))
1153  break;
1154  /* fall through */
1155  case 34:
1156  sstate->smb.mid = *(p++) << 8;
1157  if (!(--input_len))
1158  break;
1159  /* fall through */
1160  case 35:
1161  sstate->smb.mid |= *(p++);
1162  --input_len;
1163  break;
1164  /* fall through */
1165  }
1166  }
1167  sstate->bytesprocessed += (p - input);
1168 
1169  SCReturnInt((p - input));
1170 }
1171 
1172 static int SMBParse(Flow *f, void *smb_state, AppLayerParserState *pstate,
1173  uint8_t *input, uint32_t input_len,
1174  void *local_data, uint8_t dir)
1175 {
1176  SCEnter();
1177 
1178  SMBState *sstate = (SMBState *) smb_state;
1179  uint64_t retval = 0;
1180  uint64_t parsed = 0;
1181  int hdrretval = 0;
1182  int counter = 0;
1183 
1184  if (pstate == NULL) {
1185  SCLogDebug("pstate == NULL");
1186  SCReturnInt(0);
1187  }
1188 
1189  if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) {
1190  SCReturnInt(1);
1191  } else if (input == NULL) {
1192  SCReturnInt(-1);
1193  }
1194 
1195  if (sstate->bytesprocessed != 0 && sstate->data_needed_for_dir != dir) {
1196  SCReturnInt(-1);
1197  }
1198 
1199  while (input_len) {
1200  /* till we clear corner cases */
1201  if (counter++ == 30) {
1202  SCLogDebug("Somehow seem to be stuck inside the smb "
1203  "parser for quite sometime. Let's get out of here.");
1204  sstate->bytesprocessed = 0;
1205  SCReturnInt(0);
1206  }
1207 
1208  while (input_len && sstate->bytesprocessed < NBSS_HDR_LEN) {
1209  retval = NBSSParseHeader(f, smb_state, pstate, input + parsed,
1210  input_len);
1211  if (retval && retval <= input_len) {
1212  parsed += retval;
1213  input_len -= retval;
1214  SCLogDebug("[1] NBSS Header (%u/%u) Type 0x%02x Length 0x%04x "
1215  "parsed %"PRIu64" input_len %u",
1216  sstate->bytesprocessed, NBSS_HDR_LEN, sstate->nbss.type,
1217  sstate->nbss.length, parsed, input_len);
1218  } else if (input_len) {
1219  SCLogDebug("Error parsing NBSS Header");
1220  sstate->bytesprocessed = 0;
1221  SCReturnInt(0);
1222  }
1223  }
1224 
1225  switch (sstate->nbss.type) {
1226  case NBSS_SESSION_MESSAGE:
1227  while (input_len &&
1228  (sstate->bytesprocessed >= NBSS_HDR_LEN &&
1229  sstate->bytesprocessed < NBSS_HDR_LEN + SMB_HDR_LEN)) {
1230  /* inside while */
1231  hdrretval = SMBParseHeader(f, smb_state, pstate, input + parsed,
1232  input_len);
1233  if (hdrretval == -1 || hdrretval > (int32_t)input_len) {
1234  SCLogDebug("Error parsing SMB Header");
1235  sstate->bytesprocessed = 0;
1236  SCReturnInt(0);
1237  } else {
1238  parsed += hdrretval;
1239  input_len -= hdrretval;
1240  SCLogDebug("[2] SMB Header (%u/%u) Command 0x%02x "
1241  "parsed %"PRIu64" input_len %u",
1243  sstate->smb.command, parsed, input_len);
1244  }
1245  } /* while */
1246 
1247  do {
1248  if (input_len &&
1249  (sstate->bytesprocessed == NBSS_HDR_LEN + SMB_HDR_LEN)) {
1250  /* inside if */
1251  retval = SMBGetWordCount(f, smb_state, pstate, input + parsed,
1252  input_len);
1253  if (retval && retval <= input_len) {
1254  parsed += retval;
1255  input_len -= retval;
1256  } else if (input_len) {
1257  SCLogDebug("Error parsing SMB Word Count");
1258  sstate->bytesprocessed = 0;
1259  SCReturnInt(0);
1260  }
1261  SCLogDebug("[3] WordCount (%u/%u) WordCount %u parsed "
1262  "%"PRIu64" input_len %u",
1263  sstate->bytesprocessed,
1264  NBSS_HDR_LEN + SMB_HDR_LEN + 1,
1265  sstate->wordcount.wordcount,
1266  parsed, input_len);
1267  } /* if (input_len && ..) */
1268 
1269  while (input_len &&
1270  (sstate->bytesprocessed >= NBSS_HDR_LEN + SMB_HDR_LEN + 1 &&
1271  sstate->bytesprocessed < (NBSS_HDR_LEN + SMB_HDR_LEN + 1 +
1272  sstate->wordcount.wordcount))) {
1273  /* inside while */
1274  retval = SMBParseWordCount(f, smb_state, pstate,
1275  input + parsed, input_len);
1276  if (retval && retval <= input_len) {
1277  parsed += retval;
1278  input_len -= retval;
1279  } else if (input_len) {
1280  SCLogDebug("Error parsing SMB Word Count Data retval "
1281  "%"PRIu64" input_len %u", retval, input_len);
1282  sstate->bytesprocessed = 0;
1283  SCReturnInt(0);
1284  }
1285  SCLogDebug("[4] Parsing WordCount (%u/%u) WordCount %u "
1286  "parsed %"PRIu64" input_len %u",
1287  sstate->bytesprocessed,
1288  NBSS_HDR_LEN + SMB_HDR_LEN + 1 +
1289  sstate->wordcount.wordcount,
1290  sstate->wordcount.wordcount,
1291  parsed, input_len);
1292  } /* while (input_len && ..) */
1293 
1294  while (input_len &&
1295  (sstate->bytesprocessed >= (NBSS_HDR_LEN + SMB_HDR_LEN +
1296  1 + sstate->wordcount.wordcount) &&
1297  sstate->bytesprocessed < (NBSS_HDR_LEN + SMB_HDR_LEN + 3
1298  + sstate->wordcount.wordcount))) {
1299  /* inside while */
1300  retval = SMBGetByteCount(f, smb_state, pstate, input + parsed,
1301  input_len);
1302  if (retval && retval <= input_len) {
1303  parsed += retval;
1304  input_len -= retval;
1305  } else if (input_len) {
1306  SCLogDebug("Error parsing SMB Byte Count");
1307  sstate->bytesprocessed = 0;
1308  SCReturnInt(0);
1309  }
1310  SCLogDebug("[5] ByteCount (%u/%u) ByteCount %u parsed "
1311  "%"PRIu64" input_len %u",
1312  sstate->bytesprocessed,
1313  NBSS_HDR_LEN + SMB_HDR_LEN + 3,
1314  sstate->bytecount.bytecount,
1315  parsed, input_len);
1316 
1317  if (sstate->bytecount.bytecount == 0) {
1318  sstate->bytesprocessed = 0;
1319  input_len = 0;
1320  }
1321  } /* while (input_len && ..) */
1322 
1323  while (input_len &&
1324  (sstate->bytesprocessed >= (NBSS_HDR_LEN + SMB_HDR_LEN +
1325  3 + sstate->wordcount.wordcount)) &&
1326  (sstate->bytesprocessed < (NBSS_HDR_LEN + SMB_HDR_LEN + 3
1327  + sstate->wordcount.wordcount
1328  + sstate->bytecount.bytecount))) {
1329  /* inside while */
1330  retval = SMBParseByteCount(f, smb_state, pstate,
1331  input + parsed, input_len);
1332  if (retval && retval <= input_len) {
1333  parsed += retval;
1334  input_len -= retval;
1335  } else if (input_len) {
1336  SCLogDebug("Error parsing SMB Byte Count Data");
1337  sstate->bytesprocessed = 0;
1338  SCReturnInt(0);
1339  }
1340  SCLogDebug("[6] Parsing ByteCount (%u/%u) ByteCount %u "
1341  "parsed %"PRIu64" input_len %u",
1342  sstate->bytesprocessed,
1343  NBSS_HDR_LEN + SMB_HDR_LEN + 1 +
1344  sstate->wordcount.wordcount + 2 +
1345  sstate->bytecount.bytecount,
1346  sstate->bytecount.bytecount, parsed, input_len);
1347  } /* while (input_len && ..) */
1348 
1349  } while (sstate->andx.andxcommand != SMB_NO_SECONDARY_ANDX_COMMAND &&
1350  input_len && sstate->andx.maxchainedandx--);
1351 
1352  if (sstate->bytesprocessed >= sstate->nbss.length + NBSS_HDR_LEN ||
1353  sstate->andx.maxchainedandx == 0) {
1354  /* inside if */
1355  sstate->bytesprocessed = 0;
1356  sstate->transaction_id++;
1357  input_len = 0;
1358  }
1359  break;
1360 
1361  case NBSS_SESSION_REQUEST:
1366  if (sstate->bytesprocessed < (sstate->nbss.length + NBSS_HDR_LEN)) {
1367  if (input_len >= (sstate->nbss.length + NBSS_HDR_LEN -
1368  sstate->bytesprocessed)) {
1369  /* inside if */
1370  input_len -= (sstate->nbss.length + NBSS_HDR_LEN -
1371  sstate->bytesprocessed);
1372  parsed += (sstate->nbss.length + NBSS_HDR_LEN -
1373  sstate->bytesprocessed);
1374  sstate->bytesprocessed = 0;
1375  } else {
1376  sstate->bytesprocessed += input_len;
1377  input_len = 0;
1378  }
1379  } else {
1380  sstate->bytesprocessed = 0;
1381  }
1382  break;
1383 
1384  default:
1385  sstate->bytesprocessed = 0;
1386  break;
1387  } /* switch */
1388 
1389  } /* while (input_len) */
1390 
1391  sstate->data_needed_for_dir = dir;
1392  SCReturnInt(1);
1393 }
1394 
1395 static int SMBParseRequest(Flow *f, void *smb_state, AppLayerParserState *pstate,
1396  uint8_t *input, uint32_t input_len,
1397  void *local_data, const uint8_t flags)
1398 {
1399  return SMBParse(f, smb_state, pstate, input, input_len, local_data, 0);
1400 }
1401 
1402 static int SMBParseResponse(Flow *f, void *smb_state, AppLayerParserState *pstate,
1403  uint8_t *input, uint32_t input_len,
1404  void *local_data, const uint8_t flags)
1405 {
1406  return SMBParse(f, smb_state, pstate, input, input_len, local_data, 1);
1407 }
1408 
1409 
1410 /**
1411  * \brief determines if the SMB command is an ANDX command
1412  * \retval 1 if smb command is an AndX command
1413  * \retval 0 if smb command is not an AndX command
1414  */
1415 
1416 int isAndX(SMBState *smb_state)
1417 {
1418  SCEnter();
1419 
1420  switch (smb_state->smb.command) {
1422  case SMB_COM_LOCKING_ANDX:
1423  case SMB_COM_OPEN_ANDX:
1424  case SMB_COM_READ_ANDX:
1425  case SMB_COM_WRITE_ANDX:
1427  case SMB_COM_LOGOFF_ANDX:
1430  smb_state->andx.andxbytesprocessed = 0;
1431  SCReturnInt(1);
1432  default:
1433  SCReturnInt(0);
1434  }
1435 }
1436 
1437 /** \internal
1438  * \brief Allocate a SMBState
1439  * \retval s State, or NULL in case of error
1440  */
1441 static void *SMBStateAlloc(void)
1442 {
1443  SCEnter();
1444 
1445  SMBState *s = (SMBState *)SCCalloc(1, sizeof(SMBState));
1446  if (unlikely(s == NULL)) {
1447  SCReturnPtr(NULL, "void");
1448  }
1449 
1450  DCERPCInit(&s->ds.dcerpc);
1451 
1452  SCReturnPtr(s, "void");
1453 }
1454 
1455 /** \internal
1456  * \brief Free a SMBState
1457  */
1458 static void SMBStateFree(void *s)
1459 {
1460  SCEnter();
1461  SMBState *sstate = (SMBState *) s;
1462 
1463  DCERPCCleanup(&sstate->ds.dcerpc);
1464 
1465  if (sstate->ds.de_state) {
1467  }
1468 
1469  SCFree(s);
1470  SCReturn;
1471 }
1472 
1473 static int SMBSetTxDetectState(void *vtx, DetectEngineState *de_state)
1474 {
1475  SMBState *smb_state = (SMBState *)vtx;
1476  smb_state->ds.de_state = de_state;
1477  return 0;
1478 }
1479 
1480 static DetectEngineState *SMBGetTxDetectState(void *vtx)
1481 {
1482  SMBState *smb_state = (SMBState *)vtx;
1483  return smb_state->ds.de_state;
1484 }
1485 
1486 static void SMBStateTransactionFree(void *state, uint64_t tx_id)
1487 {
1488  /* do nothing */
1489 }
1490 
1491 static void *SMBGetTx(void *state, uint64_t tx_id)
1492 {
1493  SMBState *smb_state = (SMBState *)state;
1494  return smb_state;
1495 }
1496 
1497 static uint64_t SMBGetTxCnt(void *state)
1498 {
1499  /* single tx */
1500  return 1;
1501 }
1502 
1503 static int SMBGetAlstateProgressCompletionStatus(uint8_t direction)
1504 {
1505  return 1;
1506 }
1507 
1508 static int SMBGetAlstateProgress(void *tx, uint8_t direction)
1509 {
1510  return 0;
1511 }
1512 
1513 #define SMB_PROBING_PARSER_MIN_DEPTH 8
1514 
1515 static uint16_t SMBProbingParser(Flow *f, uint8_t *input, uint32_t ilen)
1516 {
1517  int32_t len;
1518  int32_t input_len = ilen;
1519 
1520  while (input_len >= SMB_PROBING_PARSER_MIN_DEPTH) {
1521  switch (input[0]) {
1522  case NBSS_SESSION_MESSAGE:
1523  if (input[4] == 0xFF && input[5] == 'S' && input[6] == 'M' &&
1524  input[7] == 'B') {
1525  return ALPROTO_SMB;
1526  }
1527 
1528  /* fall through */
1529  case NBSS_SESSION_REQUEST:
1534  len = (input[1] & 0x01) << 16;
1535  len |= input[2] << 8;
1536  len |= input[3];
1537  break;
1538  default:
1539  /* -1 indicates a stream where the probing parser would be
1540  * unable to find nbss, even if it exists. This should
1541  * prevent the probing parser from beig invoked henceforth */
1542  return ALPROTO_FAILED;
1543  }
1544 
1545  input_len -= 4;
1546  if (len >= input_len) {
1547  return ALPROTO_UNKNOWN;
1548  }
1549 
1550  input_len -= len;
1551  input += 4 + len;
1552  }
1553 
1554  return ALPROTO_UNKNOWN;
1555 }
1556 
1557 static int SMBRegisterPatternsForProtocolDetection(void)
1558 {
1559  int r = 0;
1561  "|ff|SMB", 8, 4, STREAM_TOSERVER);
1563  "|ff|SMB", 8, 4, STREAM_TOCLIENT);
1564 
1566  "|fe|SMB", 8, 4, STREAM_TOSERVER);
1568  "|fe|SMB", 8, 4, STREAM_TOCLIENT);
1569  return r == 0 ? 0 : -1;
1570 }
1571 
1573 {
1574  const char *proto_name = "smb";
1575 
1576  if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) {
1578  if (SMBRegisterPatternsForProtocolDetection() < 0)
1579  return;
1580 
1581  if (RunmodeIsUnittests()) {
1582  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
1583  "139",
1584  ALPROTO_SMB,
1587  SMBProbingParser, SMBProbingParser);
1588  } else {
1589  AppLayerProtoDetectPPParseConfPorts("tcp", IPPROTO_TCP,
1590  proto_name, ALPROTO_SMB,
1592  SMBProbingParser, SMBProbingParser);
1593  }
1594 
1596  } else {
1597  SCLogInfo("Protocol detection and parser disabled for %s protocol.",
1598  proto_name);
1599  return;
1600  }
1601 
1602  if (AppLayerParserConfParserEnabled("tcp", proto_name)) {
1603  AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_SMB, STREAM_TOSERVER, SMBParseRequest);
1604  AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_SMB, STREAM_TOCLIENT, SMBParseResponse);
1605  AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_SMB, SMBStateAlloc, SMBStateFree);
1606 
1607  AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_SMB, SMBStateTransactionFree);
1608 
1610  SMBGetTxDetectState, SMBSetTxDetectState);
1611 
1612  AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_SMB, SMBGetTx);
1613 
1614  AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_SMB, SMBGetTxCnt);
1615 
1616  AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_SMB, SMBGetAlstateProgress);
1617 
1619  SMBGetAlstateProgressCompletionStatus);
1620  } else {
1621  SCLogInfo("Parsed disabled for %s protocol. Protocol detection "
1622  "still on.", proto_name);
1623  }
1624 
1625 #ifdef UNITTESTS
1627 #endif
1628  return;
1629 }
1630 
1631 /* UNITTESTS */
1632 #ifdef UNITTESTS
1633 #include "flow-util.h"
1634 
1635 /**
1636  * \test SMBParserTest01 tests the NBSS and SMB header decoding
1637  */
1638 static int SMBParserTest01(void)
1639 {
1640  int result = 0;
1641  Flow f;
1642  uint8_t smbbuf[] = "\x00\x00\x00\x85" // NBSS
1643  "\xff\x53\x4d\x42\x72\x00\x00\x00" // SMB
1644  "\x00\x18\x53\xc8\x00\x00\x00\x00"
1645  "\x00\x00\x00\x00\x00\x00\x00\x00"
1646  "\x00\x00\xff\xfe\x00\x00\x00\x00"
1647  "\x00" // WordCount
1648  "\x62\x00" // ByteCount
1649  "\x02\x50\x43\x20\x4e\x45\x54\x57\x4f\x52\x4b\x20\x50\x52\x4f\x47\x52\x41\x4d\x20"
1650  "\x31\x2e\x30\x00\x02\x4c\x41\x4e\x4d\x41\x4e\x31\x2e\x30\x00\x02\x57\x69\x6e\x64\x6f\x77\x73"
1651  "\x20\x66\x6f\x72\x20\x57\x6f\x72\x6b\x67\x72\x6f\x75\x70\x73\x20\x33\x2e\x31\x61\x00\x02\x4c"
1652  "\x4d\x31\x2e\x32\x58\x30\x30\x32\x00\x02\x4c\x41\x4e\x4d\x41\x4e\x32\x2e\x31\x00\x02\x4e\x54"
1653  "\x20\x4c\x4d\x20\x30\x2e\x31\x32\x00";
1654 
1655  uint32_t smblen = sizeof(smbbuf) - 1;
1656  TcpSession ssn;
1658 
1659  memset(&f, 0, sizeof(f));
1660  memset(&ssn, 0, sizeof(ssn));
1661  FLOW_INITIALIZE(&f);
1662  f.protoctx = (void *)&ssn;
1663  f.proto = IPPROTO_TCP;
1664  f.alproto = ALPROTO_SMB;
1665 
1667 
1668  FLOWLOCK_WRLOCK(&f);
1669  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SMB,
1670  STREAM_TOSERVER | STREAM_EOF, smbbuf, smblen);
1671  if (r != 0) {
1672  printf("smb header check returned %" PRId32 ", expected 0: ", r);
1673  FLOWLOCK_UNLOCK(&f);
1674  goto end;
1675  }
1676  FLOWLOCK_UNLOCK(&f);
1677 
1678  SMBState *smb_state = f.alstate;
1679  if (smb_state == NULL) {
1680  printf("no smb state: ");
1681  goto end;
1682  }
1683 
1684  if (smb_state->nbss.type != NBSS_SESSION_MESSAGE) {
1685  printf("expected nbss type 0x%02x , got 0x%02x : ", NBSS_SESSION_MESSAGE, smb_state->nbss.type);
1686  goto end;
1687  }
1688 
1689  if (smb_state->nbss.length != 133) {
1690  printf("expected nbss length 0x%02x , got 0x%02x : ", 133, smb_state->nbss.length);
1691  goto end;
1692  }
1693 
1694  if (smb_state->smb.command != SMB_COM_NEGOTIATE) {
1695  printf("expected SMB command 0x%02x , got 0x%02x : ", SMB_COM_NEGOTIATE, smb_state->smb.command);
1696  goto end;
1697  }
1698 
1699  result = 1;
1700 end:
1701  if (alp_tctx != NULL)
1702  AppLayerParserThreadCtxFree(alp_tctx);
1704  FLOW_DESTROY(&f);
1705  return result;
1706 }
1707 
1708 /**
1709  * \test SMBParserTest02 tests the NBSS, SMB, and DCERPC over SMB header decoding
1710  */
1711 static int SMBParserTest02(void)
1712 {
1713  int result = 0;
1714  Flow f;
1715  uint8_t smbbuf[] = {
1716  0x00, 0x00, 0x00, 0x92, 0xff, 0x53, 0x4d, 0x42,
1717  0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
1718  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1719  0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x64, 0x05,
1720  0x00, 0x08, 0x00, 0x00, 0x10, 0x00, 0x00, 0x48,
1721  0x00, 0x00, 0x04, 0xe0, 0xff, 0x00, 0x00, 0x00,
1722  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1723  0x00, 0x4a, 0x00, 0x48, 0x00, 0x4a, 0x00, 0x02,
1724  0x00, 0x26, 0x00, 0x00, 0x40, 0x4f, 0x00, 0x5c,
1725  0x50, 0x49, 0x50, 0x45, 0x5c, 0x00, 0x05, 0x00,
1726  0x0b, 0x03, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00,
1727  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd0, 0x16,
1728  0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
1729  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0xfd,
1730  0x2c, 0x34, 0x6c, 0x3c, 0xce, 0x11, 0xa8, 0x93,
1731  0x08, 0x00, 0x2b, 0x2e, 0x9c, 0x6d, 0x00, 0x00,
1732  0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
1733  0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
1734  0x48, 0x60, 0x02, 0x00, 0x00, 0x00 };
1735 
1736  uint32_t smblen = sizeof(smbbuf);
1737  TcpSession ssn;
1739 
1740  memset(&f, 0, sizeof(f));
1741  memset(&ssn, 0, sizeof(ssn));
1742  FLOW_INITIALIZE(&f);
1743  f.protoctx = (void *)&ssn;
1744  f.proto = IPPROTO_TCP;
1745  f.alproto = ALPROTO_SMB;
1746 
1748 
1749  FLOWLOCK_WRLOCK(&f);
1750  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SMB,
1751  STREAM_TOSERVER | STREAM_EOF, smbbuf, smblen);
1752  if (r != 0) {
1753  printf("smb header check returned %" PRId32 ", expected 0: ", r);
1754  FLOWLOCK_UNLOCK(&f);
1755  goto end;
1756  }
1757  FLOWLOCK_UNLOCK(&f);
1758 
1759  SMBState *smb_state = f.alstate;
1760  if (smb_state == NULL) {
1761  printf("no smb state: ");
1762  goto end;
1763  }
1764 
1765  if (smb_state->nbss.type != NBSS_SESSION_MESSAGE) {
1766  printf("expected nbss type 0x%02x , got 0x%02x : ", NBSS_SESSION_MESSAGE, smb_state->nbss.type);
1767  goto end;
1768  }
1769 
1770  if (smb_state->nbss.length != 146) {
1771  printf("expected nbss length 0x%02x , got 0x%02x : ", 146, smb_state->nbss.length);
1772  goto end;
1773  }
1774 
1775  if (smb_state->smb.command != SMB_COM_TRANSACTION) {
1776  printf("expected SMB command 0x%02x , got 0x%02x : ", SMB_COM_TRANSACTION, smb_state->smb.command);
1777  goto end;
1778  }
1779 
1780  printUUID("BIND", smb_state->ds.dcerpc.dcerpcbindbindack.uuid_entry);
1781  result = 1;
1782 end:
1783  if (alp_tctx != NULL)
1784  AppLayerParserThreadCtxFree(alp_tctx);
1786  FLOW_DESTROY(&f);
1787  return result;
1788 }
1789 
1790 static int SMBParserTest03(void)
1791 {
1792  int result = 0;
1793  Flow f;
1794  uint8_t smbbuf1[] = {
1795  0x00, 0x00, 0x07, 0x57, 0xff, 0x53, 0x4d, 0x42,
1796  0x2f, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01, 0x20,
1797  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1798  0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x7f, 0x13,
1799  0x01, 0x08, 0xc9, 0x29, 0x0e, 0xff, 0x00, 0x00,
1800  0x00, 0x00, 0x40, 0x55, 0x01, 0x00, 0x00, 0xff,
1801  0xff, 0xff, 0xff, 0x08, 0x00, 0x0e, 0x00, 0x00,
1802  0x00, 0x0e, 0x00, 0x49, 0x07, 0x00, 0x00, 0x00,
1803  0x00, 0x18, 0x07, 0xcc, 0x1b, 0x19, 0xb8, 0x75,
1804  0x2c, 0x85, 0x52, 0x39, 0x72, 0xfa, 0x9c, 0x5f,
1805  0x5a, 0xb7, 0x59, 0xa1, 0x83, 0xba, 0x87, 0xd3,
1806  0xc3, 0xbf, 0xf4, 0x5d, 0x08, 0x32, 0x22, 0x33,
1807  0x2e, 0x62, 0x46, 0x4d, 0x03, 0x48, 0x1f, 0xea,
1808  0x7c, 0x65, 0x3e, 0x71, 0xf8, 0xea, 0x20, 0x85,
1809  0x29, 0x6f, 0x3c, 0xf2, 0x19, 0xb5, 0x65, 0xb0,
1810  0xce, 0x06, 0xcc, 0x90, 0x86, 0x20, 0x77, 0xf5,
1811  0xa0, 0xbc, 0x45, 0x9d, 0x4e, 0x92, 0xb4, 0x24,
1812  0xc8, 0x58, 0x4a, 0xc3, 0x4e, 0xb8, 0x95, 0x8d,
1813  0x93, 0x0c, 0xce, 0xe0, 0xf9, 0x7d, 0x7e, 0xd3,
1814  0x46, 0x53, 0x32, 0x95, 0x7d, 0x22, 0x76, 0x0e,
1815  0x95, 0x23, 0x2e, 0xa6, 0x58, 0x1a, 0xb6, 0x74,
1816  0x54, 0x4f, 0x37, 0x5c, 0x60, 0x00, 0xb4, 0x55,
1817  0x5b, 0xda, 0xea, 0x2c, 0xf3, 0x9b, 0x91, 0x6f,
1818  0xa8, 0x20, 0xd3, 0x40, 0x0c, 0x7c, 0xc7, 0x85,
1819  0x8c, 0x44, 0x76, 0xbc, 0x22, 0x9d, 0xfd, 0x8e,
1820  0x21, 0x46, 0x05, 0x41, 0x73, 0x0c, 0x88, 0x62,
1821  0xdc, 0x62, 0xc1, 0xc8, 0x14, 0xbb, 0x96, 0x60,
1822  0x77, 0x6c, 0x5c, 0x31, 0x2a, 0xaa, 0x87, 0x69,
1823  0x99, 0xaa, 0x83, 0x5e, 0x71, 0x11, 0x2a, 0x85,
1824  0xca, 0x5d, 0xe1, 0x67, 0x4f, 0xa2, 0x3e, 0x4e,
1825  0x94, 0xe7, 0xa3, 0xe6, 0xa0, 0xdb, 0xc2, 0x05,
1826  0x01, 0x4f, 0xf5, 0xe9, 0xfc, 0xa2, 0x2a, 0x1c,
1827  0x63, 0x21, 0xd5, 0x27, 0x98, 0x86, 0x9c, 0x66,
1828  0x5e, 0xf1, 0x97, 0xb0, 0x86, 0x58, 0x5b, 0x94,
1829  0x51, 0xfd, 0xb9, 0x83, 0x4c, 0xc4, 0x0f, 0x5f,
1830  0xdd, 0xc8, 0xce, 0x43, 0xed, 0xe8, 0xae, 0xbc,
1831  0x52, 0x73, 0xf6, 0x0f, 0x0d, 0xb4, 0xd6, 0xa7,
1832  0xcf, 0xef, 0x0e, 0x72, 0x34, 0xff, 0x2b, 0x50,
1833  0x71, 0x2a, 0x98, 0xf0, 0x60, 0x58, 0xde, 0x1d,
1834  0x96, 0x50, 0xd8, 0xec, 0xeb, 0x40, 0xcb, 0x4c,
1835  0x3b, 0x2c, 0xee, 0x76, 0xd6, 0x97, 0x1c, 0x69,
1836  0x61, 0x89, 0xc1, 0x9b, 0x03, 0xda, 0x08, 0x0b,
1837  0x15, 0xba, 0xd3, 0x3d, 0x8c, 0xea, 0xf7, 0x17,
1838  0xc3, 0x77, 0xf8, 0x04, 0xca, 0x72, 0xed, 0xfe,
1839  0xd0, 0x02, 0x73, 0x1b, 0x71, 0x72, 0x17, 0x9f,
1840  0x14, 0x96, 0xe2, 0x5f, 0xae, 0x5b, 0x7d, 0x7f,
1841  0xc9, 0x72, 0x9f, 0xd5, 0x32, 0xf4, 0xf3, 0x39,
1842  0x89, 0x36, 0x00, 0x44, 0xa9, 0x18, 0x21, 0x4b,
1843  0x26, 0xf2, 0x5a, 0x2a, 0x80, 0xea, 0x6b, 0x3e,
1844  0x68, 0x27, 0xd0, 0xa0, 0x84, 0x81, 0xb5, 0xa6,
1845  0x3b, 0xd5, 0xdc, 0xdd, 0xd1, 0xd4, 0x5b, 0xad,
1846  0x80, 0x91, 0xf2, 0x30, 0x5e, 0x90, 0x17, 0x35,
1847  0x59, 0xad, 0x34, 0x65, 0x54, 0x04, 0x5a, 0x3c,
1848  0xe4, 0x68, 0xa7, 0x30, 0x06, 0x7a, 0x85, 0xe7,
1849  0xf4, 0x20, 0xe3, 0xd7, 0xa5, 0x8b, 0x60, 0xfe,
1850  0x51, 0xad, 0xda, 0xe2, 0xd1, 0x4f, 0xfb, 0x94,
1851  0xc9, 0xba, 0xa4, 0x09, 0x5c, 0xde, 0x78, 0xdc,
1852  0x78, 0x36, 0x96, 0x8b, 0xd6, 0x72, 0xc4, 0xa7,
1853  0x1c, 0xde, 0x45, 0x85, 0xdf, 0x84, 0xb1, 0x3f,
1854  0x2b, 0x3f, 0xfe, 0x56, 0x80, 0x8d, 0x26, 0x4a,
1855  0x39, 0x22, 0x1f, 0x10, 0x89, 0x2e, 0x4e, 0x87,
1856  0xf5, 0x9c, 0x0e, 0xd9, 0xdd, 0xb2, 0xc9, 0x9c,
1857  0x3f, 0xc5, 0xe3, 0xab, 0xdc, 0x85, 0x1c, 0xf9,
1858  0xda, 0xbb, 0x36, 0x9b, 0xe7, 0x21, 0x58, 0x44,
1859  0xee, 0xb3, 0xe7, 0x37, 0xd3, 0xc3, 0x76, 0x09,
1860  0x79, 0xe2, 0xf4, 0xf1, 0x27, 0x6b, 0x74, 0xc4,
1861  0x5f, 0x06, 0x76, 0x78, 0x56, 0xb9, 0x80, 0x7f,
1862  0x63, 0x53, 0xa2, 0xd1, 0xfc, 0xfb, 0x69, 0x38,
1863  0x0c, 0x13, 0x6e, 0x9e, 0xea, 0x79, 0xc9, 0x6d,
1864  0x45, 0x6b, 0xa3, 0xa8, 0x20, 0x21, 0x24, 0xff,
1865  0x0d, 0x8d, 0xd9, 0x0a, 0x9e, 0xf4, 0x3f, 0xf5,
1866  0x18, 0x39, 0xdd, 0x9f, 0xed, 0xd6, 0x2b, 0xb1,
1867  0x4b, 0x3f, 0x24, 0x7e, 0x11, 0x79, 0x37, 0x01,
1868  0x10, 0xe7, 0x34, 0x1d, 0x36, 0x5f, 0x26, 0x99,
1869  0x5a, 0x4d, 0xe9, 0x1a, 0x89, 0x24, 0xf8, 0xea,
1870  0xca, 0x16, 0x19, 0x6c, 0x3b, 0x8e, 0x44, 0x70,
1871  0x20, 0x5f, 0x46, 0x3c, 0x60, 0xbe, 0x03, 0xfc,
1872  0x99, 0x29, 0xd7, 0x30, 0x5e, 0xbe, 0x5b, 0x17,
1873  0x4f, 0xfe, 0x3f, 0xe0, 0x50, 0xa0, 0x1b, 0x1a,
1874  0x6b, 0x17, 0xf3, 0xf9, 0x01, 0xe8, 0xc6, 0xc8,
1875  0x0f, 0x81, 0xbd, 0x2d, 0xc5, 0x8c, 0xa1, 0xab,
1876  0x9d, 0x13, 0xce, 0x73, 0x14, 0x56, 0x56, 0xb4,
1877  0x68, 0xac, 0x35, 0xf8, 0x6a, 0x55, 0x3e, 0x50,
1878  0x34, 0x5a, 0x66, 0x17, 0x98, 0x4d, 0xd1, 0xa7,
1879  0xdf, 0x57, 0xd6, 0xd4, 0x44, 0x64, 0xa7, 0x74,
1880  0x18, 0x0a, 0x4f, 0xa9, 0xe4, 0xb4, 0x0f, 0x89,
1881  0xa2, 0xc5, 0xb8, 0xa7, 0x20, 0xa2, 0xb1, 0xf8,
1882  0x70, 0xaf, 0xee, 0x6e, 0x62, 0xa5, 0x89, 0x5d,
1883  0xc9, 0x8a, 0xb9, 0x87, 0xac, 0x4d, 0x4d, 0x81,
1884  0x1c, 0x62, 0xd3, 0xbf, 0x83, 0x79, 0x98, 0x81,
1885  0xbd, 0xcc, 0x1f, 0x76, 0xc8, 0x7e, 0x2c, 0xec,
1886  0xdb, 0xa7, 0xa5, 0xea, 0x05, 0x94, 0x3f, 0xef,
1887  0x66, 0x1c, 0x5d, 0xc4, 0xbd, 0x73, 0x53, 0x1f,
1888  0xf3, 0xac, 0x1f, 0xa4, 0xb9, 0x78, 0x1b, 0x93,
1889  0xcb, 0x17, 0xb6, 0xda, 0xbb, 0x45, 0x21, 0xfa,
1890  0x52, 0xc7, 0x71, 0x05, 0xb3, 0xeb, 0x82, 0x09,
1891  0x99, 0x90, 0x5d, 0xa9, 0x76, 0xd1, 0x63, 0x6a,
1892  0x14, 0x99, 0xe9, 0xa5, 0x98, 0x5d, 0xe0, 0xb5,
1893  0x2a, 0xd1, 0xf1, 0x2e, 0xe7, 0x85, 0xdb, 0x42,
1894  0xfc, 0x61, 0x09, 0x14, 0xe5, 0x8e, 0x92, 0x70,
1895  0x91, 0x15, 0x74, 0x2c, 0x16, 0x30, 0xc4, 0xb0,
1896  0xf1, 0x61, 0xd5, 0x55, 0xa8, 0xa3, 0xca, 0x88,
1897  0xe6, 0xb1, 0x58, 0x76, 0xa5, 0x4c, 0x48, 0xe3,
1898  0xdd, 0x7a, 0x5e, 0x0a, 0x86, 0xfd, 0xd6, 0xe8,
1899  0xc0, 0x47, 0x27, 0x1a, 0x58, 0x92, 0xad, 0xa6,
1900  0x51, 0x32, 0x4d, 0x0d, 0x29, 0xd3, 0xcf, 0xf1,
1901  0xcc, 0x29, 0x1a, 0xfe, 0xf6, 0xa0, 0xf3, 0xdd,
1902  0x98, 0x73, 0xcb, 0xbb, 0x8a, 0xe9, 0x55, 0xba,
1903  0x89, 0x2d, 0x31, 0x9b, 0x3d, 0x04, 0x1f, 0xb5,
1904  0x1c, 0x84, 0x63, 0xca, 0xde, 0x75, 0xac, 0x91,
1905  0x78, 0x1f, 0x8b, 0x37, 0x8d, 0x46, 0xaa, 0x79,
1906  0x51, 0xbf, 0x30, 0xfa, 0x3d, 0x9b, 0xd9, 0x20,
1907  0x25, 0x18, 0x46, 0xb6, 0xe7, 0x8e, 0xf7, 0x5e,
1908  0x7d, 0xf8, 0xd3, 0x01, 0x39, 0xe5, 0x9d, 0x46,
1909  0x6b, 0x8c, 0xcf, 0x9d, 0xc6, 0xb9, 0xe8, 0xd8,
1910  0x25, 0x2d, 0x96, 0x07, 0xc7, 0x4e, 0xa3, 0x3a,
1911  0x9a, 0xbc, 0x9d, 0x80, 0xa6, 0x5d, 0xb1, 0xc0,
1912  0x3e, 0x81, 0xe0, 0x52, 0x8f, 0x9a, 0x1a, 0xc2,
1913  0xdb, 0x9f, 0x91, 0x85, 0x56, 0xdb, 0xb8, 0x69,
1914  0x10, 0x35, 0xe4, 0xc4, 0xaf, 0xb6, 0x13, 0xf8,
1915  0x86, 0xe1, 0x2d, 0x3c, 0xf8, 0x94, 0x60, 0xb7,
1916  0xa1, 0xde, 0x25, 0x51, 0x7d, 0xff, 0xff, 0xa6,
1917  0x23, 0x68, 0x28, 0x1f, 0x79, 0x33, 0x60, 0x86,
1918  0xe9, 0x2c, 0x3a, 0xb9, 0x3c, 0x70, 0xb3, 0xe0,
1919  0x4c, 0x8c, 0x7e, 0x06, 0xdf, 0x4d, 0xf6, 0x88,
1920  0xda, 0x9e, 0x4f, 0x5b, 0xd2, 0x2e, 0x28, 0xb8,
1921  0xe0, 0x27, 0x7a, 0x43, 0xfb, 0x23, 0x4b, 0x8a,
1922  0xd9, 0x4f, 0x29, 0x53, 0x5d, 0x75, 0xc6, 0xfc };
1923  uint8_t smbbuf2[] = {
1924  0x0a, 0x30, 0xe0, 0x74, 0x3c, 0x23, 0xc3, 0x11,
1925  0x95, 0x25, 0x04, 0xe4, 0x2d, 0x7b, 0x29, 0xa1,
1926  0x75, 0x69, 0x3f, 0x49, 0x9c, 0xfa, 0x66, 0x78,
1927  0x3c, 0xf1, 0xab, 0xee, 0xab, 0x9a, 0x75, 0x63,
1928  0x54, 0x80, 0x2b, 0x5c, 0x07, 0xf7, 0xec, 0x72,
1929  0xfb, 0xd0, 0x52, 0x5e, 0x7e, 0x99, 0xf5, 0x3b,
1930  0xc4, 0x77, 0x96, 0x12, 0xb8, 0x36, 0xb2, 0xcf,
1931  0xab, 0xf5, 0xd3, 0xf3, 0x19, 0x77, 0xbb, 0x03,
1932  0xdb, 0xf7, 0x4d, 0x81, 0xe3, 0xe8, 0x6c, 0x23,
1933  0x02, 0xe0, 0xcf, 0x24, 0xc1, 0xd5, 0x3d, 0x42,
1934  0xa4, 0xbc, 0x97, 0xf4, 0x83, 0xee, 0xff, 0x85,
1935  0x2c, 0xfd, 0xdd, 0xdc, 0x23, 0x1c, 0x87, 0x0c,
1936  0xe4, 0xd5, 0xfc, 0xc3, 0x8b, 0x10, 0xa5, 0x42,
1937  0x0f, 0x14, 0xd1, 0x89, 0xa6, 0xaf, 0xaa, 0x77,
1938  0xfc, 0x3b, 0xce, 0x6c, 0xbe, 0x62, 0xc9, 0xdd,
1939  0x16, 0xc6, 0x14, 0xc2, 0xa6, 0x13, 0x12, 0xfa,
1940  0x5a, 0x8b, 0x05, 0x88, 0x06, 0xf9, 0xef, 0x9c,
1941  0xce, 0xf7, 0x27, 0x46, 0x1d, 0x50, 0xe2, 0xeb,
1942  0x49, 0xb2, 0xb1, 0x7c, 0x6b, 0xaf, 0xe9, 0xc7,
1943  0xdd, 0x59, 0x8c, 0xda, 0x32, 0x55, 0xb5, 0xfe,
1944  0xdc, 0xe0, 0x47, 0xf4, 0xa0, 0xe7, 0xaa, 0x47,
1945  0x49, 0xdf, 0xcf, 0x9c, 0xd6, 0xfa, 0xd2, 0xca,
1946  0x55, 0xa7, 0x3f, 0x62, 0x14, 0x6c, 0xc8, 0x7f,
1947  0xad, 0x7c, 0xb1, 0x70, 0x88, 0xb3, 0x51, 0x13,
1948  0x2c, 0x3b, 0x78, 0x1d, 0xa2, 0x5e, 0xf7, 0x83,
1949  0x62, 0x6a, 0x51, 0xbd, 0xe9, 0x77, 0x62, 0xc6,
1950  0x06, 0x06, 0x51, 0x9d, 0x03, 0x95, 0x51, 0x7c,
1951  0xd3, 0x73, 0x50, 0x9b, 0x36, 0x5a, 0x28, 0x52,
1952  0xc0, 0x05, 0xee, 0xd5, 0x2d, 0xd5, 0x77, 0x52,
1953  0xab, 0x7c, 0x4a, 0x4c, 0x7e, 0xf6, 0xba, 0x52,
1954  0xc5, 0x4d, 0xb5, 0x74, 0x83, 0x77, 0x5f, 0xaa,
1955  0xba, 0x86, 0x94, 0xd2, 0x19, 0xca, 0xef, 0xc9,
1956  0x6e, 0x5b, 0x50, 0xee, 0x2c, 0xdd, 0x67, 0xc8,
1957  0xfd, 0xc3, 0xa4, 0x80, 0x63, 0x1d, 0xa2, 0x07,
1958  0x1e, 0x1a, 0x9d, 0x70, 0xe4, 0xab, 0x34, 0x7a,
1959  0xfb, 0x08, 0x82, 0x85, 0xec, 0x2d, 0x25, 0x3e,
1960  0x70, 0x22, 0x6e, 0x9d, 0x0f, 0xed, 0x60, 0x8f,
1961  0xc5, 0x06, 0x66, 0x42, 0x95, 0xcc, 0x77, 0xbe,
1962  0x4d, 0x19, 0x7c, 0xd1, 0x31, 0x26, 0xfb, 0x52,
1963  0xad, 0xbd, 0x19, 0x1d, 0x68, 0x56, 0x2c, 0xb9,
1964  0x5b, 0xaa, 0x92, 0x48, 0xcf, 0xdf, 0x65, 0x2d,
1965  0xdb, 0x87, 0x06, 0xbe, 0x51, 0x61, 0x6b, 0xf6,
1966  0x87, 0xdc, 0xbb, 0xa5, 0x48, 0x81, 0xaf, 0xd7,
1967  0xfc, 0x15, 0xf7, 0x41, 0xde, 0xe3, 0xe9, 0xd4,
1968  0xad, 0x5d, 0x64, 0x8f, 0x13, 0x68, 0xe5, 0x2b,
1969  0x4d, 0x87, 0x59, 0x7e, 0xcb, 0x2b, 0xbf, 0xbc,
1970  0xaa, 0xd2, 0xc7, 0x60, 0xef, 0xe1, 0x25, 0xe2,
1971  0x89, 0xb4, 0x78, 0x24, 0x52, 0xb4, 0x54, 0xe3,
1972  0xf0, 0xe5, 0x81, 0xba, 0xe3, 0x00, 0x62, 0x09,
1973  0x8a, 0x19, 0x7b, 0x9b, 0x0f, 0x50, 0x91, 0xa7,
1974  0x80, 0xdb, 0x0e, 0x68, 0xe1, 0x22, 0x54, 0x89,
1975  0x07, 0xc7, 0x39, 0x38, 0xca, 0xae, 0xbf, 0x5b,
1976  0xbb, 0xe4, 0x70, 0x28, 0xc5, 0x18, 0x98, 0xea };
1977  uint8_t smbbuf3[] = {
1978  0x39, 0x99, 0x97, 0x1f, 0xf1, 0x6a, 0x72, 0x0d,
1979  0x35, 0xd5, 0x33, 0x42, 0x5a, 0x9f, 0xea, 0x0f,
1980  0x6f, 0x3b, 0xc7, 0xb9, 0xd3, 0x04, 0xdf, 0x44,
1981  0x45, 0xc7, 0xc6, 0x06, 0x0b, 0x77, 0x8e, 0x8e,
1982  0x9a, 0x3c, 0xa4, 0x15, 0x85, 0x80, 0xce, 0xd0,
1983  0x8c, 0x54, 0x60, 0xf9, 0x1f, 0xb3, 0x3e, 0xed,
1984  0x21, 0x3e, 0xfa, 0x30, 0xf4, 0x50, 0x2b, 0x00,
1985  0x00, 0xea, 0xd1, 0xb3, 0xd2, 0x7e, 0x6c, 0x14,
1986  0xe5, 0xf0, 0xf4, 0x9c, 0xb4, 0x2e, 0x32, 0x41,
1987  0x20, 0x2a, 0x18, 0x78, 0x1a, 0xed, 0x04, 0x94,
1988  0x83, 0xd1, 0x87, 0x39, 0xf6, 0xcb, 0xf4, 0xc1,
1989  0xc7, 0xe0, 0x50, 0x87, 0x65, 0x4f, 0x36, 0x73,
1990  0x70, 0xf5, 0x0a, 0xaa, 0x2b, 0x28, 0xad, 0x05,
1991  0x28, 0x8d, 0x3b, 0x42, 0xfb, 0xe2, 0xd3, 0xb8,
1992  0x82, 0x71, 0x25, 0xcd, 0xa2, 0xf2, 0x4b, 0x62,
1993  0xeb, 0x14, 0x3b, 0x81, 0xaf, 0xd4, 0x68, 0x5a,
1994  0xae, 0x8e, 0x10, 0x9a, 0x17, 0x4c, 0xf1, 0x3d,
1995  0x43, 0xb9, 0xd2, 0xd5, 0x86, 0xee, 0x3a, 0xf3,
1996  0xe5, 0x41, 0xe5, 0x52, 0xda, 0x61, 0xf3, 0x20,
1997  0x30, 0x5b, 0xe5, 0x1f, 0xe2, 0x4e, 0x9d, 0xd6,
1998  0xd6, 0x2e, 0x2a, 0x63, 0xbc, 0xf6, 0xb9, 0xc2,
1999  0xec, 0xd0, 0xe9, 0xfd, 0x07, 0xfb, 0x2d, 0x8e,
2000  0xbc, 0x43, 0xcb, 0x7e, 0x55, 0x63, 0x9f, 0xb6,
2001  0xf8, 0x8b, 0x4c, 0xcd, 0x4b, 0x28, 0x47, 0x56,
2002  0xc9, 0xd2, 0xfe, 0x0e, 0x63, 0x11, 0x09, 0xd9,
2003  0xd9, 0x97, 0x0a, 0x5a, 0x21, 0xad, 0xdb, 0x53,
2004  0x24, 0xee, 0x62, 0x4a, 0xaa, 0x49, 0x14, 0xdf,
2005  0xc0, 0x61, 0x85, 0x11, 0x57, 0x6e, 0x3b, 0x8c,
2006  0x37, 0x24, 0x13, 0xde, 0xc7, 0xf3, 0x44, 0x54,
2007  0x8a, 0x69, 0x78, 0x0c, 0xf3, 0xd1, 0xcd, 0xc5,
2008  0xad, 0x45, 0xc6, 0x06, 0x56, 0x0b, 0x53, 0x40,
2009  0x79, 0x12, 0x90, 0x6b, 0xdf, 0xc5, 0x80, 0xde,
2010  0x9c, 0x8e, 0xe1, 0x73, 0xdc, 0x92, 0xc2, 0xf1,
2011  0xeb, 0xd9, 0x66, 0x0a, 0x12, 0xd2, 0x3f, 0x04,
2012  0x03, 0xaa, 0x6f, 0xd0, 0x90, 0xfa, 0xb0, 0x6b,
2013  0x7d, 0xfc, 0x76, 0xf9, 0xe3, 0xa2, 0x17, 0x28,
2014  0x4e, 0x9d, 0x2d, 0xa6, 0x7e, 0xfa, 0x19, 0x91,
2015  0xeb, 0xe5, 0xe4, 0xca, 0x09, 0x77, 0xfe, 0xc0,
2016  0x1c, 0xaa, 0xc4, 0x7c, 0xc2, 0x6a, 0x0e, 0xf3,
2017  0x4e, 0x79, 0x9b, 0x82, 0x2a, 0x4b, 0xd3, 0x35,
2018  0x1d, 0x92, 0x6c, 0x3f, 0x85, 0x57, 0x5a, 0x16,
2019  0xa1, 0x0d, 0xc7, 0x64, 0xb8, 0x46, 0x73, 0xbf,
2020  0x91, 0x5f, 0x10, 0x2a, 0x2b, 0x51, 0x49, 0xe1,
2021  0xea, 0xda, 0x2f, 0x41, 0x7b, 0x96, 0xa3, 0xd2,
2022  0x7b, 0x72, 0xc0, 0x88, 0x84, 0xcb, 0xe0, 0xb7,
2023  0xae, 0x74, 0xc9, 0x78, 0x82, 0x47, 0xf3, 0x19,
2024  0x21, 0x53, 0xe6, 0xe1, 0x67, 0xbb, 0x39, 0x05,
2025  0x6e, 0x1c, 0x38, 0x33, 0x10, 0x60, 0x24, 0x48,
2026  0xb2, 0x7a, 0xb9, 0x4e, 0x8d, 0x36, 0xcf, 0xce,
2027  0xf6, 0x31, 0x3b, 0xa3, 0x18, 0x78, 0x49, 0x91,
2028  0xef, 0xed, 0x86, 0x2c, 0x98, 0x00, 0x18, 0x49,
2029  0x73, 0xb8, 0xe5, 0x2f, 0xc1, 0x58, 0xe0, 0x47,
2030  0x2b, 0x16, 0x41, 0xc3, 0x41, 0x05, 0x00, 0x0b,
2031  0x03, 0x10, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00,
2032  0x00, 0x00, 0x00 };
2033 
2034  uint32_t smblen1 = sizeof(smbbuf1);
2035  uint32_t smblen2 = sizeof(smbbuf2);
2036  uint32_t smblen3 = sizeof(smbbuf3);
2037  TcpSession ssn;
2039  int r = 0;
2040  memset(&f, 0, sizeof(f));
2041  memset(&ssn, 0, sizeof(ssn));
2042  FLOW_INITIALIZE(&f);
2043  f.protoctx = (void *)&ssn;
2044  f.proto = IPPROTO_TCP;
2045  f.alproto = ALPROTO_SMB;
2046 
2048 
2049  FLOWLOCK_WRLOCK(&f);
2050  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SMB,
2051  STREAM_TOSERVER | STREAM_START, smbbuf1, smblen1);
2052  if (r != 0) {
2053  printf("smb header check returned %" PRId32 ", expected 0: ", r);
2054  FLOWLOCK_UNLOCK(&f);
2055  goto end;
2056  }
2057  FLOWLOCK_UNLOCK(&f);
2058 
2059  SMBState *smb_state = f.alstate;
2060  if (smb_state == NULL) {
2061  printf("no smb state: ");
2062  goto end;
2063  }
2064 
2065  if (smb_state->smb.command != SMB_COM_WRITE_ANDX) {
2066  printf("expected SMB command 0x%02x , got 0x%02x : ", SMB_COM_WRITE_ANDX, smb_state->smb.command);
2067  goto end;
2068  }
2069 
2070  FLOWLOCK_WRLOCK(&f);
2071  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SMB, STREAM_TOSERVER,
2072  smbbuf2, smblen2);
2073  if (r != 0) {
2074  printf("smb header check returned %" PRId32 ", expected 0: ", r);
2075  FLOWLOCK_UNLOCK(&f);
2076  goto end;
2077  }
2078  FLOWLOCK_UNLOCK(&f);
2079  FLOWLOCK_WRLOCK(&f);
2080  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SMB, STREAM_TOSERVER,
2081  smbbuf3, smblen3);
2082  if (r != 0) {
2083  printf("smb header check returned %" PRId32 ", expected 0: ", r);
2084  FLOWLOCK_UNLOCK(&f);
2085  goto end;
2086  }
2087  FLOWLOCK_UNLOCK(&f);
2088  printUUID("BIND", smb_state->ds.dcerpc.dcerpcbindbindack.uuid_entry);
2089  result = 1;
2090 end:
2091  if (alp_tctx != NULL)
2092  AppLayerParserThreadCtxFree(alp_tctx);
2094  FLOW_DESTROY(&f);
2095  return result;
2096 }
2097 
2098 static int SMBParserTest04(void)
2099 {
2100  int result = 0;
2101  Flow f;
2102  uint8_t smbbuf1[] = {
2103  0x00, 0x00, 0x00, 0x88, 0xff, 0x53, 0x4d, 0x42,
2104  0x2f, 0x00, 0x00, 0x00, 0x00, 0x18, 0x07, 0xc8,
2105  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2106  0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x7c, 0x05,
2107  0x00, 0x08, 0x00, 0x00, 0x0e, 0xff, 0x00, 0x00,
2108  0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0xff,
2109  0x00, 0x00, 0x00, 0x08, 0x00, 0x48, 0x00, 0x00,
2110  0x00, 0x48, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
2111  0x00, 0x49, 0x00, 0xab, 0x05, 0x00, 0x0b, 0x03,
2112  0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
2113  0x01, 0x00, 0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16,
2114  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2115  0x00, 0x00, 0x01, 0x00, 0x78, 0x56, 0x34, 0x12,
2116  0x34, 0x12, 0xcd, 0xab, 0xef, 0x00, 0x01, 0x23,
2117  0x45, 0x67, 0x89, 0xab, 0x01, 0x00, 0x00, 0x00,
2118  0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
2119  0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
2120  0x02, 0x00, 0x00, 0x00 };
2121  uint8_t smbbuf2[] = {
2122  0x00, 0x00, 0x00, 0x2f, 0xff, 0x53, 0x4d, 0x42,
2123  0x2f, 0x00, 0x00, 0x00, 0x00, 0x98, 0x07, 0xc8,
2124  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2125  0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x7c, 0x05,
2126  0x00, 0x08, 0x00, 0x00, 0x06, 0xff, 0x00, 0x2f,
2127  0x00, 0x48, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00,
2128  0x00, 0x00, 0x00 };
2129  uint8_t smbbuf3[] = {
2130  0x00, 0x00, 0x00, 0x3b, 0xff, 0x53, 0x4d, 0x42,
2131  0x2e, 0x00, 0x00, 0x00, 0x00, 0x18, 0x03, 0xc8,
2132  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2133  0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x7c, 0x05,
2134  0x00, 0x08, 0x00, 0x00, 0x0c, 0xff, 0x00, 0xde,
2135  0xde, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
2136  0x04, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, 0x00,
2137  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
2138  uint8_t smbbuf4[] = {
2139  0x00, 0x00, 0x00, 0x80, 0xff, 0x53, 0x4d, 0x42,
2140  0x2e, 0x00, 0x00, 0x00, 0x00, 0x98, 0x03, 0xc8,
2141  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2142  0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x7c, 0x05,
2143  0x00, 0x08, 0x00, 0x00, 0x0c, 0xff, 0x00, 0x00,
2144  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
2145  0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2146  0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00,
2147  0x05, 0x00, 0x0c, 0x03, 0x10, 0x00, 0x00, 0x00,
2148  0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2149  0xb8, 0x10, 0xb8, 0x10, 0x5d, 0xe0, 0x00, 0x00,
2150  0x0e, 0x00, 0x5c, 0x70, 0x69, 0x70, 0x65, 0x5c,
2151  0x73, 0x70, 0x6f, 0x6f, 0x6c, 0x73, 0x73, 0x00,
2152  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2153  0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
2154  0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
2155  0x02, 0x00, 0x00, 0x00 };
2156  uint32_t smblen1 = sizeof(smbbuf1);
2157  uint32_t smblen2 = sizeof(smbbuf2);
2158  uint32_t smblen3 = sizeof(smbbuf3);
2159  uint32_t smblen4 = sizeof(smbbuf4);
2160  TcpSession ssn;
2162  int r = 0;
2163  memset(&f, 0, sizeof(f));
2164  memset(&ssn, 0, sizeof(ssn));
2165  FLOW_INITIALIZE(&f);
2166  f.protoctx = (void *)&ssn;
2167  f.proto = IPPROTO_TCP;
2168  f.alproto = ALPROTO_SMB;
2169 
2171 
2172  FLOWLOCK_WRLOCK(&f);
2173  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SMB,
2174  STREAM_TOSERVER | STREAM_START, smbbuf1, smblen1);
2175  if (r != 0) {
2176  printf("smb header check returned %" PRId32 ", expected 0: ", r);
2177  FLOWLOCK_UNLOCK(&f);
2178  goto end;
2179  }
2180  FLOWLOCK_UNLOCK(&f);
2181 
2182  SMBState *smb_state = f.alstate;
2183  if (smb_state == NULL) {
2184  printf("no smb state: ");
2185  goto end;
2186  }
2187 
2188  if (smb_state->smb.command != SMB_COM_WRITE_ANDX) {
2189  printf("expected SMB command 0x%02x , got 0x%02x : ", SMB_COM_WRITE_ANDX, smb_state->smb.command);
2190  goto end;
2191  }
2192 
2193  FLOWLOCK_WRLOCK(&f);
2194  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SMB, STREAM_TOSERVER,
2195  smbbuf2, smblen2);
2196  if (r != 0) {
2197  printf("smb header check returned %" PRId32 ", expected 0: ", r);
2198  FLOWLOCK_UNLOCK(&f);
2199  goto end;
2200  }
2201  FLOWLOCK_UNLOCK(&f);
2202  FLOWLOCK_WRLOCK(&f);
2203  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SMB, STREAM_TOSERVER,
2204  smbbuf3, smblen3);
2205  if (r != 0) {
2206  printf("smb header check returned %" PRId32 ", expected 0: ", r);
2207  FLOWLOCK_UNLOCK(&f);
2208  goto end;
2209  }
2210  FLOWLOCK_UNLOCK(&f);
2211  FLOWLOCK_WRLOCK(&f);
2212  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SMB, STREAM_TOSERVER,
2213  smbbuf4, smblen4);
2214  if (r != 0) {
2215  printf("smb header check returned %" PRId32 ", expected 0: ", r);
2216  FLOWLOCK_UNLOCK(&f);
2217  goto end;
2218  }
2219  FLOWLOCK_UNLOCK(&f);
2220 
2221  result = 1;
2222 end:
2223  if (alp_tctx != NULL)
2224  AppLayerParserThreadCtxFree(alp_tctx);
2226  FLOW_DESTROY(&f);
2227  return result;
2228 }
2229 
2230 static int SMBParserTest05(void)
2231 {
2234 
2235  uint8_t smbbuf1[] = {
2236  /* session request */
2237  0x81, 0x00, 0x00, 0x44, 0x20, 0x43, 0x4b, 0x46,
2238  0x44, 0x45, 0x4e, 0x45, 0x43, 0x46, 0x44, 0x45,
2239  0x46, 0x46, 0x43, 0x46, 0x47, 0x45, 0x46, 0x46,
2240  0x43, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43,
2241  0x41, 0x43, 0x41, 0x43, 0x41, 0x00, 0x20, 0x43,
2242  0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43,
2243  0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43,
2244  0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43,
2245  0x41, 0x43, 0x41, 0x43, 0x41, 0x41, 0x41, 0x00
2246  };
2247  uint32_t smblen1 = sizeof(smbbuf1);
2248  uint8_t smbbuf2[] = {
2249  /* session request */
2250  0x81, 0x00, 0x00, 0x44, 0x20, 0x43, 0x4b, 0x46,
2251  0x44, 0x45, 0x4e, 0x45, 0x43, 0x46, 0x44, 0x45,
2252  0x46, 0x46, 0x43, 0x46, 0x47, 0x45, 0x46, 0x46,
2253  0x43, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43,
2254  0x41, 0x43, 0x41, 0x43, 0x41, 0x00, 0x20, 0x43,
2255  0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43,
2256  0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43,
2257  0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43,
2258  0x41, 0x43, 0x41, 0x43, 0x41, 0x41, 0x41, 0x00,
2259  /* session message */
2260  0x00, 0x00, 0x00, 0x60, 0xff, 0x53, 0x4d, 0x42,
2261  0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01, 0x20,
2262  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2263  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x2d,
2264  0x00, 0x00, 0xdd, 0xca, 0x00, 0x3d, 0x00, 0x02,
2265  0x4d, 0x45, 0x54, 0x41, 0x53, 0x50, 0x4c, 0x4f,
2266  0x49, 0x54, 0x00, 0x02, 0x4c, 0x41, 0x4e, 0x4d,
2267  0x41, 0x4e, 0x31, 0x2e, 0x30, 0x00, 0x02, 0x4c,
2268  0x4d, 0x31, 0x2e, 0x32, 0x58, 0x30, 0x30, 0x32,
2269  0x00, 0x02, 0x4e, 0x54, 0x20, 0x4c, 0x41, 0x4e,
2270  0x4d, 0x41, 0x4e, 0x20, 0x31, 0x2e, 0x30, 0x00,
2271  0x02, 0x4e, 0x54, 0x20, 0x4c, 0x4d, 0x20, 0x30,
2272  0x2e, 0x31, 0x32, 0x00
2273  };
2274  uint32_t smblen2 = sizeof(smbbuf2);
2275 
2276  int result = 0;
2277  AppProto alproto;
2278  Flow f;
2279  AppLayerProtoDetectThreadCtx *alpd_tctx;
2280  memset(&f, 0, sizeof(f));
2281  f.dp = 139;
2282 
2283  /** SMB */
2284  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB, "|ff|SMB", 8, 4, STREAM_TOCLIENT);
2285  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB, "|ff|SMB", 8, 4, STREAM_TOSERVER);
2286 
2287  /** SMB2 */
2290 
2291  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2292  "139",
2293  ALPROTO_SMB,
2296  SMBProbingParser, NULL);
2297 
2299  alpd_tctx = AppLayerProtoDetectGetCtxThread();
2300 
2301  alproto = AppLayerProtoDetectGetProto(alpd_tctx,
2302  &f,
2303  smbbuf1, smblen1,
2304  IPPROTO_TCP, STREAM_TOSERVER);
2305  if (alproto != ALPROTO_UNKNOWN) {
2306  printf("alproto is %"PRIu16 ". Should be ALPROTO_UNKNOWN\n",
2307  alproto);
2308  goto end;
2309  }
2310 
2311  alproto = AppLayerProtoDetectGetProto(alpd_tctx,
2312  &f,
2313  smbbuf2, smblen2,
2314  IPPROTO_TCP, STREAM_TOSERVER);
2315  if (alproto != ALPROTO_SMB) {
2316  printf("alproto is %"PRIu16 ". Should be ALPROTO_SMB\n",
2317  alproto);
2318  goto end;
2319  }
2320 
2321  result = 1;
2322  end:
2325  if (alpd_tctx != NULL)
2327  FLOW_DESTROY(&f);
2328  return result;
2329 }
2330 
2331 static int SMBParserTest06(void)
2332 {
2335 
2336  uint8_t smbbuf1[] = {
2337  /* session request */
2338  0x83, 0x00, 0x00, 0x01, 0x82
2339  };
2340  uint32_t smblen1 = sizeof(smbbuf1);
2341  uint8_t smbbuf2[] = {
2342  /* session request */
2343  0x83, 0x00, 0x00, 0x01, 0x82,
2344  /* session message */
2345  0x00, 0x00, 0x00, 0x55, 0xff, 0x53, 0x4d, 0x42,
2346  0x72, 0x00, 0x00, 0x00, 0x00, 0x98, 0x53, 0xc8,
2347  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2348  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
2349  0x00, 0x00, 0x00, 0x00, 0x11, 0x05, 0x00, 0x03,
2350  0x0a, 0x00, 0x01, 0x00, 0x04, 0x11, 0x00, 0x00,
2351  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
2352  0xfd, 0xe3, 0x00, 0x80, 0xb8, 0xcb, 0x22, 0x5f,
2353  0xfd, 0xeb, 0xc3, 0x01, 0x68, 0x01, 0x00, 0x10,
2354  0x00, 0x50, 0xb5, 0xc3, 0x62, 0x59, 0x02, 0xd1,
2355  0x4d, 0x99, 0x6d, 0x85, 0x7d, 0xfa, 0x93, 0x2d,
2356  0xbb
2357  };
2358  uint32_t smblen2 = sizeof(smbbuf2);
2359 
2360  int result = 0;
2361  AppProto alproto;
2362  Flow f;
2363  AppLayerProtoDetectThreadCtx *alpd_tctx;
2364  memset(&f, 0, sizeof(f));
2365  f.dp = 139;
2366 
2367  /** SMB */
2368  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB, "|ff|SMB", 8, 4, STREAM_TOCLIENT);
2369  AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_SMB, "|ff|SMB", 8, 4, STREAM_TOSERVER);
2370 
2371  /** SMB2 */
2374 
2375  AppLayerProtoDetectPPRegister(IPPROTO_TCP,
2376  "139",
2377  ALPROTO_SMB,
2380  SMBProbingParser, NULL);
2381 
2383  alpd_tctx = AppLayerProtoDetectGetCtxThread();
2384 
2385  alproto = AppLayerProtoDetectGetProto(alpd_tctx,
2386  &f,
2387  smbbuf1, smblen1,
2388  IPPROTO_TCP, STREAM_TOSERVER);
2389  if (alproto != ALPROTO_UNKNOWN) {
2390  printf("alproto is %"PRIu16 ". Should be ALPROTO_UNKNOWN\n",
2391  alproto);
2392  goto end;
2393  }
2394 
2395  alproto = AppLayerProtoDetectGetProto(alpd_tctx,
2396  &f,
2397  smbbuf2, smblen2,
2398  IPPROTO_TCP, STREAM_TOSERVER);
2399  if (alproto != ALPROTO_SMB) {
2400  printf("alproto is %"PRIu16 ". Should be ALPROTO_SMB\n",
2401  alproto);
2402  goto end;
2403  }
2404 
2405  result = 1;
2406  end:
2409  if (alpd_tctx != NULL)
2411  FLOW_DESTROY(&f);
2412  return result;
2413 }
2414 
2415 static int SMBParserTest07(void)
2416 {
2417  int result = 0;
2418  Flow f;
2419  uint8_t smbbuf1[] = {
2420  /* negative session response */
2421  0x83, 0x00, 0x00, 0x01, 0x82
2422  };
2423  uint32_t smblen1 = sizeof(smbbuf1);
2424  TcpSession ssn;
2426  int r = 0;
2427  memset(&f, 0, sizeof(f));
2428  memset(&ssn, 0, sizeof(ssn));
2429  FLOW_INITIALIZE(&f);
2430  f.protoctx = (void *)&ssn;
2431  f.proto = IPPROTO_TCP;
2432  f.alproto = ALPROTO_SMB;
2433 
2435 
2436  FLOWLOCK_WRLOCK(&f);
2437  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SMB,
2438  STREAM_TOCLIENT | STREAM_START, smbbuf1, smblen1);
2439  if (r != 0) {
2440  printf("smb header check returned %" PRId32 ", expected 0: ", r);
2441  FLOWLOCK_UNLOCK(&f);
2442  goto end;
2443  }
2444  FLOWLOCK_UNLOCK(&f);
2445 
2446  SMBState *smb_state = f.alstate;
2447  if (smb_state == NULL) {
2448  printf("no smb state: ");
2449  goto end;
2450  }
2451 
2452  if (smb_state->smb.command != 0) {
2453  printf("we shouldn't have any smb state as yet\n");
2454  goto end;
2455  }
2456 
2457  if (smb_state->nbss.length != 1 ||
2458  smb_state->nbss.type != NBSS_NEGATIVE_SESSION_RESPONSE) {
2459  printf("something wrong with nbss parsing\n");
2460  goto end;
2461  }
2462 
2463  if (smb_state->bytesprocessed != 0) {
2464  printf("smb parser bytesprocessed should be 0, but it is not\n");
2465  goto end;
2466  }
2467 
2468  result = 1;
2469 end:
2470  if (alp_tctx != NULL)
2471  AppLayerParserThreadCtxFree(alp_tctx);
2473  FLOW_DESTROY(&f);
2474  return result;
2475 }
2476 
2477 static int SMBParserTest08(void)
2478 {
2479  int result = 0;
2480  Flow f;
2481  uint8_t smbbuf1[] = {
2482  /* positive session response */
2483  0x82, 0x00, 0x00, 0x00
2484  };
2485  uint8_t smbbuf2[] = {
2486  /* negotiate protocol */
2487  0x00, 0x00, 0x00, 0x55, 0xff, 0x53, 0x4d, 0x42,
2488  0x72, 0x00, 0x00, 0x00, 0x00, 0x98, 0x53, 0xc8,
2489  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2490  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
2491  0x00, 0x00, 0x00, 0x00, 0x11, 0x05, 0x00, 0x03,
2492  0x0a, 0x00, 0x01, 0x00, 0x04, 0x11, 0x00, 0x00,
2493  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
2494  0xfd, 0xe3, 0x00, 0x80, 0x40, 0x8a, 0x57, 0x5c,
2495  0xfd, 0xeb, 0xc3, 0x01, 0x68, 0x01, 0x00, 0x10,
2496  0x00, 0x50, 0xb5, 0xc3, 0x62, 0x59, 0x02, 0xd1,
2497  0x4d, 0x99, 0x6d, 0x85, 0x7d, 0xfa, 0x93, 0x2d,
2498  0xbb
2499  };
2500  uint32_t smblen1 = sizeof(smbbuf1);
2501  uint32_t smblen2 = sizeof(smbbuf2);
2502  TcpSession ssn;
2504  int r = 0;
2505  memset(&f, 0, sizeof(f));
2506  memset(&ssn, 0, sizeof(ssn));
2507  FLOW_INITIALIZE(&f);
2508  f.protoctx = (void *)&ssn;
2509  f.proto = IPPROTO_TCP;
2510  f.alproto = ALPROTO_SMB;
2511 
2513 
2514  FLOWLOCK_WRLOCK(&f);
2515  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SMB,
2516  STREAM_TOCLIENT | STREAM_START, smbbuf1, smblen1);
2517  if (r != 0) {
2518  printf("smb header check returned %" PRId32 ", expected 0: ", r);
2519  FLOWLOCK_UNLOCK(&f);
2520  goto end;
2521  }
2522  FLOWLOCK_UNLOCK(&f);
2523 
2524  SMBState *smb_state = f.alstate;
2525  if (smb_state == NULL) {
2526  printf("no smb state: ");
2527  goto end;
2528  }
2529 
2530  if (smb_state->smb.command != 0) {
2531  printf("we shouldn't have any smb state as yet\n");
2532  goto end;
2533  }
2534 
2535  if (smb_state->nbss.length != 0 ||
2536  smb_state->nbss.type != NBSS_POSITIVE_SESSION_RESPONSE) {
2537  printf("something wrong with nbss parsing\n");
2538  goto end;
2539  }
2540 
2541  if (smb_state->bytesprocessed != 0) {
2542  printf("smb parser bytesprocessed should be 0, but it is not\n");
2543  goto end;
2544  }
2545 
2546  FLOWLOCK_WRLOCK(&f);
2547  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SMB, STREAM_TOCLIENT,
2548  smbbuf2, smblen2);
2549  if (r != 0) {
2550  printf("smb header check returned %" PRId32 ", expected 0: ", r);
2551  FLOWLOCK_UNLOCK(&f);
2552  goto end;
2553  }
2554  FLOWLOCK_UNLOCK(&f);
2555 
2556  if (smb_state->smb.command != SMB_COM_NEGOTIATE) {
2557  printf("we should expect SMB command 0x%02x , got 0x%02x : ",
2558  SMB_COM_NEGOTIATE, smb_state->smb.command);
2559  goto end;
2560  }
2561 
2562  if (smb_state->nbss.length != 85 ||
2563  smb_state->nbss.type != NBSS_SESSION_MESSAGE) {
2564  printf("something wrong with nbss parsing\n");
2565  goto end;
2566  }
2567 
2568  if (smb_state->bytesprocessed != 0) {
2569  printf("smb parser bytesprocessed should be 0, but it is not\n");
2570  goto end;
2571  }
2572 
2573  result = 1;
2574 end:
2575  if (alp_tctx != NULL)
2576  AppLayerParserThreadCtxFree(alp_tctx);
2578  FLOW_DESTROY(&f);
2579  return result;
2580 }
2581 
2582 static int SMBParserTest09(void)
2583 {
2584  int result = 0;
2585  Flow f;
2586  uint8_t smbbuf1[] = {
2587  /* session request */
2588  0x81, 0x00, 0x00, 0x44, 0x20, 0x45, 0x44, 0x45,
2589  0x4a, 0x46, 0x44, 0x45, 0x44, 0x45, 0x50, 0x43,
2590  0x4e, 0x46, 0x48, 0x44, 0x43, 0x45, 0x4c, 0x43,
2591  0x4e, 0x46, 0x43, 0x46, 0x45, 0x45, 0x4e, 0x43,
2592  0x41, 0x43, 0x41, 0x43, 0x41, 0x00, 0x20, 0x45,
2593  0x44, 0x45, 0x4a, 0x46, 0x44, 0x45, 0x44, 0x45,
2594  0x50, 0x43, 0x4e, 0x46, 0x49, 0x46, 0x41, 0x43,
2595  0x4e, 0x46, 0x43, 0x46, 0x45, 0x45, 0x4e, 0x43,
2596  0x41, 0x43, 0x41, 0x43, 0x41, 0x41, 0x41, 0x00
2597  };
2598  uint8_t smbbuf2[] = {
2599  /* session service - negotiate protocol */
2600  0x00, 0x00, 0x00, 0x85, 0xff, 0x53, 0x4d, 0x42,
2601  0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x53, 0xc8,
2602  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2603  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
2604  0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x02,
2605  0x50, 0x43, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f,
2606  0x52, 0x4b, 0x20, 0x50, 0x52, 0x4f, 0x47, 0x52,
2607  0x41, 0x4d, 0x20, 0x31, 0x2e, 0x30, 0x00, 0x02,
2608  0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e,
2609  0x30, 0x00, 0x02, 0x57, 0x69, 0x6e, 0x64, 0x6f,
2610  0x77, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x57,
2611  0x6f, 0x72, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70,
2612  0x73, 0x20, 0x33, 0x2e, 0x31, 0x61, 0x00, 0x02,
2613  0x4c, 0x4d, 0x31, 0x2e, 0x32, 0x58, 0x30, 0x30,
2614  0x32, 0x00, 0x02, 0x4c, 0x41, 0x4e, 0x4d, 0x41,
2615  0x4e, 0x32, 0x2e, 0x31, 0x00, 0x02, 0x4e, 0x54,
2616  0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32,
2617  0x00
2618  };
2619  uint32_t smblen1 = sizeof(smbbuf1);
2620  uint32_t smblen2 = sizeof(smbbuf2);
2621  TcpSession ssn;
2623  int r = 0;
2624  memset(&f, 0, sizeof(f));
2625  memset(&ssn, 0, sizeof(ssn));
2626  FLOW_INITIALIZE(&f);
2627  f.protoctx = (void *)&ssn;
2628  f.proto = IPPROTO_TCP;
2629  f.alproto = ALPROTO_SMB;
2630 
2632 
2633  FLOWLOCK_WRLOCK(&f);
2634  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SMB,
2635  STREAM_TOSERVER | STREAM_START, smbbuf1, smblen1);
2636  if (r != 0) {
2637  printf("smb header check returned %" PRId32 ", expected 0: ", r);
2638  FLOWLOCK_UNLOCK(&f);
2639  goto end;
2640  }
2641  FLOWLOCK_UNLOCK(&f);
2642 
2643  SMBState *smb_state = f.alstate;
2644  if (smb_state == NULL) {
2645  printf("no smb state: ");
2646  goto end;
2647  }
2648 
2649  if (smb_state->smb.command != 0) {
2650  printf("we shouldn't have any smb state as yet\n");
2651  goto end;
2652  }
2653 
2654  if (smb_state->nbss.length != 68 ||
2655  smb_state->nbss.type != NBSS_SESSION_REQUEST) {
2656  printf("something wrong with nbss parsing\n");
2657  goto end;
2658  }
2659 
2660  if (smb_state->bytesprocessed != 0) {
2661  printf("smb parser bytesprocessed should be 0, but it is not\n");
2662  goto end;
2663  }
2664 
2665  FLOWLOCK_WRLOCK(&f);
2666  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SMB, STREAM_TOSERVER,
2667  smbbuf2, smblen2);
2668  if (r != 0) {
2669  printf("smb header check returned %" PRId32 ", expected 0: ", r);
2670  FLOWLOCK_UNLOCK(&f);
2671  goto end;
2672  }
2673  FLOWLOCK_UNLOCK(&f);
2674 
2675  if (smb_state->smb.command != SMB_COM_NEGOTIATE) {
2676  printf("we should expect SMB command 0x%02x , got 0x%02x : ",
2677  SMB_COM_NEGOTIATE, smb_state->smb.command);
2678  goto end;
2679  }
2680 
2681  if (smb_state->nbss.length != 133 ||
2682  smb_state->nbss.type != NBSS_SESSION_MESSAGE) {
2683  printf("something wrong with nbss parsing\n");
2684  goto end;
2685  }
2686 
2687  if (smb_state->bytesprocessed != 0) {
2688  printf("smb parser bytesprocessed should be 0, but it is not\n");
2689  goto end;
2690  }
2691 
2692  result = 1;
2693 end:
2694  if (alp_tctx != NULL)
2695  AppLayerParserThreadCtxFree(alp_tctx);
2697  FLOW_DESTROY(&f);
2698  return result;
2699 }
2700 
2701 /**
2702  * \test Test to temporarily to show the direction demaraction issue in the
2703  * smb parser.
2704  */
2705 static int SMBParserTest10(void)
2706 {
2707  int result = 0;
2708  Flow f;
2709  uint8_t smbbuf1[] = {
2710  /* partial request */
2711  0x00, 0x00, 0x00, 0x85, 0xff, 0x53, 0x4d, 0x42,
2712  0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x53, 0xc8,
2713  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2714  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
2715  0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x02,
2716  0x50, 0x43, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f,
2717  0x52, 0x4b, 0x20, 0x50, 0x52, 0x4f, 0x47, 0x52,
2718  0x41, 0x4d, 0x20, 0x31, 0x2e, 0x30, 0x00, 0x02,
2719  0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e,
2720  0x30, 0x00, 0x02, 0x57, 0x69, 0x6e, 0x64, 0x6f,
2721  0x77, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x57,
2722  0x6f, 0x72, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x70,
2723  0x73, 0x20, 0x33, 0x2e, 0x31, 0x61, 0x00, 0x02,
2724  0x4c, 0x4d, 0x31, 0x2e, 0x32, 0x58, 0x30, 0x30,
2725  0x32, 0x00, 0x02, 0x4c, 0x41, 0x4e, 0x4d, 0x41,
2726  };
2727  //0x4e, 0x32, 0x2e, 0x31, 0x00, 0x02, 0x4e, 0x54,
2728  //0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32,
2729  //0x00
2730 
2731  uint8_t smbbuf2[] = {
2732  /* response */
2733  0x00, 0x00, 0x00, 0x55, 0xff, 0x53, 0x4d, 0x42,
2734  0x72, 0x00, 0x00, 0x00, 0x00, 0x98, 0x53, 0xc8,
2735  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2736  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
2737  0x00, 0x00, 0x00, 0x00, 0x11, 0x05, 0x00, 0x03,
2738  0x32, 0x00, 0x01, 0x00, 0x04, 0x41, 0x00, 0x00,
2739  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
2740  0xfd, 0xf3, 0x00, 0x80, 0x20, 0x03, 0x1a, 0x2d,
2741  0x77, 0x98, 0xc5, 0x01, 0xa4, 0x01, 0x00, 0x10,
2742  0x00, 0xb7, 0xeb, 0x0b, 0x05, 0x21, 0x22, 0x50,
2743  0x42, 0x8c, 0x38, 0x2a, 0x7f, 0xc5, 0x6a, 0x7c,
2744  0x0c
2745  };
2746  uint32_t smblen1 = sizeof(smbbuf1);
2747  uint32_t smblen2 = sizeof(smbbuf2);
2748  TcpSession ssn;
2750  int r = 0;
2751  memset(&f, 0, sizeof(f));
2752  memset(&ssn, 0, sizeof(ssn));
2753  FLOW_INITIALIZE(&f);
2754  f.protoctx = (void *)&ssn;
2755  f.proto = IPPROTO_TCP;
2756  f.alproto = ALPROTO_SMB;
2757 
2759 
2760  FLOWLOCK_WRLOCK(&f);
2761  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SMB,
2762  STREAM_TOSERVER | STREAM_START, smbbuf1, smblen1);
2763  if (r != 0) {
2764  printf("smb header check returned %" PRId32 ", expected 0: ", r);
2765  FLOWLOCK_UNLOCK(&f);
2766  goto end;
2767  }
2768  FLOWLOCK_UNLOCK(&f);
2769 
2770  SMBState *smb_state = f.alstate;
2771  if (smb_state == NULL) {
2772  printf("no smb state: ");
2773  goto end;
2774  }
2775 
2776  if (smb_state->bytesprocessed == 0) {
2777  printf("request - smb parser bytesprocessed should not be 0.\n");
2778  goto end;
2779  }
2780 
2781  FLOWLOCK_WRLOCK(&f);
2782  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_SMB, STREAM_TOCLIENT,
2783  smbbuf2, smblen2);
2784  if (r == 0) {
2785  printf("smb parser didn't return fail\n");
2786  FLOWLOCK_UNLOCK(&f);
2787  goto end;
2788  }
2789  FLOWLOCK_UNLOCK(&f);
2790 
2791  result = 1;
2792 end:
2793  if (alp_tctx != NULL)
2794  AppLayerParserThreadCtxFree(alp_tctx);
2796  FLOW_DESTROY(&f);
2797  return result;
2798 }
2799 
2800 #endif
2801 
2803 {
2804 #ifdef UNITTESTS
2805  UtRegisterTest("SMBParserTest01", SMBParserTest01);
2806  UtRegisterTest("SMBParserTest02", SMBParserTest02);
2807  UtRegisterTest("SMBParserTest03", SMBParserTest03);
2808  UtRegisterTest("SMBParserTest04", SMBParserTest04);
2809  UtRegisterTest("SMBParserTest05", SMBParserTest05);
2810  UtRegisterTest("SMBParserTest06", SMBParserTest06);
2811  UtRegisterTest("SMBParserTest07", SMBParserTest07);
2812  UtRegisterTest("SMBParserTest08", SMBParserTest08);
2813  UtRegisterTest("SMBParserTest09", SMBParserTest09);
2814  UtRegisterTest("SMBParserTest10", SMBParserTest10);
2815 #endif
2816 }
2817 #endif /* HAVE_RUST */
2818 
void RegisterSMBParsers(void)
uint8_t type
#define SMB_FLAGS_SERVER_TO_REDIR
Definition: app-layer-smb.h:94
#define NBSS_RETARGET_SESSION_RESPONSE
#define SMB_COM_WRITE_ANDX
uint32_t status
Definition: app-layer-smb.h:40
uint16_t flags
#define SCMemcmp(a, b, c)
Definition: util-memcmp.h:490
uint8_t wordcount
Definition: app-layer-smb.h:57
uint16_t andxbytesprocessed
Definition: app-layer-smb.h:75
#define SCLogDebug(...)
Definition: util-debug.h:335
int AppLayerProtoDetectSetup(void)
The first function to be called. This initializes a global protocol detection context.
void AppLayerProtoDetectPPRegister(uint8_t ipproto, const char *portstr, AppProto alproto, uint16_t min_depth, uint16_t max_depth, uint8_t direction, ProbingParserFPtr ProbingParser1, ProbingParserFPtr ProbingParser2)
register parser at a port
SMBWordCount wordcount
Definition: app-layer-smb.h:86
DetectEngineState * de_state
#define SMB_COM_NEGOTIATE
#define NBSS_SESSION_MESSAGE
void AppLayerParserRegisterGetStateProgressFunc(uint8_t ipproto, AppProto alproto, int(*StateGetProgress)(void *alstate, uint8_t direction))
uint8_t proto
Definition: flow.h:346
uint8_t command
Definition: app-layer-smb.h:39
uint16_t bytesprocessed
Definition: app-layer-smb.h:84
void AppLayerProtoDetectUnittestCtxRestore(void)
Restores back the internal context used by the app layer proto detection module, that was previously ...
#define FLOWLOCK_UNLOCK(fb)
Definition: flow.h:235
DCERPCUuidEntry * uuid_entry
int AppLayerProtoDetectPrepareState(void)
Prepares the internal state for protocol detection. This needs to be called once all the patterns and...
#define unlikely(expr)
Definition: util-optimize.h:35
int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
Given a protocol name, checks if proto detection is enabled in the conf file.
#define SMB_COM_TREE_CONNECT_ANDX
#define SMB_COM_LOGOFF_ANDX
int AppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint8_t flag)
void AppLayerParserRegisterParserAcceptableDataDirection(uint8_t ipproto, AppProto alproto, uint8_t direction)
void AppLayerParserRegisterDetectStateFuncs(uint8_t ipproto, AppProto alproto, DetectEngineState *(*GetTxDetectState)(void *tx), int(*SetTxDetectState)(void *tx, DetectEngineState *))
uint16_t andxoffset
Definition: app-layer-smb.h:74
#define SMB_NO_SECONDARY_ANDX_COMMAND
Definition: app-layer-smb.h:95
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
#define SCReturnUInt(x)
Definition: util-debug.h:343
uint8_t wordcountleft
Definition: app-layer-smb.h:58
void StreamTcpFreeConfig(char quiet)
Definition: stream-tcp.c:669
#define FLOWLOCK_WRLOCK(fb)
Definition: flow.h:232
uint8_t maxchainedandx
Definition: app-layer-smb.h:73
uint16_t AppProto
int AppLayerProtoDetectDeSetup(void)
Cleans up the app layer protocol detection phase.
#define TRUE
#define NBSS_NEGATIVE_SESSION_RESPONSE
void * protoctx
Definition: flow.h:398
uint8_t data_needed_for_dir
Definition: app-layer-smb.h:91
NBSSHdr nbss
Definition: app-layer-smb.h:82
void * alstate
Definition: flow.h:436
int AppLayerParserConfParserEnabled(const char *ipproto, const char *alproto_name)
check if a parser is enabled in the config Returns enabled always if: were running unittests and when...
#define SCCalloc(nm, a)
Definition: util-mem.h:205
int AppLayerParserRegisterParser(uint8_t ipproto, AppProto alproto, uint8_t direction, AppLayerParserFPtr Parser)
Register app layer parser for the protocol.
uint8_t isandx
Definition: app-layer-smb.h:70
void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto, void *(StateGetTx)(void *alstate, uint64_t tx_id))
#define SMB_COM_OPEN_ANDX
int AppLayerProtoDetectPPParseConfPorts(const char *ipproto_name, uint8_t ipproto, const char *alproto_name, AppProto alproto, uint16_t min_depth, uint16_t max_depth, ProbingParserFPtr ProbingParserTs, ProbingParserFPtr ProbingParserTc)
#define SMB_PROBING_PARSER_MIN_DEPTH
#define FLOW_DESTROY(f)
Definition: flow-util.h:115
uint16_t pidhigh
Definition: app-layer-smb.h:43
#define NBSS_POSITIVE_SESSION_RESPONSE
#define STREAM_EOF
Definition: stream.h:30
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
uint8_t paddingparsed
Definition: app-layer-smb.h:71
uint16_t mid
Definition: app-layer-smb.h:49
void AppLayerProtoDetectUnittestCtxBackup(void)
Backs up the internal context used by the app layer proto detection module.
#define SCEnter(...)
Definition: util-debug.h:337
void StreamTcpInitConfig(char)
To initialize the stream global configuration data.
Definition: stream-tcp.c:365
uint64_t securitysignature
Definition: app-layer-smb.h:44
#define STREAM_TOCLIENT
Definition: stream.h:32
DCERPCBindBindAck dcerpcbindbindack
void AppLayerParserRegisterGetStateProgressCompletionStatus(AppProto alproto, int(*StateGetProgressCompletionStatus)(uint8_t direction))
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol&#39;s parser thread context.
#define NBSS_SESSION_KEEP_ALIVE
uint16_t tid
Definition: app-layer-smb.h:46
void DetectEngineStateFree(DetectEngineState *state)
Frees a DetectEngineState object.
int RunmodeIsUnittests(void)
Definition: suricata.c:261
uint16_t datalength
Definition: app-layer-smb.h:76
#define NBSS_SESSION_REQUEST
uint32_t length
#define SCReturnInt(x)
Definition: util-debug.h:341
AppProto AppLayerProtoDetectGetProto(AppLayerProtoDetectThreadCtx *tctx, Flow *f, uint8_t *buf, uint32_t buflen, uint8_t ipproto, uint8_t direction)
Returns the app layer protocol given a buffer.
SMBHdr smb
Definition: app-layer-smb.h:85
void RegisterRustSMBTCPParsers(void)
uint8_t flags
Definition: app-layer-smb.h:41
void printUUID(const char *type, DCERPCUuidEntry *uuid)
printUUID function used to print UUID, Major and Minor Version Number and if it was Accepted or Rejec...
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
uint16_t datalengthhigh
Definition: app-layer-smb.h:77
void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
Registers a protocol for protocol detection phase.
void SMBParserRegisterTests(void)
#define SCFree(a)
Definition: util-mem.h:236
uint16_t uid
Definition: app-layer-smb.h:48
Port dp
Definition: flow.h:340
int AppLayerProtoDetectPMRegisterPatternCS(uint8_t ipproto, AppProto alproto, const char *pattern, uint16_t depth, uint16_t offset, uint8_t direction)
Registers a case-sensitive pattern for protocol detection.
uint16_t tx_id
void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto, void(*RegisterUnittests)(void))
uint8_t andxcommand
Definition: app-layer-smb.h:72
#define NBSS_HDR_LEN
#define STREAM_START
Definition: stream.h:29
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:39
#define STREAM_TOSERVER
Definition: stream.h:31
#define SCReturnPtr(x, type)
Definition: util-debug.h:353
#define SMB_HDR_LEN
Definition: app-layer-smb.h:52
#define APP_LAYER_PARSER_EOF
uint8_t dcerpc_present
Definition: app-layer-smb.h:90
uint16_t flags2
Definition: app-layer-smb.h:42
SMBAndX andx
Definition: app-layer-smb.h:88
uint16_t bytecountleft
Definition: app-layer-smb.h:65
int32_t DCERPCParser(DCERPC *, uint8_t *, uint32_t)
void AppLayerProtoDetectDestroyCtxThread(AppLayerProtoDetectThreadCtx *alpd_tctx)
Destroys the app layer protocol detection thread context.
void DCERPCCleanup(DCERPC *dcerpc)
uint16_t pid
Definition: app-layer-smb.h:47
uint64_t dataoffset
Definition: app-layer-smb.h:78
#define SCReturn
Definition: util-debug.h:339
void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto, uint64_t(*StateGetTxCnt)(void *alstate))
void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto, void *(*StateAlloc)(void), void(*StateFree)(void *))
#define SMB_COM_LOCKING_ANDX
uint8_t len
SMBByteCount bytecount
Definition: app-layer-smb.h:87
AppLayerProtoDetectThreadCtx * AppLayerProtoDetectGetCtxThread(void)
Inits and returns an app layer protocol detection thread context.
AppProto alproto
application level protocol
Definition: flow.h:407
The app layer protocol detection thread context.
int isAndX(SMBState *smb_state)
determines if the SMB command is an ANDX command
#define SMB_COM_SESSION_SETUP_ANDX
#define SMB_COM_NT_CREATE_ANDX
void DCERPCInit(DCERPC *dcerpc)
uint8_t bytecountbytes
Definition: app-layer-smb.h:63
#define SMB_COM_TRANSACTION
Flow data structure.
Definition: flow.h:327
DCERPCState ds
Definition: app-layer-smb.h:89
uint16_t bytecount
Definition: app-layer-smb.h:64
#define SMB_COM_READ_ANDX
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, uint8_t *input, uint32_t input_len)
void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto, void(*StateTransactionFree)(void *, uint64_t))
uint16_t transaction_id
Definition: app-layer-smb.h:83