1 /* Copyright (C) 2015-2020 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /*
19  * TODO: Update \author in this file and app-layer-template.h.
20  * TODO: Implement your app-layer logic with unit tests.
21  * TODO: Remove SCLogNotice statements or convert to debug.
22  */
23 
24 /**
25  * \file
26  *
27  * \author FirstName LastName <yourname@domain>
28  *
29  * Template application layer detector and parser for learning and
30  * template pruposes.
31  *
32  * This template implements a simple application layer for something
33  * like the echo protocol running on port 7.
34  */
35 
36 #include "suricata-common.h"
37 #include "stream.h"
38 #include "conf.h"
39 #include "app-layer-detect-proto.h"
40 #include "app-layer-parser.h"
41 #include "app-layer-template.h"
42 
43 #include "util-unittest.h"
44 #include "util-validate.h"
45 
46 /* The default port to probe for echo traffic if not provided in the
47  * configuration file. */
48 #define TEMPLATE_DEFAULT_PORT "7"
49 
50 /* The minimum size for a message. For some protocols this might
51  * be the size of a header. */
52 #define TEMPLATE_MIN_FRAME_LEN 1
53 
54 /* Enum of app-layer events for the protocol. Normally you might
55  * have events for errors in parsing data, like unexpected data being
56  * received. For template we'll make something up, and log an app-layer
57  * level alert if an empty message is received.
58  *
59  * Example rule:
60  *
61  * alert template any any -> any any (msg:"SURICATA Template empty message"; \
62  *    app-layer-event:template.empty_message; sid:X; rev:Y;)
63  */
64 enum {
65     TEMPLATE_DECODER_EVENT_EMPTY_MESSAGE,
66 };
67 
68 SCEnumCharMap template_decoder_event_table[] = {
69     {"EMPTY_MESSAGE", TEMPLATE_DECODER_EVENT_EMPTY_MESSAGE},
70 
71     // event table must be NULL-terminated
72     { NULL, -1 },
73 };
74 
TemplateTxAlloc(TemplateState * state)75 static TemplateTransaction *TemplateTxAlloc(TemplateState *state)
76 {
77     TemplateTransaction *tx = SCCalloc(1, sizeof(TemplateTransaction));
78     if (unlikely(tx == NULL)) {
79         return NULL;
80     }
81 
82     /* Increment the transaction ID on the state each time one is
83      * allocated. */
84     tx->tx_id = state->transaction_max++;
85 
86     TAILQ_INSERT_TAIL(&state->tx_list, tx, next);
87 
88     return tx;
89 }
90 
TemplateTxFree(void * txv)91 static void TemplateTxFree(void *txv)
92 {
93     TemplateTransaction *tx = txv;
94 
95     if (tx->request_buffer != NULL) {
96         SCFree(tx->request_buffer);
97     }
98 
99     if (tx->response_buffer != NULL) {
100         SCFree(tx->response_buffer);
101     }
102 
103     AppLayerDecoderEventsFreeEvents(&tx->decoder_events);
104 
105     SCFree(tx);
106 }
107 
TemplateStateAlloc(void * orig_state,AppProto proto_orig)108 static void *TemplateStateAlloc(void *orig_state, AppProto proto_orig)
109 {
110     SCLogNotice("Allocating template state.");
111     TemplateState *state = SCCalloc(1, sizeof(TemplateState));
112     if (unlikely(state == NULL)) {
113         return NULL;
114     }
115     TAILQ_INIT(&state->tx_list);
116     return state;
117 }
118 
TemplateStateFree(void * state)119 static void TemplateStateFree(void *state)
120 {
121     TemplateState *template_state = state;
122     TemplateTransaction *tx;
123     SCLogNotice("Freeing template state.");
124     while ((tx = TAILQ_FIRST(&template_state->tx_list)) != NULL) {
125         TAILQ_REMOVE(&template_state->tx_list, tx, next);
126         TemplateTxFree(tx);
127     }
128     SCFree(template_state);
129 }
130 
131 /**
132  * \brief Callback from the application layer to have a transaction freed.
133  *
134  * \param state a void pointer to the TemplateState object.
135  * \param tx_id the transaction ID to free.
136  */
TemplateStateTxFree(void * statev,uint64_t tx_id)137 static void TemplateStateTxFree(void *statev, uint64_t tx_id)
138 {
139     TemplateState *state = statev;
140     TemplateTransaction *tx = NULL, *ttx;
141 
142     SCLogNotice("Freeing transaction %"PRIu64, tx_id);
143 
144     TAILQ_FOREACH_SAFE(tx, &state->tx_list, next, ttx) {
145 
146         /* Continue if this is not the transaction we are looking
147          * for. */
148         if (tx->tx_id != tx_id) {
149             continue;
150         }
151 
152         /* Remove and free the transaction. */
153         TAILQ_REMOVE(&state->tx_list, tx, next);
154         TemplateTxFree(tx);
155         return;
156     }
157 
158     SCLogNotice("Transaction %"PRIu64" not found.", tx_id);
159 }
160 
TemplateStateGetEventInfo(const char * event_name,int * event_id,AppLayerEventType * event_type)161 static int TemplateStateGetEventInfo(const char *event_name, int *event_id,
162     AppLayerEventType *event_type)
163 {
164     *event_id = SCMapEnumNameToValue(event_name, template_decoder_event_table);
165     if (*event_id == -1) {
166         SCLogError(SC_ERR_INVALID_ENUM_MAP, "event \"%s\" not present in "
167                    "template enum map table.",  event_name);
168         /* This should be treated as fatal. */
169         return -1;
170     }
171 
172     *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
173 
174     return 0;
175 }
176 
TemplateStateGetEventInfoById(int event_id,const char ** event_name,AppLayerEventType * event_type)177 static int TemplateStateGetEventInfoById(int event_id, const char **event_name,
178                                          AppLayerEventType *event_type)
179 {
180     *event_name = SCMapEnumValueToName(event_id, template_decoder_event_table);
181     if (*event_name == NULL) {
182         SCLogError(SC_ERR_INVALID_ENUM_MAP, "event \"%d\" not present in "
183                    "template enum map table.",  event_id);
184         /* This should be treated as fatal. */
185         return -1;
186     }
187 
188     *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
189 
190     return 0;
191 }
192 
TemplateGetEvents(void * tx)193 static AppLayerDecoderEvents *TemplateGetEvents(void *tx)
194 {
195     return ((TemplateTransaction *)tx)->decoder_events;
196 }
197 
198 /**
199  * \brief Probe the input to server to see if it looks like template.
200  *
201  * \retval ALPROTO_TEMPLATE if it looks like template,
202  *     ALPROTO_FAILED, if it is clearly not ALPROTO_TEMPLATE,
203  *     otherwise ALPROTO_UNKNOWN.
204  */
TemplateProbingParserTs(Flow * f,uint8_t direction,const uint8_t * input,uint32_t input_len,uint8_t * rdir)205 static AppProto TemplateProbingParserTs(Flow *f, uint8_t direction,
206         const uint8_t *input, uint32_t input_len, uint8_t *rdir)
207 {
208     /* Very simple test - if there is input, this is template. */
209     if (input_len >= TEMPLATE_MIN_FRAME_LEN) {
210         SCLogNotice("Detected as ALPROTO_TEMPLATE.");
211         return ALPROTO_TEMPLATE;
212     }
213 
214     SCLogNotice("Protocol not detected as ALPROTO_TEMPLATE.");
215     return ALPROTO_UNKNOWN;
216 }
217 
218 /**
219  * \brief Probe the input to client to see if it looks like template.
220  *     TemplateProbingParserTs can be used instead if the protocol
221  *     is symmetric.
222  *
223  * \retval ALPROTO_TEMPLATE if it looks like template,
224  *     ALPROTO_FAILED, if it is clearly not ALPROTO_TEMPLATE,
225  *     otherwise ALPROTO_UNKNOWN.
226  */
TemplateProbingParserTc(Flow * f,uint8_t direction,const uint8_t * input,uint32_t input_len,uint8_t * rdir)227 static AppProto TemplateProbingParserTc(Flow *f, uint8_t direction,
228         const uint8_t *input, uint32_t input_len, uint8_t *rdir)
229 {
230     /* Very simple test - if there is input, this is template. */
231     if (input_len >= TEMPLATE_MIN_FRAME_LEN) {
232         SCLogNotice("Detected as ALPROTO_TEMPLATE.");
233         return ALPROTO_TEMPLATE;
234     }
235 
236     SCLogNotice("Protocol not detected as ALPROTO_TEMPLATE.");
237     return ALPROTO_UNKNOWN;
238 }
239 
TemplateParseRequest(Flow * f,void * statev,AppLayerParserState * pstate,const uint8_t * input,uint32_t input_len,void * local_data,const uint8_t flags)240 static AppLayerResult TemplateParseRequest(Flow *f, void *statev,
241     AppLayerParserState *pstate, const uint8_t *input, uint32_t input_len,
242     void *local_data, const uint8_t flags)
243 {
244     TemplateState *state = statev;
245 
246     SCLogNotice("Parsing template request: len=%"PRIu32, input_len);
247 
248     if (input == NULL) {
249         if (AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TS)) {
250             /* This is a signal that the stream is done. Do any
251              * cleanup if needed. Usually nothing is required here. */
252             SCReturnStruct(APP_LAYER_OK);
253         } else if (flags & STREAM_GAP) {
254             /* This is a signal that there has been a gap in the
255              * stream. This only needs to be handled if gaps were
256              * enabled during protocol registration. The input_len
257              * contains the size of the gap. */
258             SCReturnStruct(APP_LAYER_OK);
259         }
260         /* This should not happen. If input is NULL, one of the above should be
261          * true. */
262         DEBUG_VALIDATE_BUG_ON(true);
263         SCReturnStruct(APP_LAYER_ERROR);
264     }
265 
266     /* Normally you would parse out data here and store it in the
267      * transaction object, but as this is echo, we'll just record the
268      * request data. */
269 
270     /* Also, if this protocol may have a "protocol data unit" span
271      * multiple chunks of data, which is always a possibility with
272      * TCP, you may need to do some buffering here.
273      *
274      * For the sake of simplicity, buffering is left out here, but
275      * even for an echo protocol we may want to buffer until a new
276      * line is seen, assuming its text based.
277      */
278 
279     /* Allocate a transaction.
280      *
281      * But note that if a "protocol data unit" is not received in one
282      * chunk of data, and the buffering is done on the transaction, we
283      * may need to look for the transaction that this newly recieved
284      * data belongs to.
285      */
286     TemplateTransaction *tx = TemplateTxAlloc(state);
287     if (unlikely(tx == NULL)) {
288         SCLogNotice("Failed to allocate new Template tx.");
289         goto end;
290     }
291     SCLogNotice("Allocated Template tx %"PRIu64".", tx->tx_id);
292 
293     /* Make a copy of the request. */
294     tx->request_buffer = SCCalloc(1, input_len);
295     if (unlikely(tx->request_buffer == NULL)) {
296         goto end;
297     }
298     memcpy(tx->request_buffer, input, input_len);
299     tx->request_buffer_len = input_len;
300 
301     /* Here we check for an empty message and create an app-layer
302      * event. */
303     if ((input_len == 1 && tx->request_buffer[0] == '\n') ||
304         (input_len == 2 && tx->request_buffer[0] == '\r')) {
305         SCLogNotice("Creating event for empty message.");
306         AppLayerDecoderEventsSetEventRaw(&tx->decoder_events,
307             TEMPLATE_DECODER_EVENT_EMPTY_MESSAGE);
308     }
309 
310 end:
311     SCReturnStruct(APP_LAYER_OK);
312 }
313 
TemplateParseResponse(Flow * f,void * statev,AppLayerParserState * pstate,const uint8_t * input,uint32_t input_len,void * local_data,const uint8_t flags)314 static AppLayerResult TemplateParseResponse(Flow *f, void *statev, AppLayerParserState *pstate,
315     const uint8_t *input, uint32_t input_len, void *local_data,
316     const uint8_t flags)
317 {
318     TemplateState *state = statev;
319     TemplateTransaction *tx = NULL, *ttx;
320 
321     SCLogNotice("Parsing Template response.");
322 
323     /* Likely connection closed, we can just return here. */
324     if ((input == NULL || input_len == 0) &&
325         AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TC)) {
326         SCReturnStruct(APP_LAYER_OK);
327     }
328 
329     /* Probably don't want to create a transaction in this case
330      * either. */
331     if (input == NULL || input_len == 0) {
332         SCReturnStruct(APP_LAYER_OK);
333     }
334 
335     /* Look up the existing transaction for this response. In the case
336      * of echo, it will be the most recent transaction on the
337      * TemplateState object. */
338 
339     /* We should just grab the last transaction, but this is to
340      * illustrate how you might traverse the transaction list to find
341      * the transaction associated with this response. */
342     TAILQ_FOREACH(ttx, &state->tx_list, next) {
343         tx = ttx;
344     }
345 
346     if (tx == NULL) {
347         SCLogNotice("Failed to find transaction for response on state %p.",
348             state);
349         goto end;
350     }
351 
352     SCLogNotice("Found transaction %"PRIu64" for response on state %p.",
353         tx->tx_id, state);
354 
355     /* If the protocol requires multiple chunks of data to complete, you may
356      * run into the case where you have existing response data.
357      *
358      * In this case, we just log that there is existing data and free it. But
359      * you might want to realloc the buffer and append the data.
360      */
361     if (tx->response_buffer != NULL) {
362         SCLogNotice("WARNING: Transaction already has response data, "
363             "existing data will be overwritten.");
364         SCFree(tx->response_buffer);
365     }
366 
367     /* Make a copy of the response. */
368     tx->response_buffer = SCCalloc(1, input_len);
369     if (unlikely(tx->response_buffer == NULL)) {
370         goto end;
371     }
372     memcpy(tx->response_buffer, input, input_len);
373     tx->response_buffer_len = input_len;
374 
375     /* Set the response_done flag for transaction state checking in
376      * TemplateGetStateProgress(). */
377     tx->response_done = 1;
378 
379 end:
380     SCReturnStruct(APP_LAYER_OK);
381 }
382 
TemplateGetTxCnt(void * statev)383 static uint64_t TemplateGetTxCnt(void *statev)
384 {
385     const TemplateState *state = statev;
386     SCLogNotice("Current tx count is %"PRIu64".", state->transaction_max);
387     return state->transaction_max;
388 }
389 
TemplateGetTx(void * statev,uint64_t tx_id)390 static void *TemplateGetTx(void *statev, uint64_t tx_id)
391 {
392     TemplateState *state = statev;
393     TemplateTransaction *tx;
394 
395     SCLogNotice("Requested tx ID %"PRIu64".", tx_id);
396 
397     TAILQ_FOREACH(tx, &state->tx_list, next) {
398         if (tx->tx_id == tx_id) {
399             SCLogNotice("Transaction %"PRIu64" found, returning tx object %p.",
400                 tx_id, tx);
401             return tx;
402         }
403     }
404 
405     SCLogNotice("Transaction ID %"PRIu64" not found.", tx_id);
406     return NULL;
407 }
408 
409 /**
410  * \brief Called by the application layer.
411  *
412  * In most cases 1 can be returned here.
413  */
TemplateGetAlstateProgressCompletionStatus(uint8_t direction)414 static int TemplateGetAlstateProgressCompletionStatus(uint8_t direction) {
415     return 1;
416 }
417 
418 /**
419  * \brief Return the state of a transaction in a given direction.
420  *
421  * In the case of the echo protocol, the existence of a transaction
422  * means that the request is done. However, some protocols that may
423  * need multiple chunks of data to complete the request may need more
424  * than just the existence of a transaction for the request to be
425  * considered complete.
426  *
427  * For the response to be considered done, the response for a request
428  * needs to be seen.  The response_done flag is set on response for
429  * checking here.
430  */
TemplateGetStateProgress(void * txv,uint8_t direction)431 static int TemplateGetStateProgress(void *txv, uint8_t direction)
432 {
433     TemplateTransaction *tx = txv;
434 
435     SCLogNotice("Transaction progress requested for tx ID %"PRIu64
436         ", direction=0x%02x", tx->tx_id, direction);
437 
438     if (direction & STREAM_TOCLIENT && tx->response_done) {
439         return 1;
440     }
441     else if (direction & STREAM_TOSERVER) {
442         /* For the template, just the existence of the transaction means the
443          * request is done. */
444         return 1;
445     }
446 
447     return 0;
448 }
449 
450 /**
451  * \brief retrieve the tx data used for logging, config, detection
452  */
TemplateGetTxData(void * vtx)453 static AppLayerTxData *TemplateGetTxData(void *vtx)
454 {
455     TemplateTransaction *tx = vtx;
456     return &tx->tx_data;
457 }
458 
459 /**
460  * \brief retrieve the detection engine per tx state
461  */
TemplateGetTxDetectState(void * vtx)462 static DetectEngineState *TemplateGetTxDetectState(void *vtx)
463 {
464     TemplateTransaction *tx = vtx;
465     return tx->de_state;
466 }
467 
468 /**
469  * \brief get the detection engine per tx state
470  */
TemplateSetTxDetectState(void * vtx,DetectEngineState * s)471 static int TemplateSetTxDetectState(void *vtx,
472     DetectEngineState *s)
473 {
474     TemplateTransaction *tx = vtx;
475     tx->de_state = s;
476     return 0;
477 }
478 
RegisterTemplateParsers(void)479 void RegisterTemplateParsers(void)
480 {
481     const char *proto_name = "template";
482 
483     /* TEMPLATE_START_REMOVE */
484     if (ConfGetNode("app-layer.protocols.template") == NULL) {
485         return;
486     }
487     /* TEMPLATE_END_REMOVE */
488     /* Check if Template TCP detection is enabled. If it does not exist in
489      * the configuration file then it will be enabled by default. */
490     if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) {
491 
492         SCLogNotice("Template TCP protocol detection enabled.");
493 
494         AppLayerProtoDetectRegisterProtocol(ALPROTO_TEMPLATE, proto_name);
495 
496         if (RunmodeIsUnittests()) {
497 
498             SCLogNotice("Unittest mode, registeringd default configuration.");
499             AppLayerProtoDetectPPRegister(IPPROTO_TCP, TEMPLATE_DEFAULT_PORT,
500                 ALPROTO_TEMPLATE, 0, TEMPLATE_MIN_FRAME_LEN, STREAM_TOSERVER,
501                 TemplateProbingParserTs, TemplateProbingParserTc);
502 
503         }
504         else {
505 
506             if (!AppLayerProtoDetectPPParseConfPorts("tcp", IPPROTO_TCP,
507                     proto_name, ALPROTO_TEMPLATE, 0, TEMPLATE_MIN_FRAME_LEN,
508                     TemplateProbingParserTs, TemplateProbingParserTc)) {
509                 SCLogNotice("No template app-layer configuration, enabling echo"
510                     " detection TCP detection on port %s.",
511                     TEMPLATE_DEFAULT_PORT);
512                 AppLayerProtoDetectPPRegister(IPPROTO_TCP,
513                     TEMPLATE_DEFAULT_PORT, ALPROTO_TEMPLATE, 0,
514                     TEMPLATE_MIN_FRAME_LEN, STREAM_TOSERVER,
515                     TemplateProbingParserTs, TemplateProbingParserTc);
516             }
517 
518         }
519 
520     }
521 
522     else {
523         SCLogNotice("Protocol detecter and parser disabled for Template.");
524         return;
525     }
526 
527     if (AppLayerParserConfParserEnabled("tcp", proto_name)) {
528 
529         SCLogNotice("Registering Template protocol parser.");
530 
531         /* Register functions for state allocation and freeing. A
532          * state is allocated for every new Template flow. */
533         AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_TEMPLATE,
534             TemplateStateAlloc, TemplateStateFree);
535 
536         /* Register request parser for parsing frame from server to client. */
537         AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_TEMPLATE,
538             STREAM_TOSERVER, TemplateParseRequest);
539 
540         /* Register response parser for parsing frames from server to client. */
541         AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_TEMPLATE,
542             STREAM_TOCLIENT, TemplateParseResponse);
543 
544         /* Register a function to be called by the application layer
545          * when a transaction is to be freed. */
546         AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_TEMPLATE,
547             TemplateStateTxFree);
548 
549         /* Register a function to return the current transaction count. */
550         AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_TEMPLATE,
551             TemplateGetTxCnt);
552 
553         /* Transaction handling. */
554         AppLayerParserRegisterGetStateProgressCompletionStatus(ALPROTO_TEMPLATE,
555             TemplateGetAlstateProgressCompletionStatus);
556         AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP,
557             ALPROTO_TEMPLATE, TemplateGetStateProgress);
558         AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_TEMPLATE,
559             TemplateGetTx);
560         AppLayerParserRegisterTxDataFunc(IPPROTO_TCP, ALPROTO_TEMPLATE,
561             TemplateGetTxData);
562 
563         /* What is this being registered for? */
564         AppLayerParserRegisterDetectStateFuncs(IPPROTO_TCP, ALPROTO_TEMPLATE,
565             TemplateGetTxDetectState, TemplateSetTxDetectState);
566 
567         AppLayerParserRegisterGetEventInfo(IPPROTO_TCP, ALPROTO_TEMPLATE,
568             TemplateStateGetEventInfo);
569         AppLayerParserRegisterGetEventInfoById(IPPROTO_TCP, ALPROTO_TEMPLATE,
570             TemplateStateGetEventInfoById);
571         AppLayerParserRegisterGetEventsFunc(IPPROTO_TCP, ALPROTO_TEMPLATE,
572             TemplateGetEvents);
573 
574         /* Leave this is if you parser can handle gaps, otherwise
575          * remove. */
576         AppLayerParserRegisterOptionFlags(IPPROTO_TCP, ALPROTO_TEMPLATE,
577             APP_LAYER_PARSER_OPT_ACCEPT_GAPS);
578     }
579     else {
580         SCLogNotice("Template protocol parsing disabled.");
581     }
582 
583 #ifdef UNITTESTS
584     AppLayerParserRegisterProtocolUnittests(IPPROTO_TCP, ALPROTO_TEMPLATE,
585         TemplateParserRegisterTests);
586 #endif
587 }
588 
589 #ifdef UNITTESTS
590 #endif
591 
TemplateParserRegisterTests(void)592 void TemplateParserRegisterTests(void)
593 {
594 #ifdef UNITTESTS
595 #endif
596 }
597