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