Branch data Line data Source code
1 : : // $Id: SMB.cc 6219 2008-10-01 05:39:07Z vern $
2 : : //
3 : : // See the file "COPYING" in the main distribution directory for copyright.
4 : :
5 : : #include "NetVar.h"
6 : : #include "SMB.h"
7 : : #include "smb_pac.h"
8 : : #include "Val.h"
9 : :
10 : : namespace {
11 : : const bool DEBUG_smb_ipc = true;
12 : : }
13 : :
14 : : #define BYTEORDER_SWAP16(n) ((256 * ((n) & 0xff)) + ((n) >> 8))
15 : :
16 : : enum SMB_Command {
17 : : #define SMB_COMMAND(name, value) name = value,
18 : : #include "SMB_COM.def"
19 : : #undef SMB_COMMAND
20 : : };
21 : :
22 : : enum SMB_Transaction_Command {
23 : : HOST_ANNOUNCEMENT = 1,
24 : : ANNOUCEMENT_REQUEST = 2,
25 : : REQUEST_ELECTION = 8,
26 : : GET_BACKUP_LIST_REQUEST = 9,
27 : : GET_BACKUP_LIST_RESPONSE = 10,
28 : : BECOME_BACKUP_REQUEST = 11,
29 : : DOMAIN_ANNOUNCEMENT = 12,
30 : : MASTER_ANNOUNCEMENT = 13,
31 : : RESET_BROWSER_STATE = 14,
32 : : LOCAL_MASTER_ANNOUNCEMENT = 15,
33 : : };
34 : :
35 : : const char* SMB_command_name[256];
36 : : StringVal* SMB_command_str[256];
37 : : const char* SMB_trans_command_name[256];
38 : : StringVal* SMB_trans_command_str[256];
39 : :
40 : 0 : static void init_SMB_command_name()
41 : : {
42 : : static int initialized = 0;
43 [ # # ]: 0 : if ( initialized )
44 : 0 : return;
45 : :
46 : 0 : initialized = 1;
47 : :
48 [ # # ]: 0 : for ( int i = 0; i < 256; ++i )
49 : : {
50 : 0 : SMB_command_name[i] = "<unknown>";
51 : 0 : SMB_command_str[i] = 0;
52 : : }
53 : :
54 : : #define SMB_COMMAND(name, value) SMB_command_name[value] = #name;
55 : : #include "SMB_COM.def"
56 : : #undef SMB_COMMAND
57 : : #define SMB_COMMAND(name, value) SMB_trans_command_name[value] = #name;
58 : 0 : SMB_COMMAND(HOST_ANNOUNCEMENT, 1)
59 : 0 : SMB_COMMAND(ANNOUCEMENT_REQUEST, 2)
60 : 0 : SMB_COMMAND(REQUEST_ELECTION, 8)
61 : 0 : SMB_COMMAND(GET_BACKUP_LIST_REQUEST, 9)
62 : 0 : SMB_COMMAND(GET_BACKUP_LIST_RESPONSE, 10)
63 : 0 : SMB_COMMAND(BECOME_BACKUP_REQUEST, 11)
64 : 0 : SMB_COMMAND(DOMAIN_ANNOUNCEMENT, 12)
65 : 0 : SMB_COMMAND(MASTER_ANNOUNCEMENT, 13)
66 : 0 : SMB_COMMAND(RESET_BROWSER_STATE, 14)
67 : 0 : SMB_COMMAND(LOCAL_MASTER_ANNOUNCEMENT, 15)
68 : :
69 : : }
70 : :
71 : 0 : StringVal* get_SMB_command_str(int cmd)
72 : : {
73 [ # # ]: 0 : if ( ! SMB_command_str[cmd] )
74 : 0 : SMB_command_str[cmd] = new StringVal(SMB_command_name[cmd]);
75 : :
76 : 0 : return SMB_command_str[cmd];
77 : : }
78 : :
79 : : // ### TODO: the list of IPC pipes needs a lot of expansion.
80 : 0 : static int lookup_IPC_name(BroString* name)
81 : : {
82 : : static const char* IPC_pipe_names[] = {
83 : : "\\locator", "\\epmapper", "\\samr", "\\lsarpc", 0
84 : : };
85 : :
86 [ # # ]: 0 : for ( int i = 0; IPC_pipe_names[i]; ++i )
87 : : {
88 [ # # ][ # # ]: 0 : if ( size_t(name->Len()) == strlen(IPC_pipe_names[i]) &&
[ # # ]
89 : : strncmp((const char*) name->Bytes(),
90 : : IPC_pipe_names[i], name->Len()) == 0 )
91 : 0 : return i + 1;
92 : : }
93 : :
94 : 0 : return IPC_NONE;
95 : : }
96 : :
97 : 0 : SMB_Session::SMB_Session(Analyzer* arg_analyzer)
98 : : {
99 : 0 : analyzer = arg_analyzer;
100 : 0 : dce_rpc_session = 0;
101 : 0 : init_SMB_command_name();
102 : :
103 : : // Strangely, one does not have to connect to IPC$ before
104 : : // making DCE/RPC calls. So we assume that it's always IPC
105 : : // unless confirmed otherwise.
106 : :
107 : 0 : is_IPC = true;
108 : 0 : IPC_pipe = IPC_NONE;
109 : :
110 : 0 : transaction_name = 0;
111 : 0 : transaction_subcmd = 0;
112 : :
113 : 0 : andx_[0] = andx_[1] = 0;
114 : 0 : set_andx(0, 0);
115 : 0 : set_andx(1, 0);
116 : :
117 : 0 : }
118 : :
119 : 0 : SMB_Session::~SMB_Session()
120 : : {
121 : 0 : binpac::Unref(andx_[0]);
122 : 0 : binpac::Unref(andx_[1]);
123 : 0 : Unref(transaction_name);
124 [ # # # # ]: 0 : delete dce_rpc_session;
125 : 0 : }
126 : :
127 : 0 : void SMB_Session::set_andx(int is_orig, binpac::SMB::SMB_andx* andx)
128 : : {
129 [ # # ]: 0 : int ind = is_orig ? 1 : 0;
130 [ # # ]: 0 : if ( andx )
131 : 0 : andx->Ref();
132 : :
133 : 0 : binpac::Unref(andx_[ind]);
134 : :
135 : 0 : andx_[ind] = andx;
136 : 0 : }
137 : :
138 : 0 : void SMB_Session::Deliver(int is_orig, int len, const u_char* data)
139 : : {
140 [ # # ]: 0 : if ( len == 0 )
141 : 0 : return;
142 : :
143 : : try
144 : : {
145 : 0 : const u_char* data_start = data;
146 : 0 : const u_char* data_end = data + len;
147 : :
148 : 0 : binpac::SMB::SMB_header hdr;
149 : 0 : int hdr_len = hdr.Parse(data, data_end);
150 : :
151 : 0 : data += hdr_len;
152 : :
153 : 0 : int next_command = hdr.command();
154 : :
155 [ # # ][ # # ]: 0 : while ( data < data_end )
156 : : {
157 : 0 : SMB_Body body(data, data_end);
158 : 0 : set_andx(is_orig, 0);
159 : 0 : ParseMessage(is_orig, next_command, hdr, body);
160 : :
161 : 0 : int next = AndxOffset(is_orig, next_command);
162 [ # # ]: 0 : if ( next <= 0 )
163 : 0 : break;
164 : :
165 : : //Weird(fmt("ANDX! at %d", next));
166 : 0 : const u_char* tmp = data_start + next;
167 [ # # ]: 0 : if ( data_start + next < data + body.length() )
168 : : {
169 : 0 : Weird(fmt("ANDX buffer overlapping: next = %d, buffer_end = %d", next, data + body.length() - data_start));
170 : : break;
171 : : }
172 : :
173 : 0 : data = data_start + next;
174 : 0 : }
175 : : }
176 : 0 : catch ( const binpac::Exception& e )
177 : : {
178 : 0 : analyzer->Weird(e.msg().c_str());
179 : : }
180 : : }
181 : :
182 : : void SMB_Session::ParseMessage(int is_orig, int cmd,
183 : : binpac::SMB::SMB_header const& hdr,
184 : 0 : SMB_Body const& body)
185 : : {
186 [ # # ]: 0 : if ( smb_message )
187 : : {
188 : 0 : val_list* vl = new val_list;
189 : 0 : StringVal* cmd_str = get_SMB_command_str(cmd);
190 : 0 : Ref(cmd_str);
191 : :
192 : 0 : vl->append(analyzer->BuildConnVal());
193 : 0 : vl->append(BuildHeaderVal(hdr));
194 : 0 : vl->append(new Val(is_orig, TYPE_BOOL));
195 : 0 : vl->append(cmd_str);
196 : 0 : vl->append(new Val(body.length(), TYPE_COUNT));
197 : : vl->append(new StringVal(body.length(),
198 : 0 : (const char*) body.data()));
199 : :
200 : 0 : analyzer->ConnectionEvent(smb_message, vl);
201 : : }
202 : :
203 [ # # ]: 0 : if ( is_orig )
204 : 0 : req_cmd = cmd;
205 : :
206 : : // What if there's an error?
207 : : // if ( hdr.status->status() || hdr.status->dos_error() )
208 : : // The command code in the header might be right, but
209 : : // the response is probably mangled :-(.
210 : :
211 : 0 : int ci = hdr.status()->val_case_index();
212 [ # # # # ]: 0 : if ( (ci == 1 && hdr.status()->status()) ||
[ # # ][ # # ]
[ # # ][ # # ]
213 : : (ci == 0 && (hdr.status()->dos_error()->error_class() ||
214 : : hdr.status()->dos_error()->error())) )
215 : : {
216 : 0 : unsigned int error = 0;
217 : :
218 [ # # # ]: 0 : switch ( ci ) {
219 : : case 0:
220 : : error = hdr.status()->dos_error()->error_class() << 24 ||
221 [ # # ][ # # ]: 0 : hdr.status()->dos_error()->error();
222 : 0 : break;
223 : : case 1:
224 : 0 : error = hdr.status()->status();
225 : : break;
226 : : }
227 : :
228 : 0 : val_list* vl = new val_list;
229 : 0 : StringVal* cmd_str = get_SMB_command_str(cmd);
230 : 0 : Ref(cmd_str);
231 : :
232 : 0 : vl->append(analyzer->BuildConnVal());
233 : 0 : vl->append(BuildHeaderVal(hdr));
234 : 0 : vl->append(new Val(cmd, TYPE_COUNT));
235 : 0 : vl->append(cmd_str);
236 : : vl->append(new StringVal(body.length(),
237 : 0 : (const char*) body.data()));
238 : :
239 : 0 : analyzer->ConnectionEvent(smb_error, vl);
240 : :
241 : : // Is this the right behavior?
242 : 0 : return;
243 : : }
244 : :
245 : 0 : int ret = 0;
246 [ # # # # # : 0 : switch ( cmd ) {
# # # # #
# ]
247 : : case SMB_COM_TREE_CONNECT_ANDX:
248 [ # # ]: 0 : if ( is_orig )
249 : 0 : ret = ParseTreeConnectAndx(hdr, body);
250 : : else
251 : 0 : ret = ParseAndx(is_orig, hdr, body);
252 : 0 : break;
253 : :
254 : : case SMB_COM_NT_CREATE_ANDX:
255 [ # # ]: 0 : if ( is_orig )
256 : 0 : ret = ParseNtCreateAndx(hdr, body);
257 : : else
258 : 0 : ret = ParseAndx(is_orig, hdr, body);
259 : 0 : break;
260 : :
261 : : case SMB_COM_TRANSACTION:
262 : : case SMB_COM_TRANSACTION2:
263 : : case SMB_COM_TRANSACTION_SECONDARY:
264 : : case SMB_COM_TRANSACTION2_SECONDARY:
265 : 0 : ret = ParseTransaction(is_orig, cmd, hdr, body);
266 : 0 : break;
267 : :
268 : : case SMB_COM_READ_ANDX:
269 [ # # ]: 0 : if ( is_orig )
270 : 0 : ret = ParseReadAndx(hdr, body);
271 : : else
272 : 0 : ret = ParseReadAndxResponse(hdr, body);
273 : 0 : break;
274 : :
275 : : case SMB_COM_WRITE_ANDX:
276 [ # # ]: 0 : if ( is_orig )
277 : 0 : ret = ParseWriteAndx(hdr, body);
278 : : else
279 : 0 : ret = ParseWriteAndxResponse(hdr, body);
280 : 0 : break;
281 : :
282 : : case SMB_COM_NEGOTIATE:
283 [ # # ]: 0 : if ( is_orig )
284 : 0 : ret = ParseNegotiate(hdr, body);
285 : : else
286 : 0 : ret = ParseNegotiateResponse(hdr, body);
287 : 0 : break;
288 : :
289 : : case SMB_COM_CLOSE:
290 : 0 : ret = ParseClose(is_orig, hdr, body);
291 : 0 : break;
292 : :
293 : : case SMB_COM_TREE_DISCONNECT:
294 : 0 : ret = ParseTreeDisconnect(is_orig, hdr, body);
295 : 0 : break;
296 : :
297 : : case SMB_COM_LOGOFF_ANDX:
298 [ # # ]: 0 : if ( is_orig )
299 : 0 : ret = ParseLogoffAndx(is_orig, hdr, body);
300 : : else
301 : 0 : ret = ParseAndx(is_orig, hdr, body);
302 : 0 : break;
303 : :
304 : : case SMB_COM_SESSION_SETUP_ANDX:
305 [ # # ]: 0 : if ( is_orig )
306 : 0 : ret = ParseSetupAndx(is_orig, hdr, body);
307 : : else
308 : 0 : ret = ParseAndx(is_orig, hdr, body);
309 : 0 : break;
310 : :
311 : : default:
312 : 0 : Weird(fmt("unknown_SMB_command(0x%x)", cmd));
313 : : break;
314 : : }
315 : :
316 [ # # ]: 0 : if ( ret == -1 )
317 : 0 : Weird("SMB_parsing_error");
318 : : }
319 : :
320 : : int SMB_Session::ParseNegotiate(binpac::SMB::SMB_header const& hdr,
321 : 0 : SMB_Body const& body)
322 : : {
323 : 0 : binpac::SMB::SMB_negotiate msg;
324 : 0 : msg.Parse(body.data(), body.data() + body.length());
325 : :
326 [ # # ]: 0 : if ( smb_com_negotiate )
327 : : {
328 : 0 : TableVal* t = new TableVal(smb_negotiate);
329 [ # # ]: 0 : for ( int i = 0; i < int(msg.dialects()->size()); ++i )
330 : : {
331 : 0 : binpac::SMB::SMB_dialect* d = (*msg.dialects())[i];
332 : 0 : BroString* tmp = ExtractString(d->dialectname());
333 : 0 : t->Assign(new Val(i, TYPE_COUNT), new StringVal(tmp));
334 : : }
335 : :
336 : 0 : val_list* vl = new val_list;
337 : 0 : vl->append(analyzer->BuildConnVal());
338 : 0 : vl->append(BuildHeaderVal(hdr));
339 : 0 : vl->append(t);
340 : :
341 : 0 : analyzer->ConnectionEvent(smb_com_negotiate, vl);
342 : : }
343 : :
344 : 0 : return 0;
345 : : }
346 : :
347 : : int SMB_Session::ParseNegotiateResponse(binpac::SMB::SMB_header const& hdr,
348 : 0 : SMB_Body const& body)
349 : : {
350 : 0 : binpac::SMB::SMB_negotiate_response msg;
351 : 0 : msg.Parse(body.data(), body.data() + body.length());
352 : :
353 [ # # ]: 0 : if ( smb_com_negotiate_response )
354 : : {
355 : 0 : val_list* vl = new val_list;
356 : 0 : vl->append(analyzer->BuildConnVal());
357 : 0 : vl->append(BuildHeaderVal(hdr));
358 : 0 : vl->append(new Val(msg.dialect_index(), TYPE_COUNT));
359 : :
360 : 0 : analyzer->ConnectionEvent(smb_com_negotiate_response, vl);
361 : : }
362 : :
363 : 0 : return 0;
364 : : }
365 : :
366 : : int SMB_Session::ParseSetupAndx(int is_orig, binpac::SMB::SMB_header const& hdr,
367 : 0 : SMB_Body const& body)
368 : : {
369 : : // The binpac type depends on the negotiated server settings -
370 : : // possibly we can just pick the "right" format here, and use that?
371 : :
372 [ # # ][ # # ]: 0 : if ( hdr.flags2() && 0x0800 )
373 : : {
374 : 0 : binpac::SMB::SMB_setup_andx_ext msg(hdr.unicode());
375 : 0 : msg.Parse(body.data(), body.data() + body.length());
376 : 0 : set_andx(1, msg.andx());
377 : : }
378 : : else
379 : : {
380 : 0 : binpac::SMB::SMB_setup_andx_basic msg(hdr.unicode());
381 : 0 : msg.Parse(body.data(), body.data() + body.length());
382 : 0 : set_andx(1, msg.andx());
383 : : }
384 : :
385 [ # # ]: 0 : if ( smb_com_setup_andx )
386 : : {
387 : 0 : val_list* vl = new val_list;
388 : 0 : vl->append(analyzer->BuildConnVal());
389 : 0 : vl->append(BuildHeaderVal(hdr));
390 : :
391 : 0 : analyzer->ConnectionEvent(smb_com_setup_andx, vl);
392 : : }
393 : :
394 : 0 : return 0;
395 : : }
396 : :
397 : : int SMB_Session::ParseClose(int is_orig, binpac::SMB::SMB_header const& hdr,
398 : 0 : SMB_Body const& body)
399 : : {
400 [ # # ]: 0 : if ( smb_com_close )
401 : : {
402 : 0 : val_list* vl = new val_list;
403 : 0 : vl->append(analyzer->BuildConnVal());
404 : 0 : vl->append(BuildHeaderVal(hdr));
405 : :
406 : 0 : analyzer->ConnectionEvent(smb_com_close, vl);
407 : : }
408 : :
409 : 0 : return 0;
410 : : }
411 : :
412 : : int SMB_Session::ParseLogoffAndx(int is_orig,
413 : : binpac::SMB::SMB_header const& hdr,
414 : 0 : SMB_Body const& body)
415 : : {
416 : 0 : binpac::SMB::SMB_generic_andx msg;
417 : 0 : msg.Parse(body.data(), body.data() + body.length());
418 [ # # ]: 0 : if ( msg.word_count() > 0 )
419 : 0 : set_andx(is_orig, msg.andx());
420 : :
421 [ # # ]: 0 : if ( smb_com_logoff_andx )
422 : : {
423 : 0 : val_list* vl = new val_list;
424 : 0 : vl->append(analyzer->BuildConnVal());
425 : 0 : vl->append(BuildHeaderVal(hdr));
426 : :
427 : 0 : analyzer->ConnectionEvent(smb_com_logoff_andx, vl);
428 : : }
429 : :
430 : 0 : return 0;
431 : : }
432 : :
433 : : int SMB_Session::ParseAndx(int is_orig, binpac::SMB::SMB_header const& hdr,
434 : 0 : SMB_Body const& body)
435 : : {
436 : : // This is a generic ANDX event generator. It passes the header
437 : : // and the ANDX data out to the policy.
438 : : try
439 : : {
440 : 0 : binpac::SMB::SMB_generic_andx msg;
441 : 0 : msg.Parse(body.data(), body.data() + body.length());
442 [ # # ]: 0 : if ( msg.word_count() > 0 )
443 : 0 : set_andx(is_orig, msg.andx());
444 : :
445 [ # # ]: 0 : if ( smb_com_generic_andx )
446 : : {
447 : 0 : val_list* vl = new val_list;
448 : 0 : vl->append(analyzer->BuildConnVal());
449 : 0 : vl->append(BuildHeaderVal(hdr));
450 : : vl->append(new StringVal(msg.data().length(),
451 : 0 : (char *) msg.data().begin()));
452 : :
453 : 0 : analyzer->ConnectionEvent(smb_com_generic_andx, vl);
454 : 0 : }
455 : : }
456 : 0 : catch ( const binpac::Exception& )
457 : : {
458 : 0 : Weird("smb_andx_command_failed_to_parse");
459 : : }
460 : :
461 : 0 : return 0;
462 : : }
463 : :
464 : : int SMB_Session::ParseTreeConnectAndx(binpac::SMB::SMB_header const& hdr,
465 : 0 : SMB_Body const& body)
466 : : {
467 : 0 : binpac::SMB::SMB_tree_connect_andx req(hdr.unicode());
468 : :
469 : 0 : req.Parse(body.data(), body.data() + body.length());
470 : 0 : set_andx(1, req.andx());
471 : :
472 : 0 : BroString* path = ExtractString(req.path());
473 : 0 : BroString* service = ExtractString(req.service());
474 : :
475 : : // Replicate path.
476 : 0 : BroString* norm_path = new BroString(path->Bytes(), path->Len(), 1);
477 : 0 : norm_path->ToUpper();
478 : :
479 : 0 : RecordVal* r = new RecordVal(smb_tree_connect);
480 : 0 : r->Assign(0, new Val(req.flags(), TYPE_COUNT));
481 : : r->Assign(1, new StringVal(req.password_length(),
482 : 0 : (const char*) req.password()));
483 : 0 : r->Assign(3, new StringVal(path));
484 : 0 : r->Assign(4, new StringVal(service));
485 : :
486 [ # # ]: 0 : if ( strstr_n(norm_path->Len(), norm_path->Bytes(), 5,
487 : : (const u_char*) "\\IPC$") != -1 )
488 : 0 : is_IPC = true; // TODO: change is_IPC to 0 on tree_disconnect
489 : : else
490 : 0 : is_IPC = false;
491 : :
492 [ # # ]: 0 : delete norm_path;
493 : :
494 [ # # ]: 0 : if ( smb_com_tree_connect_andx )
495 : : {
496 : 0 : val_list* vl = new val_list;
497 : 0 : vl->append(analyzer->BuildConnVal());
498 : 0 : vl->append(BuildHeaderVal(hdr));
499 : 0 : vl->append(r);
500 : :
501 : 0 : analyzer->ConnectionEvent(smb_com_tree_connect_andx, vl);
502 : : }
503 : : else
504 : : {
505 [ # # ]: 0 : delete path;
506 [ # # ]: 0 : delete service;
507 : : }
508 : :
509 : 0 : return 0;
510 : : }
511 : :
512 : : int SMB_Session::ParseTreeDisconnect(int is_orig,
513 : : binpac::SMB::SMB_header const& hdr,
514 : 0 : SMB_Body const& body)
515 : : {
516 : 0 : binpac::SMB::SMB_tree_disconnect msg(hdr.unicode());
517 : 0 : msg.Parse(body.data(), body.data() + body.length());
518 : :
519 [ # # ]: 0 : if ( smb_com_nt_create_andx )
520 : : {
521 : 0 : val_list* vl = new val_list;
522 : 0 : vl->append(analyzer->BuildConnVal());
523 : 0 : vl->append(BuildHeaderVal(hdr));
524 : :
525 : 0 : analyzer->ConnectionEvent(smb_com_tree_disconnect, vl);
526 : : }
527 : :
528 : 0 : return 0;
529 : : }
530 : :
531 : : int SMB_Session::ParseNtCreateAndx(binpac::SMB::SMB_header const& hdr,
532 : 0 : SMB_Body const& body)
533 : : {
534 : 0 : binpac::SMB::SMB_nt_create_andx req(hdr.unicode());
535 : 0 : req.Parse(body.data(), body.data() + body.length());
536 : 0 : set_andx(1, req.andx());
537 : :
538 : 0 : BroString* name = ExtractString(req.name());
539 : :
540 : 0 : IPC_pipe = (enum IPC_named_pipe) lookup_IPC_name(name);
541 : :
542 [ # # ]: 0 : if ( smb_com_nt_create_andx )
543 : : {
544 : 0 : val_list* vl = new val_list;
545 : 0 : vl->append(analyzer->BuildConnVal());
546 : 0 : vl->append(BuildHeaderVal(hdr));
547 : 0 : vl->append(new StringVal(name));
548 : :
549 : 0 : analyzer->ConnectionEvent(smb_com_nt_create_andx, vl);
550 : : }
551 : : else
552 [ # # ]: 0 : delete name;
553 : :
554 : 0 : return 0;
555 : : }
556 : :
557 : : int SMB_Session::ParseReadAndx(binpac::SMB::SMB_header const& hdr,
558 : 0 : SMB_Body const& body)
559 : : {
560 : 0 : binpac::SMB::SMB_read_andx req;
561 : 0 : req.Parse(body.data(), body.data() + body.length());
562 : 0 : set_andx(1, req.andx());
563 : :
564 [ # # ]: 0 : if ( smb_com_read_andx )
565 : : {
566 : 0 : val_list* vl = new val_list;
567 : 0 : vl->append(analyzer->BuildConnVal());
568 : 0 : vl->append(BuildHeaderVal(hdr));
569 : 0 : vl->append(new StringVal(""));
570 : :
571 : 0 : analyzer->ConnectionEvent(smb_com_read_andx, vl);
572 : : }
573 : :
574 : 0 : return 0;
575 : : }
576 : :
577 : : int SMB_Session::ParseReadAndxResponse(binpac::SMB::SMB_header const& hdr,
578 : 0 : SMB_Body const& body)
579 : : {
580 : 0 : binpac::SMB::SMB_read_andx_response resp;
581 : 0 : resp.Parse(body.data(), body.data() + body.length());
582 : 0 : set_andx(0, resp.andx());
583 : :
584 : 0 : int data_count = resp.data_length();
585 : 0 : const u_char* data = resp.data().begin();
586 : :
587 [ # # ]: 0 : if ( smb_com_read_andx )
588 : : {
589 : 0 : val_list* vl = new val_list;
590 : 0 : vl->append(analyzer->BuildConnVal());
591 : 0 : vl->append(BuildHeaderVal(hdr));
592 : 0 : vl->append(new StringVal(data_count, (const char*) data));
593 : :
594 : 0 : analyzer->ConnectionEvent(smb_com_read_andx, vl);
595 : : }
596 : :
597 : 0 : CheckRPC(0, data_count, data);
598 : :
599 : 0 : return 0;
600 : : }
601 : :
602 : : int SMB_Session::ParseWriteAndx(binpac::SMB::SMB_header const& hdr,
603 : 0 : SMB_Body const& body)
604 : : {
605 : 0 : binpac::SMB::SMB_write_andx req;
606 : 0 : req.Parse(body.data(), body.data() + body.length());
607 : 0 : set_andx(1, req.andx());
608 : :
609 : 0 : int data_count = req.data_length();
610 : 0 : const u_char* data = req.data().begin();
611 : :
612 [ # # ]: 0 : if ( smb_com_write_andx )
613 : : {
614 : 0 : val_list* vl = new val_list;
615 : 0 : vl->append(analyzer->BuildConnVal());
616 : 0 : vl->append(BuildHeaderVal(hdr));
617 : 0 : vl->append(new StringVal(data_count, (const char*) data));
618 : :
619 : 0 : analyzer->ConnectionEvent(smb_com_write_andx, vl);
620 : : }
621 : :
622 : 0 : CheckRPC(1, data_count, data);
623 : :
624 : 0 : return 0;
625 : : }
626 : :
627 : : int SMB_Session::ParseWriteAndxResponse(binpac::SMB::SMB_header const& hdr,
628 : 0 : SMB_Body const& body)
629 : : {
630 : 0 : binpac::SMB::SMB_write_andx_response resp;
631 : 0 : resp.Parse(body.data(), body.data() + body.length());
632 : 0 : set_andx(0, resp.andx());
633 : :
634 [ # # ]: 0 : if ( smb_com_write_andx )
635 : : {
636 : 0 : val_list* vl = new val_list;
637 : 0 : vl->append(analyzer->BuildConnVal());
638 : 0 : vl->append(BuildHeaderVal(hdr));
639 : 0 : vl->append(new StringVal(""));
640 : :
641 : 0 : analyzer->ConnectionEvent(smb_com_write_andx, vl);
642 : : }
643 : :
644 : 0 : return 0;
645 : : }
646 : :
647 : : int SMB_Session::TransactionEvent(EventHandlerPtr f, int is_orig,
648 : : binpac::SMB::SMB_header const &hdr,
649 : : binpac::SMB::SMB_transaction const &trans,
650 : : int data_count,
651 : 0 : binpac::SMB::SMB_transaction_data* data)
652 : : {
653 [ # # ]: 0 : if ( f )
654 : : {
655 : 0 : val_list* vl = new val_list;
656 : :
657 : 0 : vl->append(analyzer->BuildConnVal());
658 : 0 : vl->append(BuildHeaderVal(hdr));
659 : 0 : vl->append(BuildTransactionVal(trans));
660 : 0 : vl->append(BuildTransactionDataVal(data));
661 : 0 : vl->append(new Val(is_orig, TYPE_BOOL));
662 : :
663 : 0 : analyzer->ConnectionEvent(f, vl);
664 : : }
665 : :
666 : 0 : else if ( smb_com_transaction )
667 : : { // generic transaction
668 : : }
669 : :
670 : 0 : return 0;
671 : : }
672 : :
673 : : int SMB_Session::TransactionEvent(EventHandlerPtr f, int is_orig,
674 : : binpac::SMB::SMB_header const &hdr,
675 : : binpac::SMB::SMB_transaction_secondary const &trans,
676 : 0 : int data_count, binpac::SMB::SMB_transaction_data* data)
677 : : {
678 [ # # ]: 0 : if ( f )
679 : : {
680 : 0 : val_list* vl = new val_list;
681 : :
682 : 0 : vl->append(analyzer->BuildConnVal());
683 : 0 : vl->append(BuildHeaderVal(hdr));
684 : 0 : vl->append(BuildTransactionVal(trans));
685 : 0 : vl->append(BuildTransactionDataVal(data));
686 : 0 : vl->append(new Val(is_orig, TYPE_BOOL));
687 : :
688 : 0 : analyzer->ConnectionEvent(f, vl);
689 : : }
690 : :
691 : 0 : else if ( smb_com_transaction )
692 : : { // generic transaction
693 : : }
694 : :
695 : 0 : return 0;
696 : : }
697 : :
698 : : int SMB_Session::TransactionEvent(EventHandlerPtr f, int is_orig,
699 : : binpac::SMB::SMB_header const &hdr,
700 : : binpac::SMB::SMB_transaction_response const &trans,
701 : 0 : int data_count, binpac::SMB::SMB_transaction_data* data)
702 : : {
703 [ # # ]: 0 : if ( f )
704 : : {
705 : 0 : val_list* vl = new val_list;
706 : :
707 : 0 : vl->append(analyzer->BuildConnVal());
708 : 0 : vl->append(BuildHeaderVal(hdr));
709 : 0 : vl->append(BuildTransactionVal(trans));
710 : 0 : vl->append(BuildTransactionDataVal(data));
711 : 0 : vl->append(new Val(is_orig, TYPE_BOOL));
712 : :
713 : 0 : analyzer->ConnectionEvent(f, vl);
714 : : }
715 : :
716 : 0 : else if ( smb_com_transaction )
717 : : { // generic transaction
718 : : }
719 : :
720 : 0 : return 0;
721 : : }
722 : :
723 : : int SMB_Session::ParseTransaction(int is_orig, int cmd,
724 : : binpac::SMB::SMB_header const& hdr,
725 : 0 : SMB_Body const& body)
726 : : {
727 [ # # ]: 0 : switch ( cmd ) {
728 : : case SMB_COM_TRANSACTION:
729 : : case SMB_COM_TRANSACTION2:
730 : : case SMB_COM_TRANSACTION_SECONDARY:
731 : : case SMB_COM_TRANSACTION2_SECONDARY:
732 : : break;
733 : :
734 : : default:
735 : 0 : internal_error("command mismatch for ParseTransaction");
736 : : }
737 : :
738 : : int ret;
739 [ # # ]: 0 : if ( is_orig )
740 : : {
741 [ # # ][ # # ]: 0 : if ( cmd == SMB_COM_TRANSACTION || cmd == SMB_COM_TRANSACTION2 )
742 : 0 : ret = ParseTransactionRequest(cmd, hdr, body);
743 : :
744 [ # # ][ # # ]: 0 : else if ( cmd == SMB_COM_TRANSACTION_SECONDARY ||
745 : : cmd == SMB_COM_TRANSACTION2_SECONDARY )
746 : 0 : ret = ParseTransactionSecondaryRequest(cmd, hdr, body);
747 : :
748 : : else
749 : 0 : ret = 0;
750 : : }
751 : : else
752 : 0 : ret = ParseTransactionResponse(cmd, hdr, body);
753 : :
754 : 0 : return ret;
755 : : }
756 : :
757 : : int SMB_Session::ParseTransactionRequest(int cmd,
758 : : binpac::SMB::SMB_header const& hdr,
759 : 0 : SMB_Body const& body)
760 : : {
761 : : binpac::SMB::SMB_transaction trans(cmd == SMB_COM_TRANSACTION ? 1 : 2,
762 [ # # ]: 0 : hdr.unicode());
763 : :
764 : 0 : trans.Parse(body.data(), body.data() + body.length());
765 : :
766 [ # # ]: 0 : if ( transaction_name )
767 : : {
768 : 0 : Unref(transaction_name);
769 : 0 : transaction_name = 0;
770 : : }
771 : :
772 [ # # ]: 0 : if ( cmd == SMB_COM_TRANSACTION )
773 : : {
774 : 0 : binpac::SMB::SMB_transaction_data* trans_data = trans.data();
775 : :
776 : : //transaction_name = new StringVal(ExtractString(trans.name()));
777 : : //if ( is_orig )
778 : : // Weird(fmt("smb_transaction subcmd: 0x%x", transaction_subcmd));
779 : :
780 [ # # # # ]: 0 : if ( trans_data->val_case_index() ==
[ # # ]
781 : : binpac::SMB::SMB_MAILSLOT_BROWSE &&
782 : : trans_data->mailslot() )
783 : : { // Mailslot transaction event
784 : : return TransactionEvent(smb_com_trans_mailslot, true,
785 : 0 : hdr, trans, trans.data_count(), trans.data());
786 : : }
787 : :
788 [ # # ][ # # ]: 0 : else if ( trans_data->val_case_index() ==
[ # # ]
789 : : binpac::SMB::SMB_PIPE && trans_data->pipe() )
790 : : { // Pipe
791 : : return TransactionEvent(smb_com_trans_pipe, true, hdr,
792 : 0 : trans, trans.data_count(), trans.data());
793 : : }
794 : :
795 [ # # ][ # # ]: 0 : else if ( trans_data->val_case_index() ==
[ # # ]
796 : : binpac::SMB::SMB_RAP && trans_data->rap() )
797 : : { // Remote Administration Protocol
798 : : return TransactionEvent(smb_com_trans_rap, true, hdr,
799 : 0 : trans, trans.data_count(), trans.data());
800 : : }
801 : :
802 : : else
803 : : {
804 : : // SOME UNKNOWN TRANSACTION TYPE - COULD BE RPC STILL!
805 [ # # ][ # # ]: 0 : if ( trans.data_count() > 0 && trans.setup_count() == 2 )
[ # # ]
806 : : {
807 [ # # ]: 0 : if ( CheckRPC(true, trans.data_count(),
808 : : trans_data->pipe()->data().begin()) )
809 : : {
810 [ # # ][ # # ]: 0 : if ( cmd != SMB_COM_TRANSACTION ||
811 : : transaction_subcmd != 0x26 )
812 : 0 : Weird(fmt("RPC through unknown command: 0x%x/0x%x", cmd, transaction_subcmd));
813 : : }
814 : : }
815 : : }
816 : : }
817 : :
818 [ # # ]: 0 : if ( cmd == SMB_COM_TRANSACTION2 )
819 : : {
820 [ # # # ]: 0 : switch ( transaction_subcmd ) {
821 : : case 0x3: // QueryFSInfo
822 : : case 0x5: // QueryPathInfo
823 : : case 0x7: // QueryFileInfo
824 : : case 0x8: // SetFileInfo
825 : 0 : break;
826 : :
827 : : case 0x10:
828 : : // if ( is_orig )
829 : : return ParseGetDFSReferral(hdr, trans.param_count(),
830 : 0 : trans.parameters().begin());
831 : :
832 : : default:
833 : : // if ( is_orig )
834 : : Weird(fmt("Unknown smb_transaction2 subcmd: 0x%x",
835 : 0 : transaction_subcmd));
836 : : break;
837 : : }
838 : : }
839 : :
840 [ # # ]: 0 : if ( smb_com_transaction )
841 : : return TransactionEvent(smb_com_transaction, true, hdr,
842 : : trans, trans.data_count(),
843 : 0 : trans.data());
844 : : else
845 : 0 : return 0;
846 : :
847 : : #if 0
848 : : // TODO: LANMAN transaction uses the first u_short of
849 : : // parameters as subcmd
850 : :
851 : : if ( trans.setup_count() > 0 )
852 : : transaction_subcmd = (*trans.setup())[0];
853 : :
854 : : else if ( strncmp( transaction_name->CheckString(), "\\PIPE\\", 6 ) == 0 )
855 : : transaction_subcmd = 0;
856 : :
857 : : else if ( strncmp( transaction_name->CheckString(), "\\MAILSLOT\\", 10 ) == 0 )
858 : : transaction_subcmd = 0;
859 : :
860 : : else
861 : : Weird("transaction_subcmd_missing");
862 : : #endif
863 : : }
864 : :
865 : : int SMB_Session::ParseTransactionSecondaryRequest(int cmd,
866 : : binpac::SMB::SMB_header const& hdr,
867 : 0 : SMB_Body const& body)
868 : : {
869 : 0 : binpac::SMB::SMB_transaction_secondary trans(hdr.unicode());
870 : 0 : trans.Parse(body.data(), body.data() + body.length());
871 : :
872 : : return TransactionEvent(smb_com_transaction2, true, hdr,
873 : 0 : trans, trans.data_count(), trans.data());
874 : : }
875 : :
876 : : int SMB_Session::ParseTransactionResponse(int cmd,
877 : : binpac::SMB::SMB_header const& hdr,
878 : 0 : SMB_Body const& body)
879 : : {
880 : 0 : binpac::SMB::SMB_transaction_response trans(hdr.unicode());
881 : 0 : trans.Parse(body.data(), body.data() + body.length());
882 : :
883 [ # # ]: 0 : if ( body.word_count() == 0 )
884 : : { // interim response
885 : : // Does the transaction get parsed correctly?!
886 : : return TransactionEvent(smb_com_transaction, false, hdr,
887 : 0 : trans, 0, NULL);
888 : : }
889 : :
890 : : return TransactionEvent(smb_com_transaction, false, hdr,
891 : 0 : trans, trans.data_count(), trans.data());
892 : : }
893 : :
894 : : int SMB_Session::ParseGetDFSReferral(binpac::SMB::SMB_header const& hdr,
895 : 0 : int param_count, const u_char* param)
896 : : {
897 : 0 : binpac::SMB::SMB_get_dfs_referral req(hdr.unicode());
898 : 0 : req.Parse(param, param + param_count);
899 : :
900 [ # # ]: 0 : if ( smb_get_dfs_referral )
901 : : {
902 : 0 : val_list* vl = new val_list;
903 : 0 : vl->append(analyzer->BuildConnVal());
904 : 0 : vl->append(BuildHeaderVal(hdr));
905 : 0 : vl->append(new Val(req.max_referral_level(), TYPE_COUNT));
906 : 0 : vl->append(new StringVal(ExtractString(req.file_name())));
907 : :
908 : 0 : analyzer->ConnectionEvent(smb_get_dfs_referral, vl);
909 : : }
910 : :
911 : 0 : return 0;
912 : : }
913 : :
914 : 0 : int SMB_Session::AndxOffset(int is_orig, int& next_command) const
915 : : {
916 [ # # ]: 0 : if ( ! andx(is_orig) )
917 : 0 : return -1;
918 : :
919 : 0 : next_command = andx(is_orig)->command();
920 [ # # ]: 0 : if ( next_command != 0xff )
921 : 0 : return andx(is_orig)->offset();
922 : : else
923 : 0 : return -1;
924 : : }
925 : :
926 : 0 : void SMB_Session::Weird(const char* msg)
927 : : {
928 : 0 : analyzer->Weird(msg);
929 : 0 : }
930 : :
931 : : // Extract a NUL-terminated string from [data, data+len-1]. The
932 : : // input can be in Unicode (little endian), and the returned string
933 : : // will be in ASCII. Note, Unicode strings have NUL characters
934 : : // at the end of them already. Adding an additional NUL byte at
935 : : // the end leads to embedded-NUL warnings (CheckString() run_time error).
936 : :
937 : 0 : BroString* SMB_Session::ExtractString(binpac::SMB::SMB_string const* s)
938 : : {
939 [ # # ]: 0 : return s->unicode() ? ExtractString(s->u()) : ExtractString(s->a());
940 : : }
941 : :
942 : 0 : BroString* SMB_Session::ExtractString(binpac::SMB::SMB_ascii_string const* s)
943 : : {
944 : 0 : bool add_NUL = true;
945 : 0 : int n = s->size();
946 : :
947 [ # # # # ]: 0 : if ( n > 0 && (*s)[n - 1] == '\0' )
[ # # ]
948 : 0 : add_NUL = false; // already has a NUL
949 : :
950 [ # # ]: 0 : if ( add_NUL )
951 : 0 : ++n;
952 : :
953 : 0 : u_char* b = new u_char[n];
954 : : int i;
955 [ # # ]: 0 : for ( i = 0; i < int(s->size()); ++i )
956 : 0 : b[i] = (*s)[i];
957 : :
958 [ # # ]: 0 : if ( add_NUL )
959 : 0 : b[i] = '\0';
960 : :
961 : 0 : return new BroString(1, b, n - 1);
962 : : }
963 : :
964 : 0 : BroString* SMB_Session::ExtractString(binpac::SMB::SMB_unicode_string const* s)
965 : : {
966 : 0 : bool add_NUL = true;
967 : 0 : int n = s->s()->size();
968 : :
969 [ # # # # ]: 0 : if ( n > 0 && ((*s->s())[n - 1] & 0xff) == '\0' )
[ # # ]
970 : 0 : add_NUL = false; // already has a NUL
971 : :
972 [ # # ]: 0 : if ( add_NUL )
973 : 0 : ++n;
974 : :
975 : 0 : u_char* b = new u_char[n];
976 : :
977 : : int i;
978 [ # # ]: 0 : for ( i = 0; i < int(s->s()->size()); ++i )
979 : : {
980 : 0 : uint16 x = (*s->s())[i];
981 [ # # ]: 0 : if ( x & 0xff00 )
982 : 0 : Weird(fmt("unicode string confusion: 0x%04x", x));
983 : :
984 : 0 : b[i] = u_char(x & 0xff);
985 : : }
986 : :
987 [ # # ]: 0 : if ( add_NUL )
988 : 0 : b[i] = '\0';
989 : :
990 : 0 : return new BroString(1, b, n - 1);
991 : : }
992 : :
993 : 0 : Val* SMB_Session::BuildHeaderVal(binpac::SMB::SMB_header const& hdr)
994 : : {
995 : 0 : RecordVal* r = new RecordVal(smb_hdr);
996 : :
997 : 0 : unsigned int status = 0;
998 : :
999 : : try
1000 : : {
1001 : : // FIXME: does this work? We need to catch exceptions :-(
1002 : : // or use guard functions.
1003 : : status = hdr.status()->status() ||
1004 : : hdr.status()->dos_error()->error_class() << 24 ||
1005 [ # # # # ]: 0 : hdr.status()->dos_error()->error();
[ # # ]
1006 : : }
1007 : 0 : catch ( const binpac::Exception& )
1008 : : { // do nothing
1009 : : }
1010 : :
1011 : 0 : r->Assign(0, new Val(hdr.command(), TYPE_COUNT));
1012 : 0 : r->Assign(1, new Val(status, TYPE_COUNT));
1013 : 0 : r->Assign(2, new Val(hdr.flags(), TYPE_COUNT));
1014 : 0 : r->Assign(3, new Val(hdr.flags2(), TYPE_COUNT));
1015 : 0 : r->Assign(4, new Val(hdr.tid(), TYPE_COUNT));
1016 : 0 : r->Assign(5, new Val(hdr.pid(), TYPE_COUNT));
1017 : 0 : r->Assign(6, new Val(hdr.uid(), TYPE_COUNT));
1018 : 0 : r->Assign(7, new Val(hdr.mid(), TYPE_COUNT));
1019 : :
1020 : 0 : return r;
1021 : : }
1022 : :
1023 : 0 : Val* SMB_Session::BuildTransactionVal(binpac::SMB::SMB_transaction const& trans)
1024 : : {
1025 : 0 : RecordVal* r = new RecordVal(smb_trans);
1026 : :
1027 : : // r->Assign(0, new Val(variable, type));
1028 : :
1029 : 0 : return r;
1030 : : }
1031 : :
1032 : 0 : Val* SMB_Session::BuildTransactionVal(binpac::SMB::SMB_transaction_secondary const& trans)
1033 : : {
1034 : 0 : RecordVal* r = new RecordVal(smb_trans);
1035 : :
1036 : : // r->Assign(0, new Val(variable, type));
1037 : :
1038 : 0 : return r;
1039 : : }
1040 : :
1041 : 0 : Val* SMB_Session::BuildTransactionVal(binpac::SMB::SMB_transaction_response const& trans)
1042 : : {
1043 : 0 : RecordVal* r = new RecordVal(smb_trans);
1044 : :
1045 : : // r->Assign(0, new Val(variable, type));
1046 : :
1047 : 0 : return r;
1048 : : }
1049 : :
1050 : 0 : Val* SMB_Session::BuildTransactionDataVal(binpac::SMB::SMB_transaction_data *data)
1051 : : {
1052 : 0 : RecordVal* r = new RecordVal(smb_trans_data);
1053 : :
1054 : : // r->Assign(0, new Val(variable, type));
1055 : :
1056 : 0 : return r;
1057 : : }
1058 : :
1059 : 0 : bool SMB_Session::LooksLikeRPC(int len, const u_char* msg)
1060 : : {
1061 : : try
1062 : : {
1063 : 0 : binpac::DCE_RPC_Simple::DCE_RPC_Header h;
1064 : 0 : h.Parse(msg, msg + len);
1065 : :
1066 [ # # # # ]: 0 : if ( h.rpc_vers() == 5 && h.rpc_vers_minor() == 0 )
[ # # ]
1067 : : {
1068 : 0 : unsigned short frag_len = h.frag_length();
1069 [ # # # # ]: 0 : if ( frag_len == len ||
1070 : : BYTEORDER_SWAP16(frag_len) == len )
1071 : : {
1072 [ # # ]: 0 : if ( ! is_IPC && DEBUG_smb_ipc )
1073 : 0 : analyzer->Weird("TreeConnect to IPC missing");
1074 : 0 : return true;
1075 : : }
1076 : : else
1077 : : {
1078 : 0 : analyzer->Weird(fmt("endianness %d", h.byteorder()));
1079 : : analyzer->Weird(fmt("length mismatch: %d != %d",
1080 : 0 : h.frag_length(), len));
1081 : 0 : return false;
1082 : : }
1083 [ # # ]: 0 : }
1084 : : }
1085 : 0 : catch ( const binpac::Exception& )
1086 : : { // do nothing
1087 : : }
1088 : :
1089 : 0 : return false;
1090 : : }
1091 : :
1092 : 0 : bool SMB_Session::CheckRPC(int is_orig, int data_count, const u_char *data)
1093 : : {
1094 [ # # ]: 0 : if ( LooksLikeRPC(data_count, data) )
1095 : : {
1096 [ # # ]: 0 : if ( ! dce_rpc_session )
1097 : 0 : dce_rpc_session = new DCE_RPC_Session(analyzer);
1098 : :
1099 : 0 : dce_rpc_session->DeliverPDU(is_orig, data_count, data);
1100 : :
1101 : 0 : return true;
1102 : : }
1103 : :
1104 : 0 : return false;
1105 : : }
1106 : :
1107 : 0 : Contents_SMB::Contents_SMB(Connection* conn, bool orig, SMB_Session* s)
1108 : 0 : : TCP_SupportAnalyzer(AnalyzerTag::Contents_SMB, conn, orig)
1109 : : {
1110 : 0 : smb_session = s;
1111 : 0 : msg_buf = 0;
1112 : 0 : msg_len = 0;
1113 : 0 : buf_len = 0;
1114 : 0 : buf_n = 0;
1115 : 0 : }
1116 : :
1117 : 0 : void Contents_SMB::InitMsgBuf()
1118 : : {
1119 [ # # ]: 0 : delete [] msg_buf;
1120 : 0 : msg_buf = new u_char[msg_len];
1121 : 0 : buf_len = msg_len;
1122 : 0 : buf_n = 0;
1123 : 0 : }
1124 : :
1125 : 0 : Contents_SMB::~Contents_SMB()
1126 : : {
1127 [ # # ][ # # ]: 0 : delete [] msg_buf;
[ # # ]
1128 [ # # ][ # # ]: 0 : }
[ # # ]
1129 : :
1130 : 0 : void Contents_SMB::DeliverSMB(int len, const u_char* data)
1131 : : {
1132 : : // Check the 4-byte header.
1133 [ # # ]: 0 : if ( strncmp((const char*) data, "\xffSMB", 4) )
1134 : : {
1135 : : Conn()->Weird(fmt("SMB-over-TCP header error: %02x%02x%02x%02x, \\x%02x%c%c%c",
1136 : : dshdr[0], dshdr[1], dshdr[2], dshdr[3],
1137 : 0 : data[0], data[1], data[2], data[3]));
1138 : 0 : SetSkip(1);
1139 : : }
1140 : : else
1141 : 0 : smb_session->Deliver(IsOrig(), len, data);
1142 : :
1143 : 0 : buf_n = 0;
1144 : 0 : msg_len = 0;
1145 : 0 : }
1146 : :
1147 : 0 : void Contents_SMB::DeliverStream(int len, const u_char* data, bool orig)
1148 : : {
1149 : 0 : TCP_SupportAnalyzer::DeliverStream(len, data, orig);
1150 : :
1151 [ # # ]: 0 : while ( len > 0 )
1152 : : {
1153 [ # # ]: 0 : if ( ! msg_len )
1154 : : {
1155 : : // Get the SMB-over-TCP header (4 bytes).
1156 [ # # ][ # # ]: 0 : while ( buf_n < 4 && len > 0 )
1157 : : {
1158 : 0 : dshdr[buf_n] = *data;
1159 : 0 : ++buf_n; ++data; --len;
1160 : : }
1161 : :
1162 [ # # ]: 0 : if ( buf_n < 4 )
1163 : 0 : return;
1164 : :
1165 : 0 : buf_n = 0;
1166 [ # # ]: 0 : for ( int i = 1; i < 4; ++i )
1167 : 0 : msg_len = ( msg_len << 8 ) + dshdr[i];
1168 : :
1169 [ # # ]: 0 : if ( dshdr[0] != 0 )
1170 : : {
1171 : : // Netbios header indicates this is NOT
1172 : : // a session message ...
1173 : : // 0x81 = session request
1174 : : // 0x82 = positive response
1175 : : // 0x83 = neg response
1176 : : // 0x84 = retarget(?)
1177 : : // 0x85 = keepalive
1178 : : // Maybe we should just generate a Netbios
1179 : : // event and die?
1180 : 0 : Conn()->Weird("SMB checked Netbios type and found != 0");
1181 : 0 : SetSkip(1);
1182 : 0 : return;
1183 : : }
1184 : :
1185 [ # # ]: 0 : else if ( msg_len <= 4 )
1186 : : {
1187 : 0 : Conn()->Weird("SMB message length error");
1188 : 0 : SetSkip(1);
1189 : 0 : return;
1190 : : }
1191 : : }
1192 : :
1193 [ # # ][ # # ]: 0 : if ( buf_n == 0 && msg_len <= len )
1194 : : {
1195 : : // The fast lane:
1196 : : // Keep msg_len -- it will be changed in DeliverSMB
1197 : 0 : int mlen = msg_len;
1198 : 0 : DeliverSMB(msg_len, data);
1199 : 0 : len -= mlen;
1200 : 0 : data += mlen;
1201 : : }
1202 : :
1203 : : else
1204 : : {
1205 [ # # ]: 0 : if ( buf_len < msg_len )
1206 : 0 : InitMsgBuf();
1207 : :
1208 [ # # ][ # # ]: 0 : while ( buf_n < msg_len && len > 0 )
1209 : : {
1210 : 0 : msg_buf[buf_n] = *data;
1211 : 0 : ++buf_n;
1212 : 0 : ++data;
1213 : 0 : --len;
1214 : : }
1215 : :
1216 [ # # ]: 0 : if ( buf_n < msg_len )
1217 : 0 : return;
1218 : :
1219 : 0 : DeliverSMB(msg_len, msg_buf);
1220 : : }
1221 : : }
1222 : : }
1223 : :
1224 : 0 : SMB_Analyzer::SMB_Analyzer(Connection* conn)
1225 : 0 : : TCP_ApplicationAnalyzer(AnalyzerTag::SMB, conn)
1226 : : {
1227 : 0 : smb_session = new SMB_Session(this);
1228 : 0 : o_smb = new Contents_SMB(conn, true, smb_session);
1229 : 0 : r_smb = new Contents_SMB(conn, false, smb_session);
1230 : 0 : AddSupportAnalyzer(o_smb);
1231 : 0 : AddSupportAnalyzer(r_smb);
1232 : 0 : }
1233 : :
1234 : 0 : SMB_Analyzer::~SMB_Analyzer()
1235 : : {
1236 [ # # ][ # # ]: 0 : delete smb_session;
[ # # ]
1237 [ + - ][ + - ]: 6 : }
[ # # ][ # # ]
[ # # ]
|