suricata
app-layer-smb.c
Go to the documentation of this file.
1/* Copyright (C) 2017-2021 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 * SMB protocol handling
22 */
23
24#include "suricata-common.h"
25#include "suricata.h"
26
27#include "app-layer-protos.h"
29#include "app-layer-parser.h"
30
31#include "util-unittest.h"
32
33#include "rust.h"
34#include "app-layer-smb.h"
35#include "util-misc.h"
36
37
39static SuricataFileContext sfc = { &sbcfg };
40
41#ifdef UNITTESTS
42static void SMBParserRegisterTests(void);
43#endif
44
46{
47 SCSmbInit(&sfc);
48 SCRegisterSmbParser();
49
50#ifdef UNITTESTS
51 AppLayerParserRegisterProtocolUnittests(IPPROTO_TCP, ALPROTO_SMB, SMBParserRegisterTests);
52#endif
53}
54
55#ifdef UNITTESTS
56#include "stream-tcp.h"
58
59/** \test multi transactions and cleanup */
60static int SMBParserTxCleanupTest(void)
61{
62 uint64_t ret[4];
65
67 TcpSession ssn;
68 memset(&ssn, 0, sizeof(ssn));
69
70 Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 445);
71 FAIL_IF_NULL(f);
72 f->protoctx = &ssn;
73 f->proto = IPPROTO_TCP;
76
77 char req_str[] ="\x00\x00\x00\x79\xfe\x53\x4d\x42\x40\x00\x01\x00\x00\x00\x00\x00" \
78 "\x05\x00\xe0\x1e\x10\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00" \
79 "\x00\x00\x00\x00\x00\x00\x00\x00\x10\x72\xd2\x9f\x36\xc2\x08\x14" \
80 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
81 "\x00\x00\x00\x00\x39\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00" \
82 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00" \
83 "\x00\x00\x00\x00\x07\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" \
84 "\x78\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
85 req_str[28] = 0x01;
87 STREAM_TOSERVER | STREAM_START, (uint8_t *)req_str, sizeof(req_str));
88 FAIL_IF_NOT(r == 0);
89 req_str[28]++;
91 STREAM_TOSERVER, (uint8_t *)req_str, sizeof(req_str));
92 FAIL_IF_NOT(r == 0);
93 req_str[28]++;
95 STREAM_TOSERVER, (uint8_t *)req_str, sizeof(req_str));
96 FAIL_IF_NOT(r == 0);
97 req_str[28]++;
99 STREAM_TOSERVER, (uint8_t *)req_str, sizeof(req_str));
100 FAIL_IF_NOT(r == 0);
101 req_str[28]++;
103 STREAM_TOSERVER, (uint8_t *)req_str, sizeof(req_str));
104 FAIL_IF_NOT(r == 0);
105 req_str[28]++;
107 STREAM_TOSERVER, (uint8_t *)req_str, sizeof(req_str));
108 FAIL_IF_NOT(r == 0);
109 req_str[28]++;
111 STREAM_TOSERVER, (uint8_t *)req_str, sizeof(req_str));
112 FAIL_IF_NOT(r == 0);
113 req_str[28]++;
115 STREAM_TOSERVER, (uint8_t *)req_str, sizeof(req_str));
116 FAIL_IF_NOT(r == 0);
117 req_str[28]++;
118
119 AppLayerParserTransactionsCleanup(f, STREAM_TOSERVER);
120 UTHAppLayerParserStateGetIds(f->alparser, &ret[0], &ret[1], &ret[2], &ret[3]);
121 FAIL_IF_NOT(ret[0] == 0); // inspect_id[0]
122 FAIL_IF_NOT(ret[1] == 0); // inspect_id[1]
123 FAIL_IF_NOT(ret[2] == 0); // log_id
124 FAIL_IF_NOT(ret[3] == 0); // min_id
125
126 char resp_str[] = "\x00\x00\x00\x98\xfe\x53\x4d\x42\x40\x00\x01\x00\x00\x00\x00\x00" \
127 "\x05\x00\x21\x00\x11\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00" \
128 "\x00\x00\x00\x00\x00\x00\x00\x00\x10\x72\xd2\x9f\x36\xc2\x08\x14" \
129 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
130 "\x00\x00\x00\x00\x59\x00\x00\x00\x01\x00\x00\x00\x48\x38\x40\xb3" \
131 "\x0f\xa8\xd3\x01\x84\x9a\x2b\x46\xf7\xa8\xd3\x01\x48\x38\x40\xb3" \
132 "\x0f\xa8\xd3\x01\x48\x38\x40\xb3\x0f\xa8\xd3\x01\x00\x00\x00\x00" \
133 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00" \
134 "\x00\x00\x00\x00\x9e\x8f\xb8\x91\x00\x00\x00\x00\x01\x5b\x11\xbb" \
135 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
136
137 resp_str[28] = 0x01;
139 STREAM_TOCLIENT | STREAM_START, (uint8_t *)resp_str, sizeof(resp_str));
140 FAIL_IF_NOT(r == 0);
141 resp_str[28] = 0x04;
143 STREAM_TOCLIENT, (uint8_t *)resp_str, sizeof(resp_str));
144 FAIL_IF_NOT(r == 0);
145 resp_str[28] = 0x05;
147 STREAM_TOCLIENT, (uint8_t *)resp_str, sizeof(resp_str));
148 FAIL_IF_NOT(r == 0);
149 resp_str[28] = 0x06;
151 STREAM_TOCLIENT, (uint8_t *)resp_str, sizeof(resp_str));
152 FAIL_IF_NOT(r == 0);
153 resp_str[28] = 0x08;
155 STREAM_TOCLIENT, (uint8_t *)resp_str, sizeof(resp_str));
156 FAIL_IF_NOT(r == 0);
157 resp_str[28] = 0x02;
159 STREAM_TOCLIENT, (uint8_t *)resp_str, sizeof(resp_str));
160 FAIL_IF_NOT(r == 0);
161 resp_str[28] = 0x07;
163 STREAM_TOCLIENT, (uint8_t *)resp_str, sizeof(resp_str));
164 FAIL_IF_NOT(r == 0);
165 AppLayerParserTransactionsCleanup(f, STREAM_TOCLIENT);
166
167 UTHAppLayerParserStateGetIds(f->alparser, &ret[0], &ret[1], &ret[2], &ret[3]);
168 FAIL_IF_NOT(ret[0] == 2); // inspect_id[0]
169 FAIL_IF_NOT(ret[1] == 2); // inspect_id[1]
170 FAIL_IF_NOT(ret[2] == 2); // log_id
171 FAIL_IF_NOT(ret[3] == 2); // min_id
172
173 resp_str[28] = 0x03;
175 STREAM_TOCLIENT, (uint8_t *)resp_str, sizeof(resp_str));
176 FAIL_IF_NOT(r == 0);
177 AppLayerParserTransactionsCleanup(f, STREAM_TOCLIENT);
178
179 UTHAppLayerParserStateGetIds(f->alparser, &ret[0], &ret[1], &ret[2], &ret[3]);
180 FAIL_IF_NOT(ret[0] == 8); // inspect_id[0]
181 FAIL_IF_NOT(ret[1] == 8); // inspect_id[1]
182 FAIL_IF_NOT(ret[2] == 8); // log_id
183 FAIL_IF_NOT(ret[3] == 8); // min_id
184
185 req_str[28] = 0x09;
187 STREAM_TOSERVER | STREAM_EOF, (uint8_t *)req_str, sizeof(req_str));
188 FAIL_IF_NOT(r == 0);
189 AppLayerParserTransactionsCleanup(f, STREAM_TOSERVER);
190
191 UTHAppLayerParserStateGetIds(f->alparser, &ret[0], &ret[1], &ret[2], &ret[3]);
192 FAIL_IF_NOT(ret[0] == 8); // inspect_id[0] not updated by ..Cleanup() until full tx is done
193 FAIL_IF_NOT(ret[1] == 8); // inspect_id[1]
194 FAIL_IF_NOT(ret[2] == 8); // log_id
195 FAIL_IF_NOT(ret[3] == 8); // min_id
196
197 resp_str[28] = 0x09;
199 STREAM_TOCLIENT | STREAM_EOF, (uint8_t *)resp_str, sizeof(resp_str));
200 FAIL_IF_NOT(r == 0);
201 AppLayerParserTransactionsCleanup(f, STREAM_TOCLIENT);
202
203 UTHAppLayerParserStateGetIds(f->alparser, &ret[0], &ret[1], &ret[2], &ret[3]);
204 FAIL_IF_NOT(ret[0] == 9); // inspect_id[0]
205 FAIL_IF_NOT(ret[1] == 9); // inspect_id[1]
206 FAIL_IF_NOT(ret[2] == 9); // log_id
207 FAIL_IF_NOT(ret[3] == 9); // min_id
208
211 UTHFreeFlow(f);
212
213 PASS;
214}
215
216static void SMBParserRegisterTests(void)
217{
218 UtRegisterTest("SMBParserTxCleanupTest", SMBParserTxCleanupTest);
219}
220
221#endif /* UNITTESTS */
void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto, void(*RegisterUnittests)(void))
void AppLayerParserTransactionsCleanup(Flow *f, const uint8_t pkt_dir)
remove obsolete (inspected and logged) transactions
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, const uint8_t *input, uint32_t input_len)
void UTHAppLayerParserStateGetIds(void *ptr, uint64_t *i1, uint64_t *i2, uint64_t *log, uint64_t *min)
@ ALPROTO_SMB
void RegisterSMBParsers(void)
#define FLOW_SGH_TOCLIENT
Definition flow.h:75
#define FLOW_SGH_TOSERVER
Definition flow.h:73
AppLayerParserThreadCtx * alp_tctx
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
#define PASS
Pass the test.
void StreamTcpFreeConfig(bool quiet)
Definition stream-tcp.c:859
void StreamTcpInitConfig(bool)
To initialize the stream global configuration data.
Definition stream-tcp.c:488
Flow data structure.
Definition flow.h:356
uint8_t proto
Definition flow.h:378
uint32_t flags
Definition flow.h:421
AppProto alproto
application level protocol
Definition flow.h:450
void * protoctx
Definition flow.h:441
AppLayerParserState * alparser
Definition flow.h:478
#define STREAMING_BUFFER_CONFIG_INITIALIZER
void UTHFreeFlow(Flow *flow)
Flow * UTHBuildFlow(int family, const char *src, const char *dst, Port sp, Port dp)