1 //--------------------------------------------------------------------------
2 // Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3 // Copyright (C) 2002-2013 Sourcefire, Inc.
4 // Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
5 //
6 // This program is free software; you can redistribute it and/or modify it
7 // under the terms of the GNU General Public License Version 2 as published
8 // by the Free Software Foundation. You may not use, modify or distribute
9 // this program under any other version of the GNU General Public License.
10 //
11 // This program is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License along
17 // with this program; if not, write to the Free Software Foundation, Inc.,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 //--------------------------------------------------------------------------
20
21 /* rpc_decode
22 *
23 * Purpose:
24 *
25 * This inspector normalizes the RPC requests from remote machines by
26 * converting all fragments into one continuous stream.
27 * This is very useful for doing things like defeating hostile attackers
28 * trying to stealth themselves from IDSs by fragmenting the request so the
29 * string 0186A0 is broken up.
30 *
31 * Effect:
32 *
33 * Changes the data in the packet payload and changes
34 * p->dsize to reflect the new (smaller) payload size.
35 */
36
37 #ifdef HAVE_CONFIG_H
38 #include "config.h"
39 #endif
40
41 #include "detection/detection_util.h"
42 #include "detection/detection_engine.h"
43 #include "framework/data_bus.h"
44 #include "log/messages.h"
45 #include "profiler/profiler.h"
46 #include "protocols/packet.h"
47 #include "stream/stream.h"
48 #include "stream/stream_splitter.h"
49 #include "utils/safec.h"
50 #include "utils/util.h"
51
52 #include "rpc_module.h"
53
54 using namespace snort;
55 using namespace std;
56
57 #define RPC_MAX_BUF_SIZE 256
58 #define RPC_FRAG_HDR_SIZE sizeof(uint32_t)
59 #define RPC_FRAG_LEN(ptr) (ntohl(*((const uint32_t*)(ptr))) & 0x7FFFFFFF)
60
61 struct RpcBuffer
62 {
63 uint8_t* data;
64 uint32_t len;
65 uint32_t size;
66 };
67
68 struct RpcSsnData
69 {
70 int active;
71 int events;
72 uint32_t frag_len;
73 uint32_t ignore;
74 RpcBuffer seg;
75 RpcBuffer frag;
76 };
77
78 class RpcFlowData : public FlowData
79 {
80 public:
81 RpcFlowData();
82 ~RpcFlowData() override;
83
init()84 static void init()
85 { inspector_id = FlowData::create_flow_data_id(); }
86
87 public:
88 static unsigned inspector_id;
89 RpcSsnData session;
90 };
91
92 unsigned RpcFlowData::inspector_id = 0;
93
94 typedef enum _RpcStatus
95 {
96 RPC_STATUS__SUCCESS,
97 RPC_STATUS__ERROR,
98 RPC_STATUS__DEFRAG
99 } RpcStatus;
100
101 struct RpcStats
102 {
103 PegCount total_packets;
104 PegCount concurrent_sessions;
105 PegCount max_concurrent_sessions;
106 };
107
108 static const uint32_t flush_size = 28;
109
110 #define mod_name "rpc_decode"
111 #define mod_help "RPC inspector"
112
113 THREAD_LOCAL ProfileStats rpcdecodePerfStats;
114 THREAD_LOCAL RpcStats rdstats;
115
116 static int ConvertRPC(RpcSsnData*, Packet*);
117
118 static RpcSsnData* RpcSsnDataNew(Packet*);
119 static inline void RpcSsnClean(RpcSsnData*);
120 static inline void RpcSsnSetInactive(RpcSsnData*, Packet*);
121 static inline int RpcSsnIsActive(RpcSsnData*);
122
123 static RpcStatus RpcStatefulInspection(RpcSsnData*, Packet*);
124 static inline void RpcPreprocEvent(RpcSsnData*, int);
125 static RpcStatus RpcHandleFrag(RpcSsnData*, const uint8_t*);
126 static RpcStatus RpcPrepRaw(const uint8_t*, uint32_t, Packet*);
127 static RpcStatus RpcPrepFrag(RpcSsnData*, Packet*);
128 static RpcStatus RpcPrepSeg(RpcSsnData*, Packet*);
129 static inline uint32_t RpcBufLen(RpcBuffer*);
130 static inline uint8_t* RpcBufData(RpcBuffer*);
131 static RpcStatus RpcBufAdd(RpcBuffer*, const uint8_t*, uint32_t);
132 static inline void RpcBufClean(RpcBuffer*);
133
RpcPreprocEvent(RpcSsnData * rsdata,int event)134 static inline void RpcPreprocEvent(RpcSsnData* rsdata, int event)
135 {
136 if (rsdata != nullptr)
137 {
138 /* Only log one event of the same type per session */
139 if (rsdata->events & (1 << event))
140 return;
141
142 rsdata->events |= (1 << event);
143 }
144
145 switch (event)
146 {
147 case RPC_FRAG_TRAFFIC:
148 DetectionEngine::queue_event(GID_RPC_DECODE, RPC_FRAG_TRAFFIC);
149 break;
150
151 case RPC_MULTIPLE_RECORD:
152 DetectionEngine::queue_event(GID_RPC_DECODE, RPC_MULTIPLE_RECORD);
153 break;
154
155 case RPC_LARGE_FRAGSIZE:
156 DetectionEngine::queue_event(GID_RPC_DECODE, RPC_LARGE_FRAGSIZE);
157 break;
158
159 case RPC_INCOMPLETE_SEGMENT:
160 DetectionEngine::queue_event(GID_RPC_DECODE, RPC_INCOMPLETE_SEGMENT);
161 break;
162
163 case RPC_ZERO_LENGTH_FRAGMENT:
164 DetectionEngine::queue_event(GID_RPC_DECODE, RPC_ZERO_LENGTH_FRAGMENT);
165 break;
166
167 default:
168 break;
169 }
170 }
171
RpcStatefulInspection(RpcSsnData * rsdata,Packet * p)172 static RpcStatus RpcStatefulInspection(RpcSsnData* rsdata, Packet* p)
173 {
174 const uint8_t* data = p->data;
175 uint16_t dsize = p->dsize;
176 int need;
177 RpcStatus status;
178
179 if (rsdata->ignore)
180 {
181 if (dsize < rsdata->ignore)
182 {
183 rsdata->ignore -= dsize;
184 return RPC_STATUS__SUCCESS;
185 }
186
187 dsize -= (uint16_t)rsdata->ignore;
188 data += rsdata->ignore;
189 rsdata->ignore = 0;
190 }
191
192 /* Might need to evaluate same packet, different decode buffer
193 * more than once and detection option tree won't let us do that
194 * by default */
195 p->packet_flags |= PKT_ALLOW_MULTIPLE_DETECT;
196
197 while (dsize > 0)
198 {
199 if (RpcBufLen(&rsdata->seg) == 0)
200 {
201 if (dsize < RPC_FRAG_HDR_SIZE)
202 {
203 RpcPreprocEvent(rsdata, RPC_INCOMPLETE_SEGMENT);
204
205 if (RpcBufAdd(&rsdata->seg, data, dsize) != RPC_STATUS__SUCCESS)
206 return RPC_STATUS__ERROR;
207
208 break;
209 }
210
211 rsdata->frag_len = RPC_FRAG_LEN(data);
212 if (dsize < (RPC_FRAG_HDR_SIZE + rsdata->frag_len))
213 {
214 RpcPreprocEvent(rsdata, RPC_INCOMPLETE_SEGMENT);
215
216 if (RpcBufAdd(&rsdata->seg, data, dsize) != RPC_STATUS__SUCCESS)
217 return RPC_STATUS__ERROR;
218
219 break;
220 }
221
222 dsize -= (RPC_FRAG_HDR_SIZE + rsdata->frag_len);
223
224 status = RpcHandleFrag(rsdata, data);
225
226 if (status == RPC_STATUS__ERROR)
227 return RPC_STATUS__ERROR;
228
229 if (status == RPC_STATUS__DEFRAG)
230 {
231 if ((dsize != 0) || (data != p->data))
232 {
233 /* Only do this if there is more than one fragment in
234 * the data we got */
235 if (RpcPrepRaw(data, rsdata->frag_len, p) != RPC_STATUS__SUCCESS)
236 return RPC_STATUS__ERROR;
237
238 DataBus::publish(PACKET_EVENT, p);
239 }
240
241 if ( (dsize > 0) )
242 RpcPreprocEvent(rsdata, RPC_MULTIPLE_RECORD);
243 }
244
245 data += (RPC_FRAG_HDR_SIZE + rsdata->frag_len);
246 }
247 else
248 {
249 if (RpcBufLen(&rsdata->seg) < RPC_FRAG_HDR_SIZE)
250 {
251 need = RPC_FRAG_HDR_SIZE - RpcBufLen(&rsdata->seg);
252 if (dsize < need)
253 {
254 RpcPreprocEvent(rsdata, RPC_INCOMPLETE_SEGMENT);
255
256 if (RpcBufAdd(&rsdata->seg, data, dsize) != RPC_STATUS__SUCCESS)
257 return RPC_STATUS__ERROR;
258
259 break;
260 }
261
262 if (RpcBufAdd(&rsdata->seg, data, need) != RPC_STATUS__SUCCESS)
263 return RPC_STATUS__ERROR;
264
265 data += need;
266 dsize -= need;
267
268 rsdata->frag_len = RPC_FRAG_LEN(RpcBufData(&rsdata->seg));
269 }
270
271 need = rsdata->frag_len - (RpcBufLen(&rsdata->seg) - RPC_FRAG_HDR_SIZE);
272 if (dsize < need)
273 {
274 RpcPreprocEvent(rsdata, RPC_INCOMPLETE_SEGMENT);
275
276 if (RpcBufAdd(&rsdata->seg, data, dsize) != RPC_STATUS__SUCCESS)
277 return RPC_STATUS__ERROR;
278
279 break;
280 }
281
282 if (RpcBufAdd(&rsdata->seg, data, need) != RPC_STATUS__SUCCESS)
283 return RPC_STATUS__ERROR;
284
285 data += need;
286 dsize -= need;
287
288 status = RpcHandleFrag(rsdata, RpcBufData(&rsdata->seg));
289
290 if (status == RPC_STATUS__ERROR)
291 return RPC_STATUS__ERROR;
292
293 if (status == RPC_STATUS__DEFRAG)
294 {
295 if (RpcBufLen(&rsdata->frag) != 0)
296 {
297 if (RpcPrepFrag(rsdata, p) != RPC_STATUS__SUCCESS)
298 return RPC_STATUS__ERROR;
299 }
300 else
301 {
302 if (RpcPrepSeg(rsdata, p) != RPC_STATUS__SUCCESS)
303 return RPC_STATUS__ERROR;
304 }
305
306 if ( (dsize > 0) )
307 RpcPreprocEvent(rsdata, RPC_MULTIPLE_RECORD);
308
309 DataBus::publish(PACKET_EVENT, p);
310 RpcBufClean(&rsdata->frag);
311 }
312
313 RpcBufClean(&rsdata->seg);
314 }
315 }
316
317 if (RpcBufLen(&rsdata->frag) != 0)
318 {
319 if (RpcPrepFrag(rsdata, p) != RPC_STATUS__SUCCESS)
320 return RPC_STATUS__ERROR;
321 }
322 else if (RpcBufLen(&rsdata->seg) != 0)
323 {
324 if (RpcPrepSeg(rsdata, p) != RPC_STATUS__SUCCESS)
325 return RPC_STATUS__ERROR;
326 }
327
328 return RPC_STATUS__SUCCESS;
329 }
330
RpcPrepRaw(const uint8_t * data,uint32_t fraglen,Packet * p)331 static RpcStatus RpcPrepRaw(const uint8_t* data, uint32_t fraglen, Packet* p)
332 {
333 DataBuffer& buf = DetectionEngine::get_alt_buffer(p);
334
335 if (RPC_FRAG_HDR_SIZE + fraglen > sizeof(buf.data))
336 return RPC_STATUS__ERROR;
337
338 memcpy_s(buf.data, sizeof(buf.data), data, RPC_FRAG_HDR_SIZE + fraglen);
339 buf.len = (RPC_FRAG_HDR_SIZE + fraglen);
340
341 return RPC_STATUS__SUCCESS;
342 }
343
RpcPrepFrag(RpcSsnData * rsdata,Packet * p)344 static RpcStatus RpcPrepFrag(RpcSsnData* rsdata, Packet* p)
345 {
346 DataBuffer& buf = DetectionEngine::get_alt_buffer(p);
347 uint32_t fraghdr = htonl(RpcBufLen(&rsdata->frag));
348
349 buf.data[0] = *((uint8_t*)&fraghdr);
350 buf.data[1] = *(((uint8_t*)&fraghdr) + 1);
351 buf.data[2] = *(((uint8_t*)&fraghdr) + 2);
352 buf.data[3] = *(((uint8_t*)&fraghdr) + 3);
353
354 buf.data[0] |= 0x80;
355
356 if (RpcBufLen(&rsdata->frag) > sizeof(buf.data) - 4)
357 {
358 RpcBufClean(&rsdata->frag);
359 return RPC_STATUS__ERROR;
360 }
361
362 memcpy_s(buf.data + 4, sizeof(buf.data) - 4,
363 RpcBufData(&rsdata->frag), RpcBufLen(&rsdata->frag));
364
365 if (RpcBufLen(&rsdata->frag) > RPC_MAX_BUF_SIZE)
366 RpcBufClean(&rsdata->frag);
367
368 buf.len = RpcBufLen(&rsdata->frag);
369
370 return RPC_STATUS__SUCCESS;
371 }
372
RpcPrepSeg(RpcSsnData * rsdata,Packet * p)373 static RpcStatus RpcPrepSeg(RpcSsnData* rsdata, Packet* p)
374 {
375 DataBuffer& buf = DetectionEngine::get_alt_buffer(p);
376
377 if (RpcBufLen(&rsdata->seg) > sizeof(buf.data))
378 {
379 RpcBufClean(&rsdata->seg);
380 return RPC_STATUS__ERROR;
381 }
382 memcpy_s(buf.data, sizeof(buf.data),
383 RpcBufData(&rsdata->seg), RpcBufLen(&rsdata->seg));
384
385 if (RpcBufLen(&rsdata->seg) > RPC_MAX_BUF_SIZE)
386 {
387 rsdata->ignore = (sizeof(uint32_t) + rsdata->frag_len) - RpcBufLen(&rsdata->seg);
388 RpcBufClean(&rsdata->seg);
389 }
390
391 buf.len = (uint16_t)RpcBufLen(&rsdata->seg);
392
393 return RPC_STATUS__SUCCESS;
394 }
395
RpcHandleFrag(RpcSsnData * rsdata,const uint8_t * fragment)396 static RpcStatus RpcHandleFrag(RpcSsnData* rsdata, const uint8_t* fragment)
397 {
398 int last_frag = fragment[0] & 0x80;
399 uint32_t frag_len = RPC_FRAG_LEN(fragment);
400
401 if (frag_len == 0)
402 RpcPreprocEvent(rsdata, RPC_ZERO_LENGTH_FRAGMENT);
403
404 if (!last_frag)
405 RpcPreprocEvent(rsdata, RPC_FRAG_TRAFFIC);
406
407 if ((RpcBufLen(&rsdata->frag) == 0) && last_frag)
408 return RPC_STATUS__DEFRAG;
409
410 if (RpcBufAdd(&rsdata->frag,
411 fragment + sizeof(uint32_t), frag_len) != RPC_STATUS__SUCCESS)
412 {
413 return RPC_STATUS__ERROR;
414 }
415
416 if (last_frag)
417 return RPC_STATUS__DEFRAG;
418
419 return RPC_STATUS__SUCCESS;
420 }
421
RpcBufLen(RpcBuffer * buf)422 static inline uint32_t RpcBufLen(RpcBuffer* buf)
423 {
424 return buf == nullptr ? 0 : buf->len;
425 }
426
RpcBufData(RpcBuffer * buf)427 static inline uint8_t* RpcBufData(RpcBuffer* buf)
428 {
429 return buf == nullptr ? nullptr : buf->data;
430 }
431
RpcBufAdd(RpcBuffer * buf,const uint8_t * data,uint32_t dsize)432 static RpcStatus RpcBufAdd(RpcBuffer* buf, const uint8_t* data, uint32_t dsize)
433 {
434 const uint32_t min_alloc = flush_size;
435 uint32_t alloc_size = dsize;
436
437 if (buf == nullptr)
438 return RPC_STATUS__ERROR;
439
440 if (dsize == 0)
441 return RPC_STATUS__SUCCESS;
442
443 if (alloc_size < min_alloc)
444 alloc_size = min_alloc;
445
446 if (buf->data == nullptr)
447 {
448 buf->data = (uint8_t*)snort_calloc(alloc_size);
449 buf->size = alloc_size;
450 }
451 else if ((buf->len + dsize) > buf->size)
452 {
453 uint32_t new_size = buf->len + alloc_size;
454 uint8_t* tmp = (uint8_t*)snort_calloc(new_size);
455
456 if (buf->len > new_size)
457 {
458 snort_free(buf->data);
459 buf->data = tmp;
460 buf->size = new_size;
461
462 RpcBufClean(buf);
463 return RPC_STATUS__ERROR;
464 }
465 memcpy_s(tmp, new_size, buf->data, buf->len);
466
467 snort_free(buf->data);
468 buf->data = tmp;
469 buf->size = new_size;
470 }
471
472 if (dsize > buf->size - buf->len)
473 {
474 RpcBufClean(buf);
475 return RPC_STATUS__ERROR;
476 }
477
478 memcpy_s(buf->data + buf->len, buf->size - buf->len, data, dsize);
479
480 buf->len += dsize;
481
482 return RPC_STATUS__SUCCESS;
483 }
484
RpcBufClean(RpcBuffer * buf)485 static inline void RpcBufClean(RpcBuffer* buf)
486 {
487 if (buf->data != nullptr)
488 {
489 snort_free(buf->data);
490 buf->data = nullptr;
491 }
492
493 buf->len = 0;
494 buf->size = 0;
495 }
496
RpcSsnSetInactive(RpcSsnData * rsdata,Packet *)497 static inline void RpcSsnSetInactive(RpcSsnData* rsdata, Packet*)
498 {
499 if (rsdata == nullptr)
500 return;
501
502 RpcSsnClean(rsdata);
503 }
504
RpcSsnIsActive(RpcSsnData * rsdata)505 static inline int RpcSsnIsActive(RpcSsnData* rsdata)
506 {
507 if (rsdata == nullptr)
508 return 0;
509 return rsdata->active;
510 }
511
RpcSsnClean(RpcSsnData * rsdata)512 static inline void RpcSsnClean(RpcSsnData* rsdata)
513 {
514 if (rsdata == nullptr)
515 return;
516
517 rsdata->active = 0;
518 rsdata->frag_len = 0;
519 rsdata->ignore = 0;
520 RpcBufClean(&rsdata->seg);
521 RpcBufClean(&rsdata->frag);
522 }
523
RpcFlowData()524 RpcFlowData::RpcFlowData() : FlowData(inspector_id)
525 {
526 memset(&session, 0, sizeof(session));
527 rdstats.concurrent_sessions++;
528 if(rdstats.max_concurrent_sessions < rdstats.concurrent_sessions)
529 rdstats.max_concurrent_sessions = rdstats.concurrent_sessions;
530 }
531
~RpcFlowData()532 RpcFlowData::~RpcFlowData()
533 {
534 RpcSsnClean(&session);
535 assert(rdstats.concurrent_sessions > 0);
536 rdstats.concurrent_sessions--;
537 }
538
RpcSsnDataNew(Packet * p)539 static RpcSsnData* RpcSsnDataNew(Packet* p)
540 {
541 RpcFlowData* fd = new RpcFlowData;
542 RpcSsnData* rsdata = &fd->session;
543 rsdata->active = 1;
544
545 p->flow->set_flow_data(fd);
546
547 return rsdata;
548 }
549
550 /* most significant bit */
551 #define MSB 0x80000000
552
553 /*
554 * For proto ref, see rfc1831 section 10 and page 445 UNP vol2
555 *
556 * check to make sure we've got enough data to process a record
557 *
558 * Where did the original 16 come from? It seems that it could be
559 * a last frag of 0 length according to spec.
560 *
561 * The minimum "valid" packet for us is 8 fields * 4 bytes
562 *
563 * This decoder is ignorant of TCP state so we'll have to assume
564 * that reassembled TCP stuff is reinjected to the inspector
565 * chain
566 *
567 * This decoder is also ignorant of multiple RPC requests in a
568 * single stream. To compensate, we can configure alerts
569 *
570 * Additionally, we don't do anything to verify that this is
571 * really an RPC service port so we don't decode anything that
572 * happens as a result
573 *
574 * From rfc1831:
575 *
576 * Fragment Header ( 1 flag bit, 31 bit uint )
577 * RPC Body
578 *
579 * unsigned int xid
580 * struct call_body {
581 * unsigned int rpcvers; // must be equal to two (2)
582 * unsigned int prog;
583 * unsigned int vers;
584 * unsigned int proc;
585 * opaque_auth cred;
586 * opaque_auth verf;
587 * }
588 */
589
590 #define MIN_CALL_BODY_SZ 32
591
ConvertRPC(RpcSsnData * rsdata,Packet * p)592 static int ConvertRPC(RpcSsnData* rsdata, Packet* p)
593 {
594 const uint8_t* data = p->data;
595 uint32_t psize = p->dsize;
596 uint8_t* norm_index;
597 const uint8_t* data_index; /* this is the index pointer to walk thru the data */
598 const uint8_t* data_end; /* points to the end of the payload for loop control */
599 uint32_t length; /* length of current fragment */
600 int last_fragment = 0; /* have we seen the last fragment sign? */
601 uint32_t decoded_len; /* our decoded length is always at least a 0 byte header */
602 uint32_t fraghdr; /* Used to store the RPC fragment header data */
603 int fragcount = 0; /* How many fragment counters have we seen? */
604
605 DataBuffer& buf = DetectionEngine::get_alt_buffer(p);
606 size_t decode_buf_rem = sizeof(buf.data);
607
608 if (psize < MIN_CALL_BODY_SZ)
609 {
610 return 0;
611 }
612
613 /* on match, normalize the data */
614
615 /* cheesy alignment safe fraghdr = *(uint32_t *) data*/
616 *((uint8_t*)&fraghdr) = data[0];
617 *(((uint8_t*)&fraghdr) + 1) = data[1];
618 *(((uint8_t*)&fraghdr) + 2) = data[2];
619 *(((uint8_t*)&fraghdr) + 3) = data[3];
620
621 /* The fragment header is 4 bytes in network byte order */
622 fraghdr = ntohl(fraghdr);
623 length = fraghdr & 0x7FFFFFFF;
624
625 /* Check to see if we are on the last fragment */
626 if (fraghdr & MSB)
627 {
628 /* on match, normalize the data */
629 if ((length + 4 != psize) && !(p->packet_flags & PKT_REBUILT_STREAM))
630 {
631 return RPC_MULTIPLE_RECORD;
632 }
633 else if ( length == 0 )
634 {
635 return RPC_ZERO_LENGTH_FRAGMENT;
636 }
637 return 0;
638 }
639 else
640 {
641 RpcPreprocEvent(rsdata, RPC_FRAG_TRAFFIC);
642 }
643
644 norm_index = buf.data;
645 data_index = (const uint8_t*)data;
646 data_end = (const uint8_t*)data + psize;
647
648 /* now we know it's in fragmented records, 4 bytes of
649 * header(of which the most sig bit fragment (0=yes 1=no).
650 * The header is followed by the value move pointer up 4
651 * bytes, we need to stuff header in first 4 bytes.
652 * But the header has the total length...we don't know
653 * until the end
654 */
655
656 /* This is where decoded data will be written */
657 norm_index += 4;
658 decoded_len = 4;
659 decode_buf_rem -= 4;
660
661 /* always make sure that we have enough data to process at least
662 * the header and that we only process at most, one fragment
663 */
664
665 while (((data_end - data_index) >= 4) && (last_fragment == 0))
666 {
667 /* get the fragment length (31 bits) and move the pointer to
668 the start of the actual data */
669
670 *((uint8_t*)&fraghdr) = data_index[0];
671 *(((uint8_t*)&fraghdr) + 1) = data_index[1];
672 *(((uint8_t*)&fraghdr) + 2) = data_index[2];
673 *(((uint8_t*)&fraghdr) + 3) = data_index[3];
674
675 fraghdr = ntohl(fraghdr);
676 length = fraghdr & 0x7FFFFFFF;
677
678 if (length == 0)
679 break;
680
681 /* move the current index into the packet past the
682 fragment header */
683 data_index += 4;
684
685 if (fraghdr & MSB)
686 {
687 last_fragment = 1;
688 }
689
690 if ((length + decoded_len) < decoded_len)
691 {
692 /* don't allow integer overflow to confuse us. Should be
693 * caught by length > psize but who knows when weird
694 * psize's might be allowed */
695 return RPC_LARGE_FRAGSIZE;
696 }
697
698 decoded_len += length;
699
700 if (length > psize)
701 {
702 return RPC_INCOMPLETE_SEGMENT;
703 }
704 else if (decoded_len > psize)
705 {
706 /* The entire request is larger than our current packet
707 * size
708 */
709 return RPC_LARGE_FRAGSIZE;
710 }
711 else if ((data_index + length) > data_end)
712 {
713 return RPC_LARGE_FRAGSIZE;
714 }
715 else
716 {
717 fragcount++;
718 if (decode_buf_rem >= length)
719 {
720 memcpy_s(norm_index, decode_buf_rem, data_index, length);
721
722 norm_index += length;
723 data_index += length;
724 decode_buf_rem -= length;
725 }
726 }
727 }
728
729 /* rewrite the header on the request packet
730 move the fragment header back onto the data */
731
732 fraghdr = ntohl(decoded_len); /* size */
733
734 buf.data[0] = *((uint8_t*)&fraghdr);
735 buf.data[1] = *(((uint8_t*)&fraghdr) + 1);
736 buf.data[2] = *(((uint8_t*)&fraghdr) + 2);
737 buf.data[3] = *(((uint8_t*)&fraghdr) + 3);
738
739 buf.data[0] |= 0x80; /* Mark as unfragmented */
740
741 /* is there another request encoded that is trying to evade us by doing
742 *
743 * frag last frag [ more data ]?
744 */
745 if (decoded_len + ((fragcount - 1) * 4) != psize)
746 {
747 return RPC_MULTIPLE_RECORD;
748 }
749
750 buf.len = (uint16_t)decoded_len;
751 return 0;
752 }
753
754 //-------------------------------------------------------------------------
755 // class stuff
756 //-------------------------------------------------------------------------
757
758 class RpcDecode : public Inspector
759 {
760 public:
761 RpcDecode(RpcDecodeModule*);
762
763 void eval(Packet*) override;
764 void clear(Packet*) override;
765
766 bool get_buf(InspectionBuffer::Type, Packet*, InspectionBuffer&) override;
767
get_splitter(bool c2s)768 StreamSplitter* get_splitter(bool c2s) override
769 { return c2s ? new LogSplitter(c2s) : nullptr; }
770 };
771
RpcDecode(RpcDecodeModule *)772 RpcDecode::RpcDecode(RpcDecodeModule*)
773 {
774 }
775
776 /*
777 * Purpose: Inspects the packet's payload for fragment records and
778 * converts them into one unfragmented record.
779 */
eval(Packet * p)780 void RpcDecode::eval(Packet* p)
781 {
782 Profile profile(rpcdecodePerfStats);
783
784 // preconditions - what we registered for
785 assert(p->has_tcp_data());
786
787 // If we're stateful that means stream has been configured.
788 // In this case we don't look at server packets.
789 // There is the case were stream configuration requires a 3 way handshake.
790 // If no 3 way, then the packet flags won't be set, so don't look at it
791 // since we won't be able to determine who's the client and who's the
792 // server.
793 if ( !p->is_from_client() )
794 return;
795
796 RpcSsnData* rsdata = nullptr;
797
798 if ( p->flow )
799 {
800 RpcFlowData* fd = (RpcFlowData*)p->flow->get_flow_data(RpcFlowData::inspector_id);
801
802 if ( fd )
803 rsdata = &fd->session;
804 }
805
806 ++rdstats.total_packets;
807
808 if ( !rsdata && p->flow && !Stream::is_midstream(p->flow) )
809 rsdata = RpcSsnDataNew(p);
810
811 if ( RpcSsnIsActive(rsdata) and (p->packet_flags & PKT_REBUILT_STREAM) )
812 {
813 RpcStatus ret = RpcStatefulInspection(rsdata, p);
814
815 if (ret == RPC_STATUS__SUCCESS)
816 return;
817
818 // Something went wrong - deactivate session tracking
819 // and decode normally
820 if (ret == RPC_STATUS__ERROR)
821 RpcSsnSetInactive(rsdata, p);
822 }
823 RpcPreprocEvent(rsdata, ConvertRPC(rsdata, p));
824 }
825
get_buf(InspectionBuffer::Type ibt,Packet * p,InspectionBuffer & b)826 bool RpcDecode::get_buf(InspectionBuffer::Type ibt, Packet* p, InspectionBuffer& b)
827 {
828 if ( ibt != InspectionBuffer::IBT_ALT )
829 return false;
830
831 const DataBuffer& buf = DetectionEngine::get_alt_buffer(p);
832 b.len = buf.len;
833 b.data = (b.len > 0) ? buf.data : nullptr;
834
835 return (b.data != nullptr);
836 }
837
clear(Packet * p)838 void RpcDecode::clear(Packet* p)
839 {
840 DataBuffer& buf = DetectionEngine::get_alt_buffer(p);
841 buf.len = 0;
842 }
843
844 //-------------------------------------------------------------------------
845 // api stuff
846 //-------------------------------------------------------------------------
847
mod_ctor()848 static Module* mod_ctor()
849 { return new RpcDecodeModule; }
850
mod_dtor(Module * m)851 static void mod_dtor(Module* m)
852 { delete m; }
853
rd_init()854 static void rd_init()
855 {
856 RpcFlowData::init();
857 }
858
rd_ctor(Module * m)859 static Inspector* rd_ctor(Module* m)
860 {
861 return new RpcDecode((RpcDecodeModule*)m);
862 }
863
rd_dtor(Inspector * p)864 static void rd_dtor(Inspector* p)
865 {
866 delete p;
867 }
868
869 static const InspectApi rd_api =
870 {
871 {
872 PT_INSPECTOR,
873 sizeof(InspectApi),
874 INSAPI_VERSION,
875 0,
876 API_RESERVED,
877 API_OPTIONS,
878 mod_name,
879 mod_help,
880 mod_ctor,
881 mod_dtor
882 },
883 IT_SERVICE,
884 PROTO_BIT__PDU,
885 nullptr, // buffers
886 "sunrpc",
887 rd_init,
888 nullptr, // pterm
889 nullptr, // tinit
890 nullptr, // tterm
891 rd_ctor,
892 rd_dtor,
893 nullptr, // ssn
894 nullptr // reset
895 };
896
897 #ifdef BUILDING_SO
898 SO_PUBLIC const BaseApi* snort_plugins[] =
899 {
900 &rd_api.base,
901 nullptr
902 };
903 #else
904 const BaseApi* sin_rpc_decode = &rd_api.base;
905 #endif
906
907