suricata
app-layer-dnp3.c
Go to the documentation of this file.
1/* Copyright (C) 2015-2025 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18/**
19 * \file
20 *
21 * DNP3 protocol implementation
22 */
23
24#include "suricata-common.h"
25#include "suricata.h"
26#include "util-unittest.h"
27
28#include "util-spm-bs.h"
29#include "util-enum.h"
30
31#include "app-layer.h"
32#include "app-layer-protos.h"
33#include "app-layer-parser.h"
35#include "app-layer-events.h"
36
37#include "app-layer-dnp3.h"
39
40/* Default number of unreplied requests to be considered a flood. */
41#define DNP3_DEFAULT_REQ_FLOOD_COUNT 500
42
43#define DNP3_DEFAULT_PORT "20000"
44
45/* Expected values for the start bytes. */
46#define DNP3_START_BYTE0 0x05
47#define DNP3_START_BYTE1 0x64
48
49/* Minimum length for a DNP3 frame. */
50#define DNP3_MIN_LEN 5
51
52/* Length of each CRC. */
53#define DNP3_CRC_LEN 2
54
55/* DNP3 block size. After the link header a CRC is inserted after
56 * after 16 bytes of data. */
57#define DNP3_BLOCK_SIZE 16
58
59/* Maximum transport layer sequence number. */
60#define DNP3_MAX_TRAN_SEQNO 64
61
62/* Maximum application layer sequence number. */
63// unused #define DNP3_MAX_APP_SEQNO 16
64
65/* The number of bytes in the header that are counted as part of the
66 * header length field. */
67#define DNP3_LINK_HDR_LEN 5
68
69/* Link function codes. */
70enum {
73};
74
75/* Reserved addresses. */
76// unused #define DNP3_RESERVED_ADDR_MIN 0xfff0
77// unused #define DNP3_RESERVED_ADDR_MAX 0xfffb
78
79/* Source addresses must be < 0xfff0. */
80// unused #define DNP3_SRC_ADDR_MAX 0xfff0
81
82/* Extract the prefix code from the object qualifier. */
83#define DNP3_OBJ_PREFIX(x) ((x >> 4) & 0x7)
84
85/* Extract the range code from the object qualifier. */
86#define DNP3_OBJ_RANGE(x) (x & 0xf)
87
88/* Decoder event map. */
90 {"FLOODED", DNP3_DECODER_EVENT_FLOODED},
91 {"LEN_TOO_SMALL", DNP3_DECODER_EVENT_LEN_TOO_SMALL},
92 {"BAD_LINK_CRC", DNP3_DECODER_EVENT_BAD_LINK_CRC},
93 {"BAD_TRANSPORT_CRC", DNP3_DECODER_EVENT_BAD_TRANSPORT_CRC},
94 {"MALFORMED", DNP3_DECODER_EVENT_MALFORMED},
95 {"UNKNOWN_OBJECT", DNP3_DECODER_EVENT_UNKNOWN_OBJECT},
96 {NULL, -1},
97};
98
99/* Calculate the next transport sequence number. */
100#define NEXT_TH_SEQNO(current) ((current + 1) % DNP3_MAX_TRAN_SEQNO)
101
102/* CRC table generated by pycrc - http://github.com/tpircher/pycrc.
103 * - Polynomial: 0x3d65. */
104static const uint16_t crc_table[256] = {
105 0x0000, 0x365e, 0x6cbc, 0x5ae2, 0xd978, 0xef26, 0xb5c4, 0x839a,
106 0xff89, 0xc9d7, 0x9335, 0xa56b, 0x26f1, 0x10af, 0x4a4d, 0x7c13,
107 0xb26b, 0x8435, 0xded7, 0xe889, 0x6b13, 0x5d4d, 0x07af, 0x31f1,
108 0x4de2, 0x7bbc, 0x215e, 0x1700, 0x949a, 0xa2c4, 0xf826, 0xce78,
109 0x29af, 0x1ff1, 0x4513, 0x734d, 0xf0d7, 0xc689, 0x9c6b, 0xaa35,
110 0xd626, 0xe078, 0xba9a, 0x8cc4, 0x0f5e, 0x3900, 0x63e2, 0x55bc,
111 0x9bc4, 0xad9a, 0xf778, 0xc126, 0x42bc, 0x74e2, 0x2e00, 0x185e,
112 0x644d, 0x5213, 0x08f1, 0x3eaf, 0xbd35, 0x8b6b, 0xd189, 0xe7d7,
113 0x535e, 0x6500, 0x3fe2, 0x09bc, 0x8a26, 0xbc78, 0xe69a, 0xd0c4,
114 0xacd7, 0x9a89, 0xc06b, 0xf635, 0x75af, 0x43f1, 0x1913, 0x2f4d,
115 0xe135, 0xd76b, 0x8d89, 0xbbd7, 0x384d, 0x0e13, 0x54f1, 0x62af,
116 0x1ebc, 0x28e2, 0x7200, 0x445e, 0xc7c4, 0xf19a, 0xab78, 0x9d26,
117 0x7af1, 0x4caf, 0x164d, 0x2013, 0xa389, 0x95d7, 0xcf35, 0xf96b,
118 0x8578, 0xb326, 0xe9c4, 0xdf9a, 0x5c00, 0x6a5e, 0x30bc, 0x06e2,
119 0xc89a, 0xfec4, 0xa426, 0x9278, 0x11e2, 0x27bc, 0x7d5e, 0x4b00,
120 0x3713, 0x014d, 0x5baf, 0x6df1, 0xee6b, 0xd835, 0x82d7, 0xb489,
121 0xa6bc, 0x90e2, 0xca00, 0xfc5e, 0x7fc4, 0x499a, 0x1378, 0x2526,
122 0x5935, 0x6f6b, 0x3589, 0x03d7, 0x804d, 0xb613, 0xecf1, 0xdaaf,
123 0x14d7, 0x2289, 0x786b, 0x4e35, 0xcdaf, 0xfbf1, 0xa113, 0x974d,
124 0xeb5e, 0xdd00, 0x87e2, 0xb1bc, 0x3226, 0x0478, 0x5e9a, 0x68c4,
125 0x8f13, 0xb94d, 0xe3af, 0xd5f1, 0x566b, 0x6035, 0x3ad7, 0x0c89,
126 0x709a, 0x46c4, 0x1c26, 0x2a78, 0xa9e2, 0x9fbc, 0xc55e, 0xf300,
127 0x3d78, 0x0b26, 0x51c4, 0x679a, 0xe400, 0xd25e, 0x88bc, 0xbee2,
128 0xc2f1, 0xf4af, 0xae4d, 0x9813, 0x1b89, 0x2dd7, 0x7735, 0x416b,
129 0xf5e2, 0xc3bc, 0x995e, 0xaf00, 0x2c9a, 0x1ac4, 0x4026, 0x7678,
130 0x0a6b, 0x3c35, 0x66d7, 0x5089, 0xd313, 0xe54d, 0xbfaf, 0x89f1,
131 0x4789, 0x71d7, 0x2b35, 0x1d6b, 0x9ef1, 0xa8af, 0xf24d, 0xc413,
132 0xb800, 0x8e5e, 0xd4bc, 0xe2e2, 0x6178, 0x5726, 0x0dc4, 0x3b9a,
133 0xdc4d, 0xea13, 0xb0f1, 0x86af, 0x0535, 0x336b, 0x6989, 0x5fd7,
134 0x23c4, 0x159a, 0x4f78, 0x7926, 0xfabc, 0xcce2, 0x9600, 0xa05e,
135 0x6e26, 0x5878, 0x029a, 0x34c4, 0xb75e, 0x8100, 0xdbe2, 0xedbc,
136 0x91af, 0xa7f1, 0xfd13, 0xcb4d, 0x48d7, 0x7e89, 0x246b, 0x1235
137};
138
139/**
140 * \brief Compute the CRC for a buffer.
141 *
142 * \param buf Buffer to create CRC from.
143 * \param len Length of buffer (number of bytes to use for CRC).
144
145 */
146static uint16_t DNP3ComputeCRC(const uint8_t *buf, uint32_t len)
147{
148 const uint8_t *byte = buf;
149 uint16_t crc = 0;
150 int idx;
151
152 while (len--) {
153 idx = (crc ^ *byte) & 0xff;
154 crc = (crc_table[idx] ^ (crc >> 8)) & 0xffff;
155 byte++;
156 }
157
158 return ~crc & 0xffff;
159}
160
161/**
162 * \brief Check the CRC of a block.
163 *
164 * \param block The block of data with CRC to be checked.
165 * \param len The size of the data block.
166 *
167 * \retval 1 if CRC is OK, otherwise 0.
168 */
169static int DNP3CheckCRC(const uint8_t *block, uint32_t len)
170{
171#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
172 return 1;
173#endif
174 uint32_t crc_offset;
175 uint16_t crc;
176
177 /* Need at least one byte plus the CRC. */
178 if (len < DNP3_CRC_LEN + 1) {
179 return 0;
180 }
181
182 crc_offset = len - DNP3_CRC_LEN;
183 crc = DNP3ComputeCRC(block, len - DNP3_CRC_LEN);
184 if (((crc & 0xff) == block[crc_offset]) &&
185 ((crc >> 8) == block[crc_offset + 1])) {
186 return 1;
187 }
188
189 return 0;
190}
191
192/**
193 * \brief Check the CRC of the link header.
194 *
195 * \param header Point to the link header.
196 *
197 * \retval 1 if header CRC is OK, otherwise 0.
198 */
199static int DNP3CheckLinkHeaderCRC(const DNP3LinkHeader *header)
200{
201 return DNP3CheckCRC((uint8_t *)header, sizeof(DNP3LinkHeader));
202}
203
204/**
205 * \brief Check user data CRCs.
206 *
207 * \param data Pointer to user data.
208 * \param len Length of user data.
209 *
210 * \retval 1 if CRCs are OK, otherwise 0.
211 */
212static int DNP3CheckUserDataCRCs(const uint8_t *data, uint32_t len)
213{
214 uint32_t offset = 0;
215 uint32_t block_size;
216
217 while (offset < len) {
219 block_size = DNP3_BLOCK_SIZE + DNP3_CRC_LEN;
220 }
221 else {
222 block_size = len - offset;
223 }
224
225 if (!DNP3CheckCRC(data + offset, block_size)) {
226 /* Once failed, may as well return immediately. */
227 return 0;
228 }
229
230 offset += block_size;
231 }
232
233 return 1;
234}
235
236/**
237 * \brief Check the DNP3 frame start bytes.
238 *
239 * \retval 1 if valid, 0 if not.
240 */
241static int DNP3CheckStartBytes(const DNP3LinkHeader *header)
242{
243 return header->start_byte0 == DNP3_START_BYTE0 &&
244 header->start_byte1 == DNP3_START_BYTE1;
245}
246
247/* Some DNP3 servers start with a banner. */
248#define DNP3_BANNER "DNP3"
249
250/**
251 * \brief Check if a frame contains a banner.
252 *
253 * Some servers (outstations) appear to send back a banner that fails
254 * the normal frame checks. So first check for a banner.
255 *
256 * \retval 1 if a banner is found, 0 if not.
257 */
258static int DNP3ContainsBanner(const uint8_t *input, uint32_t len)
259{
260 return BasicSearch(input, len, (uint8_t *)DNP3_BANNER, strlen(DNP3_BANNER)) != NULL;
261}
262
263/**
264 * \brief DNP3 probing parser.
265 */
266static uint16_t DNP3ProbingParser(
267 const Flow *f, uint8_t direction, const uint8_t *input, uint32_t len, uint8_t *rdir)
268{
269 const DNP3LinkHeader *const hdr = (const DNP3LinkHeader *)input;
270 const bool toserver = (direction & STREAM_TOSERVER) != 0;
271
272 /* May be a banner. */
273 if (DNP3ContainsBanner(input, len)) {
274 SCLogDebug("Packet contains a DNP3 banner.");
275 bool is_banner = true;
276 // magic 0x100 = 256 seems good enough
277 for (uint32_t i = 0; i < len && i < 0x100; i++) {
278 if (!isprint(input[i])) {
279 is_banner = false;
280 break;
281 }
282 }
283 if (is_banner) {
284 if (toserver) {
285 *rdir = STREAM_TOCLIENT;
286 }
287 return ALPROTO_DNP3;
288 }
289 }
290
291 /* Check that we have the minimum amount of bytes. */
292 if (len < sizeof(DNP3LinkHeader)) {
293 SCLogDebug("Length too small to be a DNP3 header.");
294 return ALPROTO_UNKNOWN;
295 }
296
297 /* Verify start value (from AN2013-004b). */
298 if (!DNP3CheckStartBytes(hdr)) {
299 SCLogDebug("Invalid start bytes.");
300 return ALPROTO_FAILED;
301 }
302
303 /* Verify minimum length. */
304 if (hdr->len < DNP3_MIN_LEN) {
305 SCLogDebug("Packet too small to be a valid DNP3 fragment.");
306 return ALPROTO_FAILED;
307 }
308
309 // Test compatibility between direction and dnp3.ctl.direction
310 if ((DNP3_LINK_DIR(hdr->control) != 0) != toserver) {
311 *rdir = toserver ? STREAM_TOCLIENT : STREAM_TOSERVER;
312 }
313 SCLogDebug("Detected DNP3.");
314 return ALPROTO_DNP3;
315}
316
317/**
318 * \brief Calculate the length of the transport layer with CRCs removed.
319 *
320 * \param input_len The length of the transport layer buffer.
321 *
322 * \retval The length of the buffer after CRCs are removed.
323 */
324static int DNP3CalculateTransportLengthWithoutCRCs(uint32_t input_len)
325{
326 /* Too small. */
327 if (input_len < DNP3_CRC_LEN) {
328 return -1;
329 }
330
331 /* Get the number of complete blocks. */
332 int blocks = input_len / (DNP3_BLOCK_SIZE + DNP3_CRC_LEN);
333
334 /* And the number of bytes in the last block. */
335 int rem = input_len - (blocks * (DNP3_BLOCK_SIZE + DNP3_CRC_LEN));
336
337 if (rem) {
338 if (rem < DNP3_CRC_LEN) {
339 return -1;
340 }
341 return (blocks * DNP3_BLOCK_SIZE) + (rem - DNP3_CRC_LEN);
342 }
343 else {
344 return (blocks * DNP3_BLOCK_SIZE);
345 }
346}
347
348/**
349 * \brief Reassemble the application layer by stripping the CRCs.
350 *
351 * Remove the CRCs from the user data blocks. The output is the user
352 * data with the CRCs removed as well as the transport header removed,
353 * but the input data still needs to include the transport header as
354 * its part of the first user data block.
355 *
356 * If the output length passed in is non-null, the new input data will
357 * be appended, and the output length pointer incremented as needed.
358 *
359 * \param input Input buffer starting at the transport header (which
360 * will be removed from the output).
361 * \param input_len Length of the input buffer.
362 * \param output Pointer to output buffer (may be realloc'd).
363 * \param output_len Pointer to output length.
364 *
365 * \retval 1 if reassembly was successful, otherwise 0.
366 */
367static int DNP3ReassembleApplicationLayer(const uint8_t *input,
368 uint32_t input_len, uint8_t **output, uint32_t *output_len)
369{
370 int len = DNP3CalculateTransportLengthWithoutCRCs(input_len);
371
372 if (len <= 0) {
373 return 0;
374 }
375
376 /* Remove one byte for the transport header and make sure we have
377 * at least one byte of user data. */
378 if (--len < 1) {
379 return 0;
380 }
381
382 if (*output == NULL) {
383 *output = SCCalloc(1, len);
384 if (unlikely(*output == NULL)) {
385 return 0;
386 }
387 }
388 else {
389 uint8_t *ptr = SCRealloc(*output, (size_t)(*output_len + len));
390 if (unlikely(ptr == NULL)) {
391 return 0;
392 }
393 *output = ptr;
394 }
395
396 int offset = 0, block_size;
397 while ((uint32_t)offset < input_len) {
398 if (input_len - offset > DNP3_BLOCK_SIZE + DNP3_CRC_LEN) {
399 block_size = DNP3_BLOCK_SIZE + DNP3_CRC_LEN;
400 }
401 else {
402 block_size = input_len - offset;
403 }
404
405 /* If handling the first block (offset is 0), trim off the
406 * first byte which is the transport header, and not part of
407 * the application data. */
408 if (offset == 0) {
409 offset++;
410 block_size--;
411 }
412
413 /* Need at least 3 bytes to continue. One for application
414 * data, and 2 for the CRC. If not, return failure for
415 * malformed frame. */
416 if (block_size < DNP3_CRC_LEN + 1) {
417 SCLogDebug("Not enough data to continue.");
418 return 0;
419 }
420
421 /* Make sure there is enough space to write into. */
422 if (block_size - DNP3_CRC_LEN > len) {
423 SCLogDebug("Not enough data to continue.");
424 return 0;
425 }
426
427 memcpy(*output + *output_len, input + offset,
428 block_size - DNP3_CRC_LEN);
429 *output_len += block_size - DNP3_CRC_LEN;
430 offset += block_size;
431 len -= block_size - DNP3_CRC_LEN;
432 }
433
434 return 1;
435}
436
437/**
438 * \brief Allocate a DNP3 state object.
439 *
440 * The DNP3 state object represents a single DNP3 TCP session.
441 */
442static void *DNP3StateAlloc(void *orig_state, AppProto proto_orig)
443{
444 SCEnter();
445 DNP3State *dnp3;
446
447 dnp3 = (DNP3State *)SCCalloc(1, sizeof(DNP3State));
448 if (unlikely(dnp3 == NULL)) {
449 return NULL;
450 }
451 TAILQ_INIT(&dnp3->tx_list);
452
453 SCReturnPtr(dnp3, "void");
454}
455
456/**
457 * \brief Set a DNP3 application layer event.
458 *
459 * Sets an event on the current transaction object.
460 */
461static void DNP3SetEvent(DNP3State *dnp3, uint8_t event)
462{
463 if (dnp3 && dnp3->curr) {
464 AppLayerDecoderEventsSetEventRaw(&dnp3->curr->tx_data.events, event);
465 dnp3->events++;
466 }
467 else {
468 SCLogWarning("Failed to set event, state or tx pointer was NULL.");
469 }
470}
471
472/**
473 * \brief Set a DNP3 application layer event on a transaction.
474 */
475static void DNP3SetEventTx(DNP3Transaction *tx, uint8_t event)
476{
477 AppLayerDecoderEventsSetEventRaw(&tx->tx_data.events, event);
478 tx->dnp3->events++;
479}
480
481/**
482 * \brief Allocation a DNP3 transaction.
483 */
484static DNP3Transaction *DNP3TxAlloc(DNP3State *dnp3, bool request)
485{
486 DNP3Transaction *tx = SCCalloc(1, sizeof(DNP3Transaction));
487 if (unlikely(tx == NULL)) {
488 return NULL;
489 }
490 dnp3->transaction_max++;
491 dnp3->unreplied++;
492 dnp3->curr = tx;
493 tx->dnp3 = dnp3;
494 tx->tx_num = dnp3->transaction_max;
495 tx->is_request = request;
496 if (tx->is_request) {
498 } else {
500 }
501 TAILQ_INIT(&tx->objects);
502 TAILQ_INSERT_TAIL(&dnp3->tx_list, tx, next);
503
504 /* Check for flood state. */
506 DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_FLOODED);
507 dnp3->flooded = 1;
508 }
509
510 return tx;
511}
512
513/**
514 * \brief Calculate the length of a link frame with CRCs.
515 *
516 * This is required as the length parameter in the DNP3 header does not
517 * include the added CRCs.
518 *
519 * \param length The length from the DNP3 link header.
520 *
521 * \retval The length of the frame with CRCs included or 0 if the length isn't
522 * long enough to be a valid DNP3 frame.
523 */
524static uint32_t DNP3CalculateLinkLength(uint8_t length)
525{
526 uint32_t frame_len = 0;
527 int rem;
528
529 /* Fail early if the length is less than the minimum size. */
530 if (length < DNP3_LINK_HDR_LEN) {
531 return 0;
532 }
533
534 /* Subtract the 5 bytes of the header that are included in the
535 * length. */
536 length -= DNP3_LINK_HDR_LEN;
537
538 rem = length % DNP3_BLOCK_SIZE;
539 frame_len = (length / DNP3_BLOCK_SIZE) * (DNP3_BLOCK_SIZE + DNP3_CRC_LEN);
540 if (rem) {
541 frame_len += rem + DNP3_CRC_LEN;
542 }
543
544 return frame_len + sizeof(DNP3LinkHeader);
545}
546
547/**
548 * \brief Check if the link function code specifies user data.
549 *
550 * \param header Point to link header.
551 *
552 * \retval 1 if frame contains user data, otherwise 0.
553 */
554static int DNP3IsUserData(const DNP3LinkHeader *header)
555{
556 switch (DNP3_LINK_FC(header->control)) {
559 return 1;
560 default:
561 return 0;
562 }
563}
564
565/**
566 * \brief Check if the frame has user data.
567 *
568 * Check if the DNP3 frame actually has user data by checking if data
569 * exists after the headers.
570 *
571 * \retval 1 if user data exists, otherwise 0.
572 */
573static int DNP3HasUserData(const DNP3LinkHeader *header, uint8_t direction)
574{
575 if (direction == STREAM_TOSERVER) {
576 return header->len >= DNP3_LINK_HDR_LEN + sizeof(DNP3TransportHeader) +
577 sizeof(DNP3ApplicationHeader);
578 }
579 else {
580 return header->len >= DNP3_LINK_HDR_LEN + sizeof(DNP3TransportHeader) +
581 sizeof(DNP3ApplicationHeader) + sizeof(DNP3InternalInd);
582 }
583}
584
585/**
586 * \brief Reset a DNP3Buffer.
587 */
588static void DNP3BufferReset(DNP3Buffer *buffer)
589{
590 buffer->offset = 0;
591 buffer->len = 0;
592}
593
594/**
595 * \brief Add data to a DNP3 buffer, enlarging the buffer if required.
596 *
597 * \param buffer Buffer to add data data.
598 * \param data Data to be added to buffer.
599 * \param len Size of data to be added to buffer.
600 *
601 * \param 1 if data was added successful, otherwise 0.
602 */
603static int DNP3BufferAdd(DNP3Buffer *buffer, const uint8_t *data, uint32_t len)
604{
605 if (buffer->size == 0) {
606 buffer->buffer = SCCalloc(1, len);
607 if (unlikely(buffer->buffer == NULL)) {
608 return 0;
609 }
610 buffer->size = len;
611 }
612 else if (buffer->len + len > buffer->size) {
613 uint8_t *tmp = SCRealloc(buffer->buffer, buffer->len + len);
614 if (unlikely(tmp == NULL)) {
615 return 0;
616 }
617 buffer->buffer = tmp;
618 buffer->size = buffer->len + len;
619 }
620 memcpy(buffer->buffer + buffer->len, data, len);
621 buffer->len += len;
622
623 return 1;
624}
625
626/**
627 * \brief Trim a DNP3 buffer.
628 *
629 * Trimming a buffer moves the data in the buffer up to the front of
630 * the buffer freeing up room at the end for more incoming data.
631 *
632 * \param buffer The buffer to trim.
633 */
634static void DNP3BufferTrim(DNP3Buffer *buffer)
635{
636 if (buffer->offset == buffer->len) {
637 DNP3BufferReset(buffer);
638 }
639 else if (buffer->offset > 0) {
640 memmove(buffer->buffer, buffer->buffer + buffer->offset,
641 buffer->len - buffer->offset);
642 buffer->len = buffer->len - buffer->offset;
643 buffer->offset = 0;
644 }
645}
646
647/**
648 * \brief Free a DNP3 object.
649 */
650static void DNP3ObjectFree(DNP3Object *object)
651{
652 if (object->points != NULL) {
653 DNP3FreeObjectPointList(object->group, object->variation,
654 object->points);
655 }
656 SCFree(object);
657}
658
659/**
660 * \brief Allocate a DNP3 object.
661 */
662static DNP3Object *DNP3ObjectAlloc(void)
663{
664 DNP3Object *object = SCCalloc(1, sizeof(*object));
665 if (unlikely(object == NULL)) {
666 return NULL;
667 }
668 object->points = DNP3PointListAlloc();
669 if (object->points == NULL) {
670 DNP3ObjectFree(object);
671 return NULL;
672 }
673 return object;
674}
675
676/**
677 * \brief Decode DNP3 application objects.
678 *
679 * This function decoded known DNP3 application objects. As the
680 * protocol isn't self describing, we can only decode the buffer while
681 * the application objects are known. As soon as an unknown
682 * group/variation is hit, we must stop processing.
683 *
684 * \param buf the input buffer
685 * \param len length of the input buffer
686 * \param objects pointer to list where decoded objects will be stored.
687 *
688 * \retval 1 if all objects decoded, 0 if all objects could not be decoded (
689 * unknown group/variations)
690 */
691static int DNP3DecodeApplicationObjects(DNP3Transaction *tx, const uint8_t *buf,
692 uint32_t len, DNP3ObjectList *objects)
693{
694 int retval = 0;
695
696 if (buf == NULL || len == 0) {
697 return 1;
698 }
699
700 while (len) {
701 uint32_t offset = 0;
702
703 if (len < sizeof(DNP3ObjHeader)) {
704 goto done;
705 }
706 DNP3ObjHeader *header = (DNP3ObjHeader *)buf;
707 offset += sizeof(DNP3ObjHeader);
708
709 DNP3Object *object = DNP3ObjectAlloc();
710 if (unlikely(object == NULL)) {
711 goto done;
712 }
713 TAILQ_INSERT_TAIL(objects, object, next);
714
715 object->group = header->group;
716 object->variation = header->variation;
717 object->qualifier = header->qualifier;
718 object->prefix_code = DNP3_OBJ_PREFIX(header->qualifier);
719 object->range_code = DNP3_OBJ_RANGE(header->qualifier);
720
721 /* IEEE 1815-2012, Table 4-5. */
722 switch (object->range_code) {
723 case 0x00:
724 case 0x03: {
725 /* 1 octet start and stop indexes OR 1 octet start and
726 * stop virtual addresses. */
727 if (offset + (sizeof(uint8_t) * 2) > len) {
728 /* Not enough data. */
729 SCLogDebug("Not enough data.");
730 goto not_enough_data;
731 }
732 object->start = buf[offset++];
733 object->stop = buf[offset++];
734 object->count = object->stop - object->start + 1;
735 break;
736 }
737 case 0x01:
738 case 0x04: {
739 /* 2 octet start and stop indexes OR 2 octect start
740 * and stop virtual addresses. */
741 if (offset + (sizeof(uint16_t) * 2) > len) {
742 /* Not enough data. */
743 SCLogDebug("Not enough data.");
744 goto not_enough_data;
745 }
746 object->start = DNP3_SWAP16(*(uint16_t *)(buf + offset));
747 offset += sizeof(uint16_t);
748 object->stop = DNP3_SWAP16(*(uint16_t *)(buf + offset));
749 offset += sizeof(uint16_t);
750 object->count = object->stop - object->start + 1;
751 break;
752 }
753 case 0x02:
754 case 0x05: {
755 /* 4 octet start and stop indexes OR 4 octect start
756 * and stop virtual addresses. */
757 if (offset + (sizeof(uint32_t) * 2) > len) {
758 /* Not enough data. */
759 SCLogDebug("Not enough data.");
760 goto not_enough_data;
761 }
762 object->start = DNP3_SWAP32(*(uint32_t *)(buf + offset));
763 offset += sizeof(uint32_t);
764 object->stop = DNP3_SWAP32(*(uint32_t *)(buf + offset));
765 offset += sizeof(uint32_t);
766 object->count = object->stop - object->start + 1;
767 break;
768 }
769 case 0x06:
770 /* No range field. */
771 object->count = 0;
772 break;
773 case 0x07:
774 /* 1 octet count of objects. */
775 if (offset + sizeof(uint8_t) > len) {
776 SCLogDebug("Not enough data.");
777 goto not_enough_data;
778 }
779 object->count = buf[offset];
780 offset += sizeof(uint8_t);
781 break;
782 case 0x08: {
783 /* 2 octet count of objects. */
784 if (offset + sizeof(uint16_t) > len) {
785 SCLogDebug("Not enough data.");
786 goto not_enough_data;
787 }
788 object->count = DNP3_SWAP16(*(uint16_t *)(buf + offset));
789 offset += sizeof(uint16_t);
790 break;
791 }
792 case 0x09: {
793 /* 4 octet count of objects. */
794 if (offset + sizeof(uint32_t) > len) {
795 SCLogDebug("Not enough data.");
796 goto not_enough_data;
797 }
798 object->count = DNP3_SWAP32(*(uint32_t *)(buf + offset));
799 offset += sizeof(uint32_t);
800 break;
801 }
802 case 0x0b: {
803 if (offset + sizeof(uint8_t) > len) {
804 /* Not enough data. */
805 SCLogDebug("Not enough data.");
806 goto not_enough_data;
807 }
808 object->count = *(uint8_t *)(buf + offset);
809 offset += sizeof(uint8_t);
810 break;
811 }
812 default:
813 SCLogDebug("Range code 0x%02x is reserved.",
814 object->range_code);
815 goto done;
816 }
817
818 buf += offset;
819 len -= offset;
820
821 if (object->variation == 0 || object->count == 0) {
822 goto next;
823 }
824
825 int event = DNP3DecodeObject(header->group, header->variation, &buf,
826 &len, object->prefix_code, object->start, object->count,
827 object->points);
828 if (event) {
829 DNP3SetEventTx(tx, DNP3_DECODER_EVENT_UNKNOWN_OBJECT);
830 goto done;
831 }
832
833 next:
834 continue;
835 }
836
837 /* All objects were decoded. */
838 retval = 1;
839
840not_enough_data:
841done:
842 return retval;
843}
844
845/**
846 * \brief Handle DNP3 request user data.
847 *
848 * \param dnp3 the current DNP3State
849 * \param input pointer to the DNP3 frame (starting with link header)
850 * \param input_len length of the input frame
851 */
852static void DNP3HandleUserDataRequest(
853 Flow *f, DNP3State *dnp3, const uint8_t *input, uint32_t input_len)
854{
855 DNP3LinkHeader *lh;
857 DNP3ApplicationHeader *ah;
858 DNP3Transaction *tx = NULL, *ttx;
859
860 lh = (DNP3LinkHeader *)input;
861
862 if (!DNP3CheckUserDataCRCs(input + sizeof(DNP3LinkHeader),
863 input_len - sizeof(DNP3LinkHeader))) {
864 return;
865 }
866
867 th = input[sizeof(DNP3LinkHeader)];
868
869 if (!DNP3_TH_FIR(th)) {
870 TAILQ_FOREACH(ttx, &dnp3->tx_list, next) {
871 if (ttx->lh.src == lh->src && ttx->lh.dst == lh->dst && ttx->is_request && !ttx->done &&
872 NEXT_TH_SEQNO(DNP3_TH_SEQ(ttx->th)) == DNP3_TH_SEQ(th)) {
873 tx = ttx;
874 break;
875 }
876 }
877
878 if (tx == NULL) {
879 return;
880 }
881
882 /* Update the saved transport header so subsequent segments
883 * will be matched to this sequence number. */
884 tx->th = th;
885 tx->tx_data.updated_ts = true;
886 }
887 else {
888 ah = (DNP3ApplicationHeader *)(input + sizeof(DNP3LinkHeader) +
889 sizeof(DNP3TransportHeader));
890
891 /* Ignore confirms - for now. */
892 if (ah->function_code == DNP3_APP_FC_CONFIRM) {
893 return;
894 }
895
896 /* Create a transaction. */
897 tx = DNP3TxAlloc(dnp3, true);
898 if (unlikely(tx == NULL)) {
899 return;
900 }
901 tx->tx_data.updated_ts = true;
902 tx->lh = *lh;
903 tx->th = th;
904 tx->ah = *ah;
905 }
906
907 if (!DNP3ReassembleApplicationLayer(input + sizeof(DNP3LinkHeader),
908 input_len - sizeof(DNP3LinkHeader), &tx->buffer, &tx->buffer_len)) {
909
910 /* Malformed, set event and mark as done. */
911 DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_MALFORMED);
912 tx->done = 1;
913 return;
914 }
915
916 /* If this is not the final segment, just return. */
917 if (!DNP3_TH_FIN(th)) {
918 return;
919 }
920
921 tx->done = 1;
922
923 if (DNP3DecodeApplicationObjects(tx, tx->buffer + sizeof(DNP3ApplicationHeader),
924 tx->buffer_len - sizeof(DNP3ApplicationHeader), &tx->objects)) {
925 tx->complete = 1;
926 }
927 if (f != NULL) {
929 }
930}
931
932static void DNP3HandleUserDataResponse(
933 Flow *f, DNP3State *dnp3, const uint8_t *input, uint32_t input_len)
934{
935 DNP3LinkHeader *lh;
937 DNP3ApplicationHeader *ah;
938 DNP3InternalInd *iin;
939 DNP3Transaction *tx = NULL, *ttx;
940 uint32_t offset = 0;
941
942 lh = (DNP3LinkHeader *)input;
943 offset += sizeof(DNP3LinkHeader);
944
945 if (!DNP3CheckUserDataCRCs(input + offset, input_len - offset)) {
946 return;
947 }
948
949 th = input[offset++];
950
951 if (!DNP3_TH_FIR(th)) {
952 TAILQ_FOREACH(ttx, &dnp3->tx_list, next) {
953 if (ttx->lh.src == lh->src && ttx->lh.dst == lh->dst && !ttx->is_request &&
954 !ttx->done && NEXT_TH_SEQNO(DNP3_TH_SEQ(ttx->th)) == DNP3_TH_SEQ(th)) {
955 tx = ttx;
956 break;
957 }
958 }
959
960 if (tx == NULL) {
961 return;
962 }
963
964 /* Replace the transport header in the transaction with this
965 * one in case there are more frames. */
966 tx->th = th;
967 tx->tx_data.updated_tc = true;
968 }
969 else {
970 ah = (DNP3ApplicationHeader *)(input + offset);
971 offset += sizeof(DNP3ApplicationHeader);
972 iin = (DNP3InternalInd *)(input + offset);
973
974 tx = DNP3TxAlloc(dnp3, false);
975 if (unlikely(tx == NULL)) {
976 return;
977 }
978 tx->tx_data.updated_tc = true;
979 tx->lh = *lh;
980 tx->th = th;
981 tx->ah = *ah;
982 tx->iin = *iin;
983 }
984
986
987 if (!DNP3ReassembleApplicationLayer(input + sizeof(DNP3LinkHeader),
988 input_len - sizeof(DNP3LinkHeader), &tx->buffer, &tx->buffer_len)) {
989 DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_MALFORMED);
990 return;
991 }
992
993 if (!DNP3_TH_FIN(th)) {
994 return;
995 }
996
997 tx->done = 1;
998
999 offset = sizeof(DNP3ApplicationHeader) + sizeof(DNP3InternalInd);
1000 if (DNP3DecodeApplicationObjects(
1001 tx, tx->buffer + offset, tx->buffer_len - offset, &tx->objects)) {
1002 tx->complete = 1;
1003 }
1004 if (f != NULL) {
1005 AppLayerParserTriggerRawStreamInspection(f, STREAM_TOCLIENT);
1006 }
1007}
1008
1009/**
1010 * \brief Decode the DNP3 request link layer.
1011 *
1012 * \retval number of bytes processed or -1 if the data stream does not look
1013 * like DNP3.
1014 */
1015static int DNP3HandleRequestLinkLayer(
1016 Flow *f, DNP3State *dnp3, const uint8_t *input, uint32_t input_len)
1017{
1018 SCEnter();
1019 uint32_t processed = 0;
1020
1021 while (input_len) {
1022
1023 /* Need at least enough bytes for a DNP3 header. */
1024 if (input_len < sizeof(DNP3LinkHeader)) {
1025 break;
1026 }
1027
1028 DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1029
1030 if (!DNP3CheckStartBytes(header)) {
1031 goto error;
1032 }
1033
1034 if (!DNP3CheckLinkHeaderCRC(header)) {
1035 DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_BAD_LINK_CRC);
1036 goto error;
1037 }
1038
1039 uint32_t frame_len = DNP3CalculateLinkLength(header->len);
1040 if (frame_len == 0) {
1041 DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_LEN_TOO_SMALL);
1042 goto error;
1043 }
1044 if (input_len < frame_len) {
1045 /* Insufficient data, just break - will wait for more data. */
1046 break;
1047 }
1048
1049 /* Ignore non-user data for now. */
1050 if (!DNP3IsUserData(header)) {
1051 goto next;
1052 }
1053
1054 /* Make sure the header length is large enough for transport and
1055 * application headers. */
1056 if (!DNP3HasUserData(header, STREAM_TOSERVER)) {
1057 DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_LEN_TOO_SMALL);
1058 goto next;
1059 }
1060
1061 if (!DNP3CheckUserDataCRCs(input + sizeof(DNP3LinkHeader),
1062 frame_len - sizeof(DNP3LinkHeader))) {
1063 DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_BAD_TRANSPORT_CRC);
1064 goto next;
1065 }
1066
1067 DNP3HandleUserDataRequest(f, dnp3, input, frame_len);
1068
1069 next:
1070 /* Advance the input buffer. */
1071 input += frame_len;
1072 input_len -= frame_len;
1073 processed += frame_len;
1074 }
1075
1076 SCReturnInt(processed);
1077error:
1078 /* Error out. Should only happen if this doesn't look like a DNP3
1079 * frame. */
1080 SCReturnInt(-1);
1081}
1082
1083/**
1084 * \brief Handle incoming request data.
1085 *
1086 * The actual request PDU parsing is done in
1087 * DNP3HandleRequestLinkLayer. This function takes care of buffering TCP
1088 * date if a segment does not contain a complete frame (or contains
1089 * multiple frames, but not the complete final frame).
1090 */
1091static AppLayerResult DNP3ParseRequest(Flow *f, void *state, AppLayerParserState *pstate,
1092 StreamSlice stream_slice, void *local_data)
1093{
1094 SCEnter();
1095 DNP3State *dnp3 = (DNP3State *)state;
1096 DNP3Buffer *buffer = &dnp3->request_buffer;
1097 int processed = 0;
1098
1099 const uint8_t *input = StreamSliceGetData(&stream_slice);
1100 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1101
1102 if (input_len == 0) {
1104 }
1105
1106 if (buffer->len) {
1107 if (!DNP3BufferAdd(buffer, input, input_len)) {
1108 goto error;
1109 }
1110 processed = DNP3HandleRequestLinkLayer(
1111 f, dnp3, buffer->buffer + buffer->offset, buffer->len - buffer->offset);
1112 if (processed < 0) {
1113 goto error;
1114 }
1115 buffer->offset += processed;
1116 DNP3BufferTrim(buffer);
1117 }
1118 else {
1119 processed = DNP3HandleRequestLinkLayer(f, dnp3, input, input_len);
1120 if (processed < 0) {
1121 SCLogDebug("Failed to process request link layer.");
1122 goto error;
1123 }
1124
1125 input += processed;
1126 input_len -= processed;
1127
1128 /* Not all data was processed, buffer it. */
1129 if (input_len) {
1130 if (!DNP3BufferAdd(buffer, input, input_len)) {
1131 goto error;
1132 }
1133 }
1134 }
1135
1137
1138error:
1139 /* Reset the buffer. */
1140 DNP3BufferReset(buffer);
1142}
1143
1144/**
1145 * \brief Decode the DNP3 response link layer.
1146 *
1147 * \retval number of bytes processed or -1 if the data stream does not
1148 * like look DNP3.
1149 */
1150static int DNP3HandleResponseLinkLayer(
1151 Flow *f, DNP3State *dnp3, const uint8_t *input, uint32_t input_len)
1152{
1153 SCEnter();
1154 uint32_t processed = 0;
1155
1156 while (input_len) {
1157
1158 /* Need at least enough bytes for a DNP3 header. */
1159 if (input_len < sizeof(DNP3LinkHeader)) {
1160 break;
1161 }
1162
1163 DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1164
1165 if (!DNP3CheckStartBytes(header)) {
1166 goto error;
1167 }
1168
1169 if (!DNP3CheckLinkHeaderCRC(header)) {
1170 DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_BAD_LINK_CRC);
1171 goto error;
1172 }
1173
1174 /* Calculate the number of bytes needed to for this frame. */
1175 uint32_t frame_len = DNP3CalculateLinkLength(header->len);
1176 if (frame_len == 0) {
1177 DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_LEN_TOO_SMALL);
1178 goto error;
1179 }
1180 if (input_len < frame_len) {
1181 /* Insufficient data, just break - will wait for more data. */
1182 break;
1183 }
1184
1185 /* Only handle user data frames for now. */
1186 if (!DNP3IsUserData(header)) {
1187 goto next;
1188 }
1189
1190 /* Make sure the header length is large enough for transport and
1191 * application headers. */
1192 if (!DNP3HasUserData(header, STREAM_TOCLIENT)) {
1193 DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_LEN_TOO_SMALL);
1194 goto error;
1195 }
1196
1197 if (!DNP3CheckUserDataCRCs(input + sizeof(DNP3LinkHeader),
1198 frame_len - sizeof(DNP3LinkHeader))) {
1199 DNP3SetEvent(dnp3, DNP3_DECODER_EVENT_BAD_TRANSPORT_CRC);
1200 goto next;
1201 }
1202
1203 DNP3HandleUserDataResponse(f, dnp3, input, frame_len);
1204
1205 next:
1206 /* Advance the input buffer. */
1207 input += frame_len;
1208 input_len -= frame_len;
1209 processed += frame_len;
1210 }
1211
1212 SCReturnInt(processed);
1213error:
1214 /* Error out. Should only happen if the data stream no longer
1215 * looks like DNP3. */
1216 SCReturnInt(-1);
1217}
1218
1219/**
1220 * \brief Parse incoming data.
1221 *
1222 * This is the entry function for DNP3 application layer data. Its
1223 * main responsibility is buffering incoming data that cannot be
1224 * processed.
1225 *
1226 * See DNP3ParseResponsePDUs for DNP3 frame handling.
1227 */
1228static AppLayerResult DNP3ParseResponse(Flow *f, void *state, AppLayerParserState *pstate,
1229 StreamSlice stream_slice, void *local_data)
1230{
1231 SCEnter();
1232
1233 DNP3State *dnp3 = (DNP3State *)state;
1234 DNP3Buffer *buffer = &dnp3->response_buffer;
1235 int processed;
1236
1237 const uint8_t *input = StreamSliceGetData(&stream_slice);
1238 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1239
1240 if (buffer->len) {
1241 if (!DNP3BufferAdd(buffer, input, input_len)) {
1242 goto error;
1243 }
1244 processed = DNP3HandleResponseLinkLayer(
1245 f, dnp3, buffer->buffer + buffer->offset, buffer->len - buffer->offset);
1246 if (processed < 0) {
1247 goto error;
1248 }
1249 buffer->offset += processed;
1250 DNP3BufferTrim(buffer);
1251 }
1252 else {
1253
1254 /* Check if this is a banner, ignore if it is. */
1255 if (DNP3ContainsBanner(input, input_len)) {
1256 goto done;
1257 }
1258
1259 processed = DNP3HandleResponseLinkLayer(f, dnp3, input, input_len);
1260 if (processed < 0) {
1261 goto error;
1262 }
1263 input += processed;
1264 input_len -= processed;
1265
1266 /* Not all data was processed, buffer it. */
1267 if (input_len) {
1268 if (!DNP3BufferAdd(buffer, input, input_len)) {
1269 goto error;
1270 }
1271 }
1272 }
1273
1274done:
1276
1277error:
1278 /* An error occurred while processing DNP3 frames. Dump the
1279 * buffer as we can't be assured that they are valid anymore. */
1280 DNP3BufferReset(buffer);
1282}
1283
1284static void *DNP3GetTx(void *alstate, uint64_t tx_id)
1285{
1286 SCEnter();
1287 DNP3State *dnp3 = (DNP3State *)alstate;
1288 DNP3Transaction *tx = NULL;
1289 uint64_t tx_num = tx_id + 1;
1290
1291 if (dnp3->curr && dnp3->curr->tx_num == (tx_num)) {
1292 SCReturnPtr(dnp3->curr, "void");
1293 }
1294
1295 TAILQ_FOREACH(tx, &dnp3->tx_list, next) {
1296 if (tx_num != tx->tx_num) {
1297 continue;
1298 }
1299 SCReturnPtr(tx, "void");
1300 }
1301
1302 SCReturnPtr(NULL, "void");
1303}
1304
1305static uint64_t DNP3GetTxCnt(void *state)
1306{
1307 SCEnter();
1308 uint64_t count = ((uint64_t)((DNP3State *)state)->transaction_max);
1309 SCReturnUInt(count);
1310}
1311
1312/**
1313 * \brief Free all the objects in a DNP3ObjectList.
1314 */
1315static void DNP3TxFreeObjectList(DNP3ObjectList *objects)
1316{
1317 DNP3Object *object;
1318
1319 while ((object = TAILQ_FIRST(objects)) != NULL) {
1320 TAILQ_REMOVE(objects, object, next);
1321 DNP3ObjectFree(object);
1322 }
1323}
1324
1325/**
1326 * \brief Free a DNP3 transaction.
1327 */
1328static void DNP3TxFree(DNP3Transaction *tx)
1329{
1330 SCEnter();
1331
1332 if (tx->buffer != NULL) {
1333 SCFree(tx->buffer);
1334 }
1335
1336 SCAppLayerTxDataCleanup(&tx->tx_data);
1337
1338 DNP3TxFreeObjectList(&tx->objects);
1339
1340 SCFree(tx);
1341 SCReturn;
1342}
1343
1344/**
1345 * \brief Free a transaction by ID on a specific DNP3 state.
1346 *
1347 * This function is called by the app-layer to free a transaction on a
1348 * specific DNP3 state object.
1349 */
1350static void DNP3StateTxFree(void *state, uint64_t tx_id)
1351{
1352 SCEnter();
1353 DNP3State *dnp3 = state;
1354 DNP3Transaction *tx = NULL, *ttx;
1355 uint64_t tx_num = tx_id + 1;
1356
1357 TAILQ_FOREACH_SAFE(tx, &dnp3->tx_list, next, ttx) {
1358
1359 if (tx->tx_num != tx_num) {
1360 continue;
1361 }
1362
1363 if (tx == dnp3->curr) {
1364 dnp3->curr = NULL;
1365 }
1366
1367 if (tx->tx_data.events != NULL) {
1368 if (tx->tx_data.events->cnt <= dnp3->events) {
1369 dnp3->events -= tx->tx_data.events->cnt;
1370 } else {
1371 dnp3->events = 0;
1372 }
1373 }
1374 dnp3->unreplied--;
1375
1376 /* Check flood state. */
1377 if (dnp3->flooded && dnp3->unreplied < DNP3_DEFAULT_REQ_FLOOD_COUNT) {
1378 dnp3->flooded = 0;
1379 }
1380
1381 TAILQ_REMOVE(&dnp3->tx_list, tx, next);
1382 DNP3TxFree(tx);
1383 break;
1384 }
1385
1386 SCReturn;
1387}
1388
1389/**
1390 * \brief Free a DNP3 state.
1391 */
1392static void DNP3StateFree(void *state)
1393{
1394 SCEnter();
1395 DNP3State *dnp3 = state;
1396 DNP3Transaction *tx;
1397 if (state != NULL) {
1398 while ((tx = TAILQ_FIRST(&dnp3->tx_list)) != NULL) {
1399 TAILQ_REMOVE(&dnp3->tx_list, tx, next);
1400 DNP3TxFree(tx);
1401 }
1402 if (dnp3->request_buffer.buffer != NULL) {
1404 }
1405 if (dnp3->response_buffer.buffer != NULL) {
1407 }
1408 SCFree(dnp3);
1409 }
1410 SCReturn;
1411}
1412
1413/**
1414 * \brief Called by the app-layer to get the state progress.
1415 */
1416static int DNP3GetAlstateProgress(void *tx, uint8_t direction)
1417{
1418 DNP3Transaction *dnp3tx = (DNP3Transaction *)tx;
1419 DNP3State *dnp3 = dnp3tx->dnp3;
1420 int retval = 0;
1421
1422 /* If flooded, "ack" old transactions. */
1423 if (dnp3->flooded && (dnp3->transaction_max -
1425 SCLogDebug("flooded: returning tx as done.");
1426 SCReturnInt(1);
1427 }
1428
1429 if (dnp3tx->complete)
1430 retval = 1;
1431
1432 SCReturnInt(retval);
1433}
1434
1435/**
1436 * \brief App-layer support.
1437 */
1438static int DNP3StateGetEventInfo(
1439 const char *event_name, uint8_t *event_id, AppLayerEventType *event_type)
1440{
1441 if (SCAppLayerGetEventIdByName(event_name, dnp3_decoder_event_table, event_id) == 0) {
1442 *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
1443 return 0;
1444 }
1445 return -1;
1446}
1447
1448/**
1449 * \brief App-layer support.
1450 */
1451static int DNP3StateGetEventInfoById(
1452 uint8_t event_id, const char **event_name, AppLayerEventType *event_type)
1453{
1454 *event_name = SCMapEnumValueToName(event_id, dnp3_decoder_event_table);
1455 if (*event_name == NULL) {
1456 SCLogError("Event \"%d\" not present in "
1457 "the DNP3 enum event map table.",
1458 event_id);
1459 return -1;
1460 }
1461
1462 *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
1463
1464 return 0;
1465}
1466
1467static AppLayerTxData *DNP3GetTxData(void *vtx)
1468{
1469 DNP3Transaction *tx = (DNP3Transaction *)vtx;
1470 return &tx->tx_data;
1471}
1472
1473static AppLayerStateData *DNP3GetStateData(void *vstate)
1474{
1475 DNP3State *state = (DNP3State *)vstate;
1476 return &state->state_data;
1477}
1478
1479/**
1480 * \brief Check if the prefix code is a size prefix.
1481 *
1482 * \retval 1 if the prefix_code specifies a size prefix, 0 if not.
1483 */
1484int DNP3PrefixIsSize(uint8_t prefix_code)
1485{
1486 switch (prefix_code) {
1487 case 0x04:
1488 case 0x05:
1489 case 0x06:
1490 return 1;
1491 break;
1492 default:
1493 return 0;
1494 }
1495}
1496
1497static AppLayerGetTxIterTuple DNP3GetTxIterator(const uint8_t ipproto, const AppProto alproto,
1498 void *alstate, uint64_t min_tx_id, uint64_t max_tx_id, AppLayerGetTxIterState *state)
1499{
1500 DNP3State *dnp_state = (DNP3State *)alstate;
1501 AppLayerGetTxIterTuple no_tuple = { NULL, 0, false };
1502 if (dnp_state) {
1503 DNP3Transaction *tx_ptr;
1504 if (state->un.ptr == NULL) {
1505 tx_ptr = TAILQ_FIRST(&dnp_state->tx_list);
1506 } else {
1507 tx_ptr = (DNP3Transaction *)state->un.ptr;
1508 }
1509 if (tx_ptr) {
1510 while (tx_ptr->tx_num < min_tx_id + 1) {
1511 tx_ptr = TAILQ_NEXT(tx_ptr, next);
1512 if (!tx_ptr) {
1513 return no_tuple;
1514 }
1515 }
1516 if (tx_ptr->tx_num >= max_tx_id + 1) {
1517 return no_tuple;
1518 }
1519 state->un.ptr = TAILQ_NEXT(tx_ptr, next);
1520 AppLayerGetTxIterTuple tuple = {
1521 .tx_ptr = tx_ptr,
1522 .tx_id = tx_ptr->tx_num - 1,
1523 .has_next = (state->un.ptr != NULL),
1524 };
1525 return tuple;
1526 }
1527 }
1528 return no_tuple;
1529}
1530
1531/**
1532 * \brief Register the DNP3 application protocol parser.
1533 */
1535{
1536 SCEnter();
1537
1538 const char *proto_name = "dnp3";
1539
1540 if (SCAppLayerProtoDetectConfProtoDetectionEnabledDefault("tcp", proto_name, false)) {
1542
1543 if (RunmodeIsUnittests()) {
1545 sizeof(DNP3LinkHeader), STREAM_TOSERVER, DNP3ProbingParser, DNP3ProbingParser);
1546 }
1547 else {
1548 if (!SCAppLayerProtoDetectPPParseConfPorts("tcp", IPPROTO_TCP, proto_name, ALPROTO_DNP3,
1549 0, sizeof(DNP3LinkHeader), DNP3ProbingParser, DNP3ProbingParser)) {
1550 return;
1551 }
1552 }
1553
1554 } else {
1555 SCLogConfig("Protocol detection and parser disabled for DNP3.");
1556 SCReturn;
1557 }
1558
1559 if (SCAppLayerParserConfParserEnabled("tcp", proto_name)) {
1560 SCLogConfig("Registering DNP3/tcp parsers.");
1561
1562 AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_DNP3, STREAM_TOSERVER,
1563 DNP3ParseRequest);
1564 AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_DNP3, STREAM_TOCLIENT,
1565 DNP3ParseResponse);
1566
1568 DNP3StateAlloc, DNP3StateFree);
1569
1570 AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_DNP3, DNP3GetTx);
1571 AppLayerParserRegisterGetTxIterator(IPPROTO_TCP, ALPROTO_DNP3, DNP3GetTxIterator);
1572 AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_DNP3, DNP3GetTxCnt);
1574 DNP3StateTxFree);
1575
1577 DNP3GetAlstateProgress);
1579
1581 DNP3StateGetEventInfo);
1583 DNP3StateGetEventInfoById);
1584
1586 DNP3GetTxData);
1587 AppLayerParserRegisterStateDataFunc(IPPROTO_TCP, ALPROTO_DNP3, DNP3GetStateData);
1588 } else {
1589 SCLogConfig("Parser disabled for protocol %s. "
1590 "Protocol detection still on.", proto_name);
1591 }
1592
1593#ifdef UNITTESTS
1596#endif
1597
1598 SCReturn;
1599}
1600
1601#ifdef UNITTESTS
1602
1603#include "flow-util.h"
1604#include "stream-tcp.h"
1605
1606/**
1607 * \brief Utility function to fix CRCs when mangling a frame.
1608 */
1609static void DNP3FixCrc(uint8_t *data, uint32_t len)
1610{
1611 uint32_t block_size;
1612
1613 while (len) {
1614 if (len >= DNP3_BLOCK_SIZE + DNP3_CRC_LEN) {
1615 block_size = DNP3_BLOCK_SIZE;
1616 } else {
1617 block_size = len - DNP3_CRC_LEN;
1618 }
1619 uint16_t crc = DNP3ComputeCRC(data, block_size);
1620 data[block_size + 1] = (crc >> 8) & 0xff;
1621 data[block_size] = crc & 0xff;
1622 data += block_size + DNP3_CRC_LEN;
1623 len -= block_size + DNP3_CRC_LEN;
1624 }
1625}
1626
1627/**
1628 * \test Test CRC checking on partial and full blocks.
1629 */
1630static int DNP3ParserTestCheckCRC(void)
1631{
1632 uint8_t request[] = {
1633 /* DNP3 start. */
1634 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1635 0xa5, 0xe9,
1636
1637 /* Transport header. */
1638 0xff,
1639
1640 /* Application layer - segment 1. */
1641 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1642 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1643 0xef,
1644
1645 /* Application layer - segment 2. */
1646 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1647 };
1648
1649 /* Check link header CRC. */
1650 FAIL_IF(!DNP3CheckCRC(request, sizeof(DNP3LinkHeader)));
1651
1652 /* Check first application layer segment. */
1653 FAIL_IF(!DNP3CheckCRC(request + sizeof(DNP3LinkHeader),
1655
1656#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1657 /* Change a byte in link header, should fail now. */
1658 request[2]++;
1659 FAIL_IF(DNP3CheckCRC(request, sizeof(DNP3LinkHeader)));
1660
1661 /* Change a byte in the first application segment, should fail
1662 * now. */
1663 request[sizeof(DNP3LinkHeader) + 3]++;
1664 FAIL_IF(DNP3CheckCRC(request + sizeof(DNP3LinkHeader),
1666#endif
1667
1668 PASS;
1669}
1670
1671/**
1672 * \test Test validation of all CRCs in user data.
1673 */
1674static int DNP3CheckUserDataCRCsTest(void)
1675{
1676 /* Multi-block data with valid CRCs. */
1677 uint8_t data_valid[] = {
1678 0xff, 0xc9, 0x05, 0x0c,
1679 0x01, 0x28, 0x01, 0x00,
1680 0x00, 0x00, 0x01, 0x01,
1681 0x01, 0x00, 0x00, 0x00,
1682 0x72, 0xef, /* CRC. */
1683
1684 0xff, 0xc9, 0x05, 0x0c,
1685 0x01, 0x28, 0x01, 0x00,
1686 0x00, 0x00, 0x01, 0x01,
1687 0x01, 0x00, 0x00, 0x00,
1688 0x72, 0xef, /* CRC. */
1689
1690 0xff, 0xc9, 0x05, 0x0c,
1691 0x01, 0x28, 0x01, 0x00,
1692 0x00, 0x00, 0x01, 0x01,
1693 0x01, 0x00, 0x00, 0x00,
1694 0x72, 0xef, /* CRC. */
1695
1696 0x00, 0x00, 0x00, 0x00,
1697 0x00,
1698 0xff, 0xff, /* CRC. */
1699 };
1700 FAIL_IF(!DNP3CheckUserDataCRCs(data_valid, sizeof(data_valid)));
1701
1702#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1703 /* Multi-block data with one non-crc byte altered. */
1704 uint8_t data_invalid[] = {
1705 0xff, 0xc9, 0x05, 0x0c,
1706 0x01, 0x28, 0x01, 0x00,
1707 0x00, 0x00, 0x01, 0x01,
1708 0x01, 0x00, 0x00, 0x00,
1709 0x72, 0xef, /* CRC. */
1710
1711 0xff, 0xc9, 0x05, 0x0c,
1712 0x01, 0x28, 0x01, 0x00,
1713 0x00, 0x00, 0x01, 0x01,
1714 0x01, 0x00, 0x00, 0x00,
1715 0x72, 0xef, /* CRC. */
1716
1717 0xff, 0xc9, 0x05, 0x0c,
1718 0x01, 0x28, 0x01, 0x00,
1719 0x00, 0x00, 0x01, 0x01,
1720 0x01, 0x00, 0x00, 0x00,
1721 0x72, 0xef, /* CRC. */
1722
1723 0x00, 0x00, 0x00, 0x00,
1724 0x01, /* Invalid byte. */
1725 0xff, 0xff, /* CRC. */
1726 };
1727 FAIL_IF(DNP3CheckUserDataCRCs(data_invalid, sizeof(data_invalid)));
1728
1729 /* 1 byte - need at least 3. */
1730 uint8_t one_byte_nocrc[] = { 0x01 };
1731 FAIL_IF(DNP3CheckUserDataCRCs(one_byte_nocrc, sizeof(one_byte_nocrc)));
1732
1733 /* 2 bytes - need at least 3. */
1734 uint8_t two_byte_nocrc[] = { 0x01, 0x02 };
1735 FAIL_IF(DNP3CheckUserDataCRCs(two_byte_nocrc, sizeof(two_byte_nocrc)));
1736#endif
1737
1738 /* 3 bytes, valid CRC. */
1739 uint8_t three_bytes_good_crc[] = { 0x00, 0x00, 0x00 };
1740 *(uint16_t *)(three_bytes_good_crc + 1) = DNP3ComputeCRC(
1741 three_bytes_good_crc, 1);
1742 FAIL_IF(!DNP3CheckUserDataCRCs(three_bytes_good_crc,
1743 sizeof(three_bytes_good_crc)));
1744
1745 PASS;
1746}
1747
1748/**
1749 * \test Test the link layer length calculation.
1750 *
1751 * Test the calculation that converts the link provided in the DNP3
1752 * header to the actual length of the frame. That is the length with
1753 * CRCs as the length in the header does not include CRCs.
1754 */
1755static int DNP3CalculateLinkLengthTest(void)
1756{
1757 /* These are invalid. */
1758 FAIL_IF(DNP3CalculateLinkLength(0) != 0);
1759 FAIL_IF(DNP3CalculateLinkLength(1) != 0);
1760 FAIL_IF(DNP3CalculateLinkLength(2) != 0);
1761 FAIL_IF(DNP3CalculateLinkLength(3) != 0);
1762 FAIL_IF(DNP3CalculateLinkLength(4) != 0);
1763
1764 /* This is the minimum size. */
1765 FAIL_IF(DNP3CalculateLinkLength(5) != 10);
1766
1767 /* 1 full user data blocks of data. */
1768 FAIL_IF(DNP3CalculateLinkLength(21) != 28);
1769
1770 /* 2 full user data blocks of data. */
1771 FAIL_IF(DNP3CalculateLinkLength(37) != 46);
1772
1773 /* 2 full user data blocks, plus one more byte. */
1774 /* 2 full user data blocks of data. */
1775 FAIL_IF(DNP3CalculateLinkLength(38) != 49);
1776
1777 /* The maximum size. */
1778 FAIL_IF(DNP3CalculateLinkLength(255) != 292);
1779
1780 PASS;
1781}
1782
1783/**
1784 * \test The conversion of length with CRCs to the length without
1785 * CRCs.
1786 */
1787static int DNP3CalculateTransportLengthWithoutCRCsTest(void)
1788{
1789 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(0) != -1);
1790 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(1) != -1);
1791 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(2) != 0);
1792 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(3) != 1);
1793 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(16) != 14);
1794 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(17) != 15);
1795 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(18) != 16);
1796
1797 /* 19 bytes is not enough for a second block. */
1798 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(19) != -1);
1799
1800 /* 20 bytes really isn't enough either, but is large enough to
1801 * satisfy the CRC on the second block. */
1802 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(20) != 16);
1803
1804 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(21) != 17);
1805
1806 PASS;
1807}
1808
1809/**
1810 * \test Test the validation of the link header CRC.
1811 */
1812static int DNP3ParserCheckLinkHeaderCRC(void)
1813{
1814 /* DNP3 frame with valid headers and CRCs. */
1815 uint8_t request[] = {
1816 /* DNP3 start. */
1817 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1818 0xa5, 0xe9,
1819
1820 /* Transport header. */
1821 0xff,
1822
1823 /* Application layer. */
1824 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1825 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1826 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1827 };
1828
1829 DNP3LinkHeader *header = (DNP3LinkHeader *)request;
1830 FAIL_IF(!DNP3CheckLinkHeaderCRC(header));
1831
1832#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1833 /* Alter a byte in the header. */
1834 request[4] = 0;
1835 FAIL_IF(DNP3CheckLinkHeaderCRC(header));
1836#endif
1837
1838 PASS;
1839}
1840
1841/**
1842 * \test Test removal of CRCs from user data.
1843 */
1844static int DNP3ReassembleApplicationLayerTest01(void)
1845{
1846 uint32_t reassembled_len = 0;
1847 uint8_t *output = NULL;
1848
1849 uint8_t payload[] = {
1850
1851 0xff, 0xc9, 0x05, 0x0c,
1852 0x01, 0x28, 0x01, 0x00,
1853 0x00, 0x00, 0x01, 0x01,
1854 0x01, 0x00, 0x00, 0x00,
1855 0x72, 0xef, /* CRC. */
1856
1857 0xff, 0xc9, 0x05, 0x0c,
1858 0x01, 0x28, 0x01, 0x00,
1859 0x00, 0x00, 0x01, 0x01,
1860 0x01, 0x00, 0x00, 0x00,
1861 0x72, 0xef, /* CRC. */
1862
1863 0xff, 0xc9, 0x05, 0x0c,
1864 0x01, 0x28, 0x01, 0x00,
1865 0x00, 0x00, 0x01, 0x01,
1866 0x01, 0x00, 0x00, 0x00,
1867 0x72, 0xef, /* CRC. */
1868
1869 0x00, 0x00, 0x00, 0x00,
1870 0x00,
1871 0xff, 0xff, /* CRC. */
1872 };
1873
1874 uint8_t expected[] = {
1875 0xc9, 0x05, 0x0c,
1876 0x01, 0x28, 0x01, 0x00,
1877 0x00, 0x00, 0x01, 0x01,
1878 0x01, 0x00, 0x00, 0x00,
1879 /* CRC removed. */
1880 0xff, 0xc9, 0x05, 0x0c,
1881 0x01, 0x28, 0x01, 0x00,
1882 0x00, 0x00, 0x01, 0x01,
1883 0x01, 0x00, 0x00, 0x00,
1884 /* CRC removed. */
1885 0xff, 0xc9, 0x05, 0x0c,
1886 0x01, 0x28, 0x01, 0x00,
1887 0x00, 0x00, 0x01, 0x01,
1888 0x01, 0x00, 0x00, 0x00,
1889 /* CRC removed. */
1890 0x00, 0x00, 0x00, 0x00,
1891 0x00
1892 /* CRC removed. */
1893 };
1894
1895 /* Valid frame. */
1896 FAIL_IF(!DNP3ReassembleApplicationLayer(payload,
1897 sizeof(payload), &output, &reassembled_len));
1898 FAIL_IF(output == NULL);
1899 FAIL_IF(reassembled_len != sizeof(expected));
1900 FAIL_IF(memcmp(expected, output, reassembled_len));
1901 SCFree(output);
1902
1903 /* 1 byte, invalid. */
1904 reassembled_len = 0;
1905 output = NULL;
1906 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 1, &output,
1907 &reassembled_len));
1908 FAIL_IF(output != NULL);
1909 FAIL_IF(reassembled_len != 0);
1910
1911 /* 2 bytes, invalid. */
1912 reassembled_len = 0;
1913 output = NULL;
1914 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 2, &output,
1915 &reassembled_len));
1916 FAIL_IF(output != NULL);
1917 FAIL_IF(reassembled_len != 0);
1918
1919 /* 3 bytes, minimum - but that would only be the transport header
1920 * which isn't included in the output. */
1921 reassembled_len = 0;
1922 output = NULL;
1923 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 3, &output,
1924 &reassembled_len));
1925 FAIL_IF(output != NULL);
1926 FAIL_IF(reassembled_len != 0);
1927
1928 /* 4 bytes is the minimum to get any reassembled data. */
1929 reassembled_len = 0;
1930 output = NULL;
1931 FAIL_IF(!DNP3ReassembleApplicationLayer(payload, 4, &output,
1932 &reassembled_len));
1933 FAIL_IF(output == NULL);
1934 FAIL_IF(reassembled_len != 1);
1935
1936 /* Last block too short (by 1 byte) for data + CRC. */
1937 uint8_t short_payload1[] = {
1938
1939 0xff, 0xc9, 0x05, 0x0c,
1940 0x01, 0x28, 0x01, 0x00,
1941 0x00, 0x00, 0x01, 0x01,
1942 0x01, 0x00, 0x00, 0x00,
1943 0x72, 0xef, /* CRC. */
1944
1945 0xff, 0xc9, 0x05, 0x0c,
1946 0x01, 0x28, 0x01, 0x00,
1947 0x00, 0x00, 0x01, 0x01,
1948 0x01, 0x00, 0x00, 0x00,
1949 0x72, 0xef, /* CRC. */
1950
1951 0xff, 0xc9, 0x05, 0x0c,
1952 0x01, 0x28, 0x01, 0x00,
1953 0x00, 0x00, 0x01, 0x01,
1954 0x01, 0x00, 0x00, 0x00,
1955 0x72, 0xef, /* CRC. */
1956
1957 0x00, 0x00
1958 };
1959 reassembled_len = 0;
1960 FAIL_IF(DNP3ReassembleApplicationLayer(short_payload1,
1961 sizeof(short_payload1), &output, &reassembled_len));
1962
1963 /* Last block too short (by 2 bytes) for data + CRC. */
1964 uint8_t short_payload2[] = {
1965
1966 0xff, 0xc9, 0x05, 0x0c,
1967 0x01, 0x28, 0x01, 0x00,
1968 0x00, 0x00, 0x01, 0x01,
1969 0x01, 0x00, 0x00, 0x00,
1970 0x72, 0xef, /* CRC. */
1971
1972 0xff, 0xc9, 0x05, 0x0c,
1973 0x01, 0x28, 0x01, 0x00,
1974 0x00, 0x00, 0x01, 0x01,
1975 0x01, 0x00, 0x00, 0x00,
1976 0x72, 0xef, /* CRC. */
1977
1978 0xff, 0xc9, 0x05, 0x0c,
1979 0x01, 0x28, 0x01, 0x00,
1980 0x00, 0x00, 0x01, 0x01,
1981 0x01, 0x00, 0x00, 0x00,
1982 0x72, 0xef, /* CRC. */
1983
1984 0x00,
1985 };
1986 reassembled_len = 0;
1987 FAIL_IF(DNP3ReassembleApplicationLayer(short_payload2,
1988 sizeof(short_payload2), &output, &reassembled_len));
1989
1990 PASS;
1991}
1992
1993/**
1994 * \test Test the probing parser.
1995 */
1996static int DNP3ProbingParserTest(void)
1997{
1998 uint8_t pkt[] = {
1999 0x05, 0x64, 0x05, 0xc9, 0x03, 0x00, 0x04, 0x00,
2000 0xbd, 0x71
2001 };
2002 uint8_t rdir = 0;
2003
2004 /* Valid frame. */
2005 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt, sizeof(pkt), &rdir) != ALPROTO_DNP3);
2006
2007 /* Send too little bytes. */
2008 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt, sizeof(DNP3LinkHeader) - 1, &rdir) != ALPROTO_UNKNOWN);
2009
2010 /* Bad start bytes. */
2011 pkt[0] = 0x06;
2012 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt, sizeof(pkt), &rdir) != ALPROTO_FAILED);
2013
2014 /* Restore start byte. */
2015 pkt[0] = 0x05;
2016
2017 /* Set the length to a value less than the minimum length of 5. */
2018 pkt[2] = 0x03;
2019 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt, sizeof(pkt), &rdir) != ALPROTO_FAILED);
2020
2021 /* Send a banner. */
2022 char mybanner[] = "Welcome to DNP3 SCADA.";
2023 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, (uint8_t *)mybanner, sizeof(mybanner) - 1,
2024 &rdir) != ALPROTO_DNP3);
2025 FAIL_IF(rdir != STREAM_TOCLIENT);
2026
2027 PASS;
2028}
2029
2030/**
2031 * \test Test a basic request/response.
2032 */
2033static int DNP3ParserTestRequestResponse(void)
2034{
2035 DNP3State *state = NULL;
2036
2037 uint8_t request[] = {
2038 /* DNP3 start. */
2039 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2040 0xa5, 0xe9,
2041
2042 /* Transport header. */
2043 0xff,
2044
2045 /* Application layer. */
2046 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2047 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2048 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2049 };
2050
2051 uint8_t response[] = {
2052 /* DNP3 start. */
2053 0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2054 0xe2, 0x59,
2055
2056 /* Transport header. */
2057 0xc3,
2058
2059 /* Application layer. */
2060 0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2061 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2062 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2063 0xff, 0xff
2064 };
2065
2067 Flow flow;
2068 TcpSession ssn;
2069
2070 memset(&flow, 0, sizeof(flow));
2071 memset(&ssn, 0, sizeof(ssn));
2072
2073 flow.protoctx = (void *)&ssn;
2074 flow.proto = IPPROTO_TCP;
2075 flow.alproto = ALPROTO_DNP3;
2076
2077 StreamTcpInitConfig(true);
2078
2079 SCMutexLock(&flow.m);
2081 STREAM_TOSERVER, request, sizeof(request)));
2082 SCMutexUnlock(&flow.m);
2083
2084 state = flow.alstate;
2085 FAIL_IF(state == NULL);
2086
2087 DNP3Transaction *tx = DNP3GetTx(state, 0);
2088 FAIL_IF(tx == NULL);
2089 FAIL_IF(tx->tx_num != 1);
2090 FAIL_IF(tx != state->curr);
2091 FAIL_IF(tx->buffer == NULL);
2092 FAIL_IF(tx->buffer_len != 20);
2093 FAIL_IF(tx->ah.function_code != DNP3_APP_FC_DIR_OPERATE);
2094
2095 SCMutexLock(&flow.m);
2097 STREAM_TOCLIENT, response, sizeof(response)));
2098 SCMutexUnlock(&flow.m);
2099 DNP3Transaction *tx0 = DNP3GetTx(state, 1);
2100 FAIL_IF(tx0 == NULL);
2101 FAIL_IF(tx0 == tx);
2102 FAIL_IF(!tx0->done);
2103 FAIL_IF(tx0->buffer == NULL);
2104
2106 StreamTcpFreeConfig(true);
2107 FLOW_DESTROY(&flow);
2108 PASS;
2109}
2110
2111/**
2112 * \test Test an unsolicited response from an outstation.
2113 *
2114 * This is kind of like a request initiated from the "server".
2115 */
2116static int DNP3ParserTestUnsolicitedResponseConfirm(void)
2117{
2118 DNP3State *state = NULL;
2119
2120 /* Unsolicited response with confirm bit set. */
2121 uint8_t response[] = {
2122 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2123 0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2124 0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2125 0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9
2126 };
2127
2128 /* Confirm. */
2129 uint8_t confirm[] = {
2130 0x05, 0x64, 0x08, 0xc4, 0x02, 0x00,
2131 0x01, 0x00, 0xd3, 0xb7, 0xc0, 0xda, 0x00, 0x6a,
2132 0x3d
2133 };
2134
2136 Flow flow;
2137 TcpSession ssn;
2138
2139 memset(&flow, 0, sizeof(flow));
2140 memset(&ssn, 0, sizeof(ssn));
2141
2142 flow.protoctx = (void *)&ssn;
2143 flow.proto = IPPROTO_TCP;
2144 flow.alproto = ALPROTO_DNP3;
2145
2146 StreamTcpInitConfig(true);
2147
2148 SCMutexLock(&flow.m);
2150 STREAM_TOCLIENT, response, sizeof(response)));
2151 SCMutexUnlock(&flow.m);
2152
2153 state = flow.alstate;
2154 FAIL_IF(state == NULL);
2155
2156 DNP3Transaction *tx = DNP3GetTx(state, 0);
2157 FAIL_IF(tx == NULL);
2158 FAIL_IF(tx->tx_num != 1);
2159 FAIL_IF(tx != state->curr);
2160 FAIL_IF(!tx->done);
2161 FAIL_IF(tx->ah.function_code != DNP3_APP_FC_UNSOLICITED_RESP);
2162
2163 SCMutexLock(&flow.m);
2165 STREAM_TOSERVER, confirm, sizeof(confirm)));
2166 SCMutexUnlock(&flow.m);
2167
2168 /* Confirms are ignored currently. With the move to
2169 unidirectional transactions it might be easy to support these
2170 now. */
2171 DNP3Transaction *resptx = DNP3GetTx(state, 1);
2172 FAIL_IF(resptx);
2173
2175 StreamTcpFreeConfig(true);
2176 FLOW_DESTROY(&flow);
2177 PASS;
2178}
2179
2180/**
2181 * \test Test flood state.
2182 *
2183 * Note that flood state needs to revisited with the modification to a
2184 * unidirectional protocol.
2185 */
2186static int DNP3ParserTestFlooded(void)
2187{
2188 DNP3State *state = NULL;
2189
2190 uint8_t request[] = {
2191 /* DNP3 start. */
2192 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2193 0xa5, 0xe9,
2194
2195 /* Transport header. */
2196 0xff,
2197
2198 /* Application layer. */
2199 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2200 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2201 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2202 };
2203
2205 Flow flow;
2206 TcpSession ssn;
2207
2208 memset(&flow, 0, sizeof(flow));
2209 memset(&ssn, 0, sizeof(ssn));
2210
2211 flow.protoctx = (void *)&ssn;
2212 flow.proto = IPPROTO_TCP;
2213 flow.alproto = ALPROTO_DNP3;
2214
2215 StreamTcpInitConfig(true);
2216
2217 SCMutexLock(&flow.m);
2219 STREAM_TOSERVER, request, sizeof(request)));
2220 SCMutexUnlock(&flow.m);
2221
2222 state = flow.alstate;
2223 FAIL_IF(state == NULL);
2224
2225 DNP3Transaction *tx = DNP3GetTx(state, 0);
2226 FAIL_IF(tx == NULL);
2227 FAIL_IF(tx->tx_num != 1);
2228 FAIL_IF(tx != state->curr);
2229 FAIL_IF(tx->buffer == NULL);
2230 FAIL_IF(tx->buffer_len != 20);
2231 FAIL_IF(tx->ah.function_code != DNP3_APP_FC_DIR_OPERATE);
2232 FAIL_IF_NOT(tx->done);
2233 FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2234
2235 for (int i = 0; i < DNP3_DEFAULT_REQ_FLOOD_COUNT - 1; i++) {
2236 SCMutexLock(&flow.m);
2238 STREAM_TOSERVER, request, sizeof(request)));
2239 SCMutexUnlock(&flow.m);
2240 }
2241 FAIL_IF(state->flooded);
2242 FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2243
2244 /* One more request should trip us into flooded state. */
2245 SCMutexLock(&flow.m);
2247 STREAM_TOSERVER, request, sizeof(request)));
2248 SCMutexUnlock(&flow.m);
2249 FAIL_IF(!state->flooded);
2250
2251 /* Progress for the oldest tx should return 1. */
2252 FAIL_IF(!DNP3GetAlstateProgress(tx, 0));
2253
2255 StreamTcpFreeConfig(true);
2256 FLOW_DESTROY(&flow);
2257 PASS;
2258}
2259
2260/**
2261 * \test Test parsing of partial frames.
2262 *
2263 * As DNP3 operates over TCP, it is possible that a partial DNP3 frame
2264 * is received. Test that the partial frame will be buffered until the
2265 * remainder is seen.
2266 */
2267static int DNP3ParserTestPartialFrame(void)
2268{
2269 DNP3State *state = NULL;
2270 DNP3Transaction *tx;
2271 int r;
2272
2273 uint8_t request_partial1[] = {
2274 /* DNP3 start. */
2275 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2276 0xa5, 0xe9,
2277
2278 /* Transport header. */
2279 0xff,
2280
2281 /* Application layer. */
2282 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2283 };
2284
2285 uint8_t request_partial2[] = {
2286 /* Remainder of application layer. */
2287 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2288 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2289 };
2290
2291 uint8_t response_partial1[] = {
2292 /* DNP3 start. */
2293 0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2294 0xe2, 0x59,
2295
2296 /* Transport header. */
2297 0xc3,
2298
2299 /* Application layer. */
2300 0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2301 };
2302
2303 uint8_t response_partial2[] = {
2304 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2305 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2306 0xff, 0xff
2307 };
2308
2309 /* Boiler plate for app layer setup. */
2311 Flow flow;
2312 TcpSession ssn;
2313 memset(&flow, 0, sizeof(flow));
2314 memset(&ssn, 0, sizeof(ssn));
2315 flow.protoctx = (void *)&ssn;
2316 flow.proto = IPPROTO_TCP;
2317 flow.alproto = ALPROTO_DNP3;
2318 StreamTcpInitConfig(true);
2319
2320 /* Pass in the first partial frame. */
2321
2322 SCMutexLock(&flow.m);
2323 r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2324 STREAM_TOSERVER, request_partial1, sizeof(request_partial1));
2325 SCMutexUnlock(&flow.m);
2326 FAIL_IF(r != 0);
2327
2328 /* Frame should just be buffered, but not yet processed. */
2329 state = flow.alstate;
2330 FAIL_IF(state == NULL);
2331 FAIL_IF(state->request_buffer.len != sizeof(request_partial1));
2332 FAIL_IF(state->request_buffer.offset != 0);
2333 FAIL_IF(memcmp(state->request_buffer.buffer, request_partial1,
2334 sizeof(request_partial1)));
2335
2336 /* There should not be a transaction yet. */
2337 FAIL_IF(state->transaction_max != 0);
2338 FAIL_IF(DNP3GetTx(state, 0) != NULL);
2339
2340 /* Send the second partial. */
2341 SCMutexLock(&flow.m);
2342 r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2343 STREAM_TOSERVER, request_partial2, sizeof(request_partial2));
2344 SCMutexUnlock(&flow.m);
2345 FAIL_IF(r != 0);
2346
2347 /* The second partial completed the frame, the buffer should now
2348 * be clear. */
2349 FAIL_IF(state->request_buffer.len != 0);
2350 FAIL_IF(state->request_buffer.offset != 0);
2351
2352 /* Should now have a complete transaction. */
2353 tx = DNP3GetTx(state, 0);
2354 FAIL_IF(tx == NULL);
2355 FAIL_IF(tx->tx_num != 1);
2356 FAIL_IF(tx != state->curr);
2357 FAIL_IF(tx->buffer == NULL);
2358 FAIL_IF(tx->buffer_len != 20);
2359 FAIL_IF(tx->ah.function_code != DNP3_APP_FC_DIR_OPERATE);
2360
2361 /* Send partial response. */
2362 SCMutexLock(&flow.m);
2363 r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2364 STREAM_TOCLIENT, response_partial1, sizeof(response_partial1));
2365 SCMutexUnlock(&flow.m);
2366 FAIL_IF(r != 0);
2367 FAIL_IF(state->response_buffer.len != sizeof(response_partial1));
2368 FAIL_IF(state->response_buffer.offset != 0);
2369 tx = DNP3GetTx(state, 1);
2370 FAIL_IF_NOT_NULL(tx);
2371
2372 /* Send rest of response. */
2373 SCMutexLock(&flow.m);
2374 r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2375 STREAM_TOCLIENT, response_partial2, sizeof(response_partial2));
2376 SCMutexUnlock(&flow.m);
2377 FAIL_IF(r != 0);
2378
2379 /* Buffer should now be empty. */
2380 FAIL_IF(state->response_buffer.len != 0);
2381 FAIL_IF(state->response_buffer.offset != 0);
2382
2383 /* There should now be a response transaction. */
2384 tx = DNP3GetTx(state, 1);
2385 FAIL_IF_NULL(tx);
2386 FAIL_IF(tx->buffer == NULL);
2387 FAIL_IF(tx->buffer_len == 0);
2388
2390 StreamTcpFreeConfig(true);
2391 FLOW_DESTROY(&flow);
2392 PASS;
2393}
2394
2395/**
2396 * \test Test multiple DNP3 frames in one TCP read.
2397 */
2398static int DNP3ParserTestMultiFrame(void)
2399{
2400 DNP3State *state = NULL;
2401
2402 /* Unsolicited response 1. */
2403 uint8_t unsol_response1[] = {
2404 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2405 0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2406 0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2407 0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9,
2408 };
2409
2410 /* Unsolicited response 2. */
2411 uint8_t unsol_response2[] = {
2412 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2413 0x89, 0xe5, 0xc5, 0xfb, 0x82, 0x00, 0x00, 0x02,
2414 0x02, 0x17, 0x01, 0x0c, 0x01, 0xd8, 0x75, 0xd8,
2415 0x32, 0x4c, 0xc9, 0x3c, 0x01, 0xa1, 0xc9,
2416 };
2417
2418 uint8_t combined[sizeof(unsol_response1) + sizeof(unsol_response2)];
2419 memcpy(combined, unsol_response1, sizeof(unsol_response1));
2420 memcpy(combined + sizeof(unsol_response1), unsol_response2,
2421 sizeof(unsol_response2));
2422
2423 /* Setup. */
2425 Flow flow;
2426 TcpSession ssn;
2427 int r;
2428 memset(&flow, 0, sizeof(flow));
2429 memset(&ssn, 0, sizeof(ssn));
2430 flow.protoctx = (void *)&ssn;
2431 flow.proto = IPPROTO_TCP;
2432 flow.alproto = ALPROTO_DNP3;
2433 StreamTcpInitConfig(true);
2434
2435 SCMutexLock(&flow.m);
2436 r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2437 STREAM_TOCLIENT, combined, sizeof(combined));
2438 SCMutexUnlock(&flow.m);
2439 FAIL_IF(r != 0);
2440
2441 state = flow.alstate;
2442 FAIL_IF(state == NULL);
2443 FAIL_IF(state->transaction_max != 2);
2444
2446 StreamTcpFreeConfig(true);
2447 FLOW_DESTROY(&flow);
2448 PASS;
2449}
2450
2451/**
2452 * \test Test the parsing of a request PDU.
2453 *
2454 * The PDU under test contains a single read request object:
2455 * - Group: 1
2456 * - Variation: 0
2457 * - Count: 0
2458 */
2459static int DNP3ParserTestParsePDU01(void)
2460{
2461 /* Frame to be tested. This frame is a DNP3 request with one read
2462 * request data object, group 1, variation 0. */
2463 const uint8_t pkt[] = {
2464 0x05, 0x64,
2465 0x0b, 0xc4, 0x17, 0x00, 0xef, 0xff, 0xc4, 0x8f,
2466 0xe1, 0xc8, 0x01, 0x01, 0x00, 0x06, 0x77, 0x6e
2467 };
2468
2469 DNP3State *dnp3state = DNP3StateAlloc(NULL, ALPROTO_UNKNOWN);
2470 int pdus = DNP3HandleRequestLinkLayer(NULL, dnp3state, pkt, sizeof(pkt));
2471 FAIL_IF(pdus < 1);
2472 DNP3Transaction *dnp3tx = DNP3GetTx(dnp3state, 0);
2473 FAIL_IF_NULL(dnp3tx);
2474 FAIL_IF(!dnp3tx->is_request);
2475 FAIL_IF(TAILQ_EMPTY(&dnp3tx->objects));
2476 DNP3Object *object = TAILQ_FIRST(&dnp3tx->objects);
2477 FAIL_IF(object->group != 1 || object->variation != 0);
2478 FAIL_IF(object->count != 0);
2479
2480 DNP3StateFree(dnp3state);
2481 PASS;
2482}
2483
2484/**
2485 * \test Test the decode of a DNP3 fragment with a single 70:3 object.
2486 */
2487static int DNP3ParserDecodeG70V3Test(void)
2488{
2489 const uint8_t pkt[] = {
2490 0x05, 0x64,
2491 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00, 0xc7, 0xee,
2492 0xc7, 0xc9, 0x1b, 0x46, 0x03, 0x5b, 0x01, 0x55,
2493 0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2494 0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2495 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2496 0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2497 0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2498 0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2499 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2500 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2501 0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2502 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2503 0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2504 0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2505 0xc4, 0x8b
2506 };
2507
2508 DNP3State *dnp3state = DNP3StateAlloc(NULL, ALPROTO_UNKNOWN);
2509 FAIL_IF_NULL(dnp3state);
2510 int bytes = DNP3HandleRequestLinkLayer(NULL, dnp3state, pkt, sizeof(pkt));
2511 FAIL_IF(bytes != sizeof(pkt));
2512 DNP3Transaction *tx = DNP3GetTx(dnp3state, 0);
2513 FAIL_IF_NULL(tx);
2515 DNP3Object *obj = TAILQ_FIRST(&tx->objects);
2516 FAIL_IF_NULL(obj);
2517 FAIL_IF_NOT(obj->group == 70);
2518 FAIL_IF_NOT(obj->variation == 3);
2519 FAIL_IF_NOT(obj->prefix_code == 0x5);
2520 FAIL_IF_NOT(obj->range_code == 0xb);
2521 FAIL_IF_NOT(obj->count == 1);
2522 DNP3Point *point = TAILQ_FIRST(obj->points);
2523 FAIL_IF_NULL(point);
2524 FAIL_IF_NOT(point->prefix == 85);
2525 FAIL_IF_NOT(point->size == 85);
2526 FAIL_IF_NULL(point->data);
2527 DNP3ObjectG70V3 *data = point->data;
2528 FAIL_IF_NOT(strcmp(
2529 data->filename,
2530 "C:/temp/DNPDeviceConfiguration written to Remote Device.xml") == 0);
2531 DNP3StateFree(dnp3state);
2532 PASS;
2533}
2534
2535/**
2536 * \brief Test that an alert is raised on an unknown object.
2537 */
2538static int DNP3ParserUnknownEventAlertTest(void)
2539{
2540 /* Valid DNP3 frame with 70:3 object. */
2541 uint8_t pkt[] = {
2542 0x05, 0x64, 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00,
2543 0xc7, 0xee,
2544
2545 0xc7, 0xc9, 0x1b,
2546
2547 /* Object and variation. Originally 70:3, now 70:99, an
2548 * unknown object. */
2549 0x46, 0x63,
2550
2551 0x5b, 0x01, 0x55,
2552 0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2553 0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2554 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2555 0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2556 0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2557 0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2558 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2559 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2560 0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2561 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2562 0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2563 0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2564 0xc4, 0x8b
2565 };
2566
2567 DNP3FixCrc(pkt + 10, sizeof(pkt) - 10);
2568
2569 DNP3State *dnp3state = DNP3StateAlloc(NULL, ALPROTO_UNKNOWN);
2570 FAIL_IF_NULL(dnp3state);
2571 int bytes = DNP3HandleRequestLinkLayer(NULL, dnp3state, pkt, sizeof(pkt));
2572 FAIL_IF(bytes != sizeof(pkt));
2573
2574 DNP3StateFree(dnp3state);
2575 PASS;
2576}
2577
2578/**
2579* \brief Test that an alert is raised on incorrect data.
2580*/
2581static int DNP3ParserIncorrectUserData(void)
2582{
2583 uint8_t packet_bytes[] = {
2584 0x05, 0x64, 0x08, 0xc4, 0x03, 0x00, 0x04, 0x00,
2585 0xbf, 0xe9, 0xc1, 0xc1, 0x82, 0xc5, 0xee
2586 };
2587
2589 Flow flow;
2590 TcpSession ssn;
2591 memset(&flow, 0, sizeof(flow));
2592 memset(&ssn, 0, sizeof(ssn));
2593 flow.protoctx = (void *)&ssn;
2594 flow.proto = IPPROTO_TCP;
2595 flow.alproto = ALPROTO_DNP3;
2596 StreamTcpInitConfig(true);
2597
2598 int r = AppLayerParserParse(NULL, alp_tctx, &flow, ALPROTO_DNP3,
2599 STREAM_TOCLIENT, packet_bytes, sizeof(packet_bytes));
2600
2601 FAIL_IF(r == 0);
2602
2604 StreamTcpFreeConfig(true);
2605 FLOW_DESTROY(&flow);
2606 PASS;
2607}
2608
2609#endif
2610
2612{
2613#ifdef UNITTESTS
2614 UtRegisterTest("DNP3ParserTestCheckCRC", DNP3ParserTestCheckCRC);
2615 UtRegisterTest("DNP3ParserCheckLinkHeaderCRC",
2616 DNP3ParserCheckLinkHeaderCRC);
2617 UtRegisterTest("DNP3CheckUserDataCRCsTest", DNP3CheckUserDataCRCsTest);
2618 UtRegisterTest("DNP3CalculateLinkLengthTest", DNP3CalculateLinkLengthTest);
2619 UtRegisterTest("DNP3CalculateTransportLengthWithoutCRCsTest",
2620 DNP3CalculateTransportLengthWithoutCRCsTest);
2621 UtRegisterTest("DNP3ReassembleApplicationLayerTest01",
2622 DNP3ReassembleApplicationLayerTest01);
2623 UtRegisterTest("DNP3ProbingParserTest", DNP3ProbingParserTest);
2624 UtRegisterTest("DNP3ParserTestRequestResponse",
2625 DNP3ParserTestRequestResponse);
2626 UtRegisterTest("DNP3ParserTestUnsolicitedResponseConfirm",
2627 DNP3ParserTestUnsolicitedResponseConfirm);
2628 UtRegisterTest("DNP3ParserTestPartialFrame", DNP3ParserTestPartialFrame);
2629 UtRegisterTest("DNP3ParserTestMultiFrame", DNP3ParserTestMultiFrame);
2630 UtRegisterTest("DNP3ParserTestFlooded", DNP3ParserTestFlooded);
2631 UtRegisterTest("DNP3ParserTestParsePDU01", DNP3ParserTestParsePDU01);
2632 UtRegisterTest("DNP3ParserDecodeG70V3Test", DNP3ParserDecodeG70V3Test);
2633 UtRegisterTest("DNP3ParserUnknownEventAlertTest",
2634 DNP3ParserUnknownEventAlertTest);
2635 UtRegisterTest("DNP3ParserIncorrectUserData", DNP3ParserIncorrectUserData);
2636#endif
2637}
void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
Registers a protocol for protocol detection phase.
int SCAppLayerProtoDetectPPParseConfPorts(const char *ipproto_name, uint8_t ipproto, const char *alproto_name, AppProto alproto, uint16_t min_depth, uint16_t max_depth, ProbingParserFPtr ProbingParserTs, ProbingParserFPtr ProbingParserTc)
void SCAppLayerProtoDetectPPRegister(uint8_t ipproto, const char *portstr, AppProto alproto, uint16_t min_depth, uint16_t max_depth, uint8_t direction, ProbingParserFPtr ProbingParser1, ProbingParserFPtr ProbingParser2)
register parser at a port
int SCAppLayerProtoDetectConfProtoDetectionEnabledDefault(const char *ipproto, const char *alproto, bool default_enabled)
Given a protocol name, checks if proto detection is enabled in the conf file.
DNP3PointList * DNP3PointListAlloc(void)
Allocate a list for DNP3 points.
void DNP3FreeObjectPointList(int group, int variation, DNP3PointList *list)
Free a DNP3PointList.
int DNP3DecodeObject(int group, int variation, const uint8_t **buf, uint32_t *len, uint8_t prefix_code, uint32_t start, uint32_t count, DNP3PointList *points)
Decode a DNP3 object.
void DNP3ParserRegisterTests(void)
@ DNP3_LINK_FC_UNCONFIRMED_USER_DATA
@ DNP3_LINK_FC_CONFIRMED_USER_DATA
#define DNP3_BLOCK_SIZE
SCEnumCharMap dnp3_decoder_event_table[]
#define DNP3_OBJ_RANGE(x)
#define DNP3_DEFAULT_PORT
void RegisterDNP3Parsers(void)
Register the DNP3 application protocol parser.
#define DNP3_DEFAULT_REQ_FLOOD_COUNT
#define DNP3_CRC_LEN
#define DNP3_BANNER
#define DNP3_OBJ_PREFIX(x)
#define DNP3_START_BYTE1
#define DNP3_MIN_LEN
#define DNP3_START_BYTE0
#define NEXT_TH_SEQNO(current)
#define DNP3_LINK_HDR_LEN
int DNP3PrefixIsSize(uint8_t prefix_code)
Check if the prefix code is a size prefix.
#define DNP3_LINK_FC(control)
#define DNP3_APP_FC_UNSOLICITED_RESP
#define DNP3_APP_FC_DIR_OPERATE
uint8_t len
#define DNP3_TH_FIR(x)
#define DNP3_APP_FC_CONFIRM
uint16_t crc
#define DNP3_SWAP32(x)
#define DNP3_TH_SEQ(x)
#define DNP3_LINK_DIR(control)
#define DNP3_TH_FIN(x)
uint8_t DNP3TransportHeader
DNP3 transport header.
@ DNP3_DECODER_EVENT_MALFORMED
@ DNP3_DECODER_EVENT_LEN_TOO_SMALL
@ DNP3_DECODER_EVENT_UNKNOWN_OBJECT
@ DNP3_DECODER_EVENT_BAD_LINK_CRC
@ DNP3_DECODER_EVENT_FLOODED
@ DNP3_DECODER_EVENT_BAD_TRANSPORT_CRC
#define DNP3_SWAP16(x)
int SCAppLayerGetEventIdByName(const char *event_name, SCEnumCharMap *table, uint8_t *event_id)
void AppLayerDecoderEventsSetEventRaw(AppLayerDecoderEvents **sevents, uint8_t event)
Set an app layer decoder event.
struct HtpBodyChunk_ * next
void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto, uint64_t(*StateGetTxCnt)(void *alstate))
void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto, void(*StateTransactionFree)(void *, uint64_t))
void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto, void(*RegisterUnittests)(void))
void AppLayerParserRegisterTxDataFunc(uint8_t ipproto, AppProto alproto, AppLayerTxData *(*GetTxData)(void *tx))
void AppLayerParserTriggerRawStreamInspection(Flow *f, int direction)
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
void AppLayerParserRegisterStateProgressCompletionStatus(AppProto alproto, const int ts, const int tc)
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, const uint8_t *input, uint32_t input_len)
void AppLayerParserRegisterStateDataFunc(uint8_t ipproto, AppProto alproto, AppLayerStateData *(*GetStateData)(void *state))
void AppLayerParserRegisterGetTxIterator(uint8_t ipproto, AppProto alproto, AppLayerGetTxIteratorFunc Func)
int AppLayerParserRegisterParser(uint8_t ipproto, AppProto alproto, uint8_t direction, AppLayerParserFPtr Parser)
Register app layer parser for the protocol.
void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto, void *(StateGetTx)(void *alstate, uint64_t tx_id))
void AppLayerParserRegisterGetEventInfo(uint8_t ipproto, AppProto alproto, int(*StateGetEventInfo)(const char *event_name, uint8_t *event_id, AppLayerEventType *event_type))
void AppLayerParserRegisterGetStateProgressFunc(uint8_t ipproto, AppProto alproto, int(*StateGetProgress)(void *alstate, uint8_t direction))
int SCAppLayerParserConfParserEnabled(const char *ipproto, const char *alproto_name)
check if a parser is enabled in the config Returns enabled always if: were running unittests
void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto, void *(*StateAlloc)(void *, AppProto), void(*StateFree)(void *))
void AppLayerParserRegisterGetEventInfoById(uint8_t ipproto, AppProto alproto, int(*StateGetEventInfoById)(uint8_t event_id, const char **event_name, AppLayerEventType *event_type))
struct AppLayerGetTxIterTuple AppLayerGetTxIterTuple
struct AppLayerTxData AppLayerTxData
#define APP_LAYER_TX_SKIP_INSPECT_TC
#define APP_LAYER_TX_SKIP_INSPECT_TS
#define APP_LAYER_OK
struct AppLayerResult AppLayerResult
#define APP_LAYER_ERROR
struct StreamSlice StreamSlice
struct AppLayerStateData AppLayerStateData
enum AppLayerEventType AppLayerEventType
uint16_t AppProto
@ ALPROTO_FAILED
@ ALPROTO_UNKNOWN
@ ALPROTO_DNP3
#define FLOW_DESTROY(f)
Definition flow-util.h:119
AppLayerParserThreadCtx * alp_tctx
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
#define PASS
Pass the test.
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
#define TAILQ_FOREACH(var, head, field)
Definition queue.h:252
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition queue.h:329
#define TAILQ_INIT(head)
Definition queue.h:262
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition queue.h:294
#define TAILQ_FIRST(head)
Definition queue.h:250
#define TAILQ_REMOVE(head, elm, field)
Definition queue.h:312
#define TAILQ_NEXT(elm, field)
Definition queue.h:307
#define TAILQ_EMPTY(head)
Definition queue.h:248
void StreamTcpFreeConfig(bool quiet)
Definition stream-tcp.c:859
void StreamTcpInitConfig(bool)
To initialize the stream global configuration data.
Definition stream-tcp.c:488
union AppLayerGetTxIterState::@7 un
A struct used for buffering incoming data prior to reassembly.
uint8_t * buffer
Struct to hold the list of decoded objects.
DNP3PointList * points
uint8_t range_code
uint8_t prefix_code
uint8_t variation
DNP3 object point.
uint32_t prefix
uint32_t size
Per flow DNP3 state.
DNP3Transaction * curr
uint8_t flooded
DNP3Buffer request_buffer
AppLayerStateData state_data
uint64_t transaction_max
DNP3Buffer response_buffer
uint16_t events
uint32_t unreplied
DNP3 transaction.
DNP3LinkHeader lh
DNP3InternalInd iin
DNP3TransportHeader th
DNP3ObjectList objects
AppLayerTxData tx_data
struct DNP3State_ * dnp3
DNP3ApplicationHeader ah
Flow data structure.
Definition flow.h:356
uint8_t proto
Definition flow.h:378
AppProto alproto
application level protocol
Definition flow.h:450
void * alstate
Definition flow.h:479
SCMutex m
Definition flow.h:435
void * protoctx
Definition flow.h:441
int RunmodeIsUnittests(void)
Definition suricata.c:270
#define SCMutexUnlock(mut)
#define SCMutexLock(mut)
#define SCEnter(...)
Definition util-debug.h:277
#define SCReturnUInt(x)
Definition util-debug.h:283
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCReturnInt(x)
Definition util-debug.h:281
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition util-debug.h:255
#define SCReturnPtr(x, type)
Definition util-debug.h:293
#define SCReturnStruct(x)
Definition util-debug.h:297
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
#define SCLogConfig(...)
Definition util-debug.h:229
#define SCReturn
Definition util-debug.h:279
const char * SCMapEnumValueToName(int enum_value, SCEnumCharMap *table)
Maps an enum value to a string name, from the supplied table.
Definition util-enum.c:68
#define SCFree(p)
Definition util-mem.h:61
#define SCRealloc(ptr, sz)
Definition util-mem.h:50
#define SCCalloc(nm, sz)
Definition util-mem.h:53
#define unlikely(expr)
uint8_t * BasicSearch(const uint8_t *haystack, uint32_t haystack_len, const uint8_t *needle, uint16_t needle_len)
Basic search improved. Limits are better handled, so it doesn't start searches that wont fit in the r...
Definition util-spm-bs.c:47
uint64_t offset
#define DEBUG_VALIDATE_BUG_ON(exp)