40 #define DNP3_DEFAULT_REQ_FLOOD_COUNT 500
42 #define DNP3_DEFAULT_PORT "20000"
45 #define DNP3_START_BYTE0 0x05
46 #define DNP3_START_BYTE1 0x64
49 #define DNP3_MIN_LEN 5
52 #define DNP3_CRC_LEN 2
56 #define DNP3_BLOCK_SIZE 16
59 #define DNP3_MAX_TRAN_SEQNO 64
66 #define DNP3_LINK_HDR_LEN 5
82 #define DNP3_OBJ_PREFIX(x) ((x >> 4) & 0x7)
85 #define DNP3_OBJ_RANGE(x) (x & 0xf)
99 #define NEXT_TH_SEQNO(current) ((current + 1) % DNP3_MAX_TRAN_SEQNO)
103 static const uint16_t crc_table[256] = {
104 0x0000, 0x365e, 0x6cbc, 0x5ae2, 0xd978, 0xef26, 0xb5c4, 0x839a,
105 0xff89, 0xc9d7, 0x9335, 0xa56b, 0x26f1, 0x10af, 0x4a4d, 0x7c13,
106 0xb26b, 0x8435, 0xded7, 0xe889, 0x6b13, 0x5d4d, 0x07af, 0x31f1,
107 0x4de2, 0x7bbc, 0x215e, 0x1700, 0x949a, 0xa2c4, 0xf826, 0xce78,
108 0x29af, 0x1ff1, 0x4513, 0x734d, 0xf0d7, 0xc689, 0x9c6b, 0xaa35,
109 0xd626, 0xe078, 0xba9a, 0x8cc4, 0x0f5e, 0x3900, 0x63e2, 0x55bc,
110 0x9bc4, 0xad9a, 0xf778, 0xc126, 0x42bc, 0x74e2, 0x2e00, 0x185e,
111 0x644d, 0x5213, 0x08f1, 0x3eaf, 0xbd35, 0x8b6b, 0xd189, 0xe7d7,
112 0x535e, 0x6500, 0x3fe2, 0x09bc, 0x8a26, 0xbc78, 0xe69a, 0xd0c4,
113 0xacd7, 0x9a89, 0xc06b, 0xf635, 0x75af, 0x43f1, 0x1913, 0x2f4d,
114 0xe135, 0xd76b, 0x8d89, 0xbbd7, 0x384d, 0x0e13, 0x54f1, 0x62af,
115 0x1ebc, 0x28e2, 0x7200, 0x445e, 0xc7c4, 0xf19a, 0xab78, 0x9d26,
116 0x7af1, 0x4caf, 0x164d, 0x2013, 0xa389, 0x95d7, 0xcf35, 0xf96b,
117 0x8578, 0xb326, 0xe9c4, 0xdf9a, 0x5c00, 0x6a5e, 0x30bc, 0x06e2,
118 0xc89a, 0xfec4, 0xa426, 0x9278, 0x11e2, 0x27bc, 0x7d5e, 0x4b00,
119 0x3713, 0x014d, 0x5baf, 0x6df1, 0xee6b, 0xd835, 0x82d7, 0xb489,
120 0xa6bc, 0x90e2, 0xca00, 0xfc5e, 0x7fc4, 0x499a, 0x1378, 0x2526,
121 0x5935, 0x6f6b, 0x3589, 0x03d7, 0x804d, 0xb613, 0xecf1, 0xdaaf,
122 0x14d7, 0x2289, 0x786b, 0x4e35, 0xcdaf, 0xfbf1, 0xa113, 0x974d,
123 0xeb5e, 0xdd00, 0x87e2, 0xb1bc, 0x3226, 0x0478, 0x5e9a, 0x68c4,
124 0x8f13, 0xb94d, 0xe3af, 0xd5f1, 0x566b, 0x6035, 0x3ad7, 0x0c89,
125 0x709a, 0x46c4, 0x1c26, 0x2a78, 0xa9e2, 0x9fbc, 0xc55e, 0xf300,
126 0x3d78, 0x0b26, 0x51c4, 0x679a, 0xe400, 0xd25e, 0x88bc, 0xbee2,
127 0xc2f1, 0xf4af, 0xae4d, 0x9813, 0x1b89, 0x2dd7, 0x7735, 0x416b,
128 0xf5e2, 0xc3bc, 0x995e, 0xaf00, 0x2c9a, 0x1ac4, 0x4026, 0x7678,
129 0x0a6b, 0x3c35, 0x66d7, 0x5089, 0xd313, 0xe54d, 0xbfaf, 0x89f1,
130 0x4789, 0x71d7, 0x2b35, 0x1d6b, 0x9ef1, 0xa8af, 0xf24d, 0xc413,
131 0xb800, 0x8e5e, 0xd4bc, 0xe2e2, 0x6178, 0x5726, 0x0dc4, 0x3b9a,
132 0xdc4d, 0xea13, 0xb0f1, 0x86af, 0x0535, 0x336b, 0x6989, 0x5fd7,
133 0x23c4, 0x159a, 0x4f78, 0x7926, 0xfabc, 0xcce2, 0x9600, 0xa05e,
134 0x6e26, 0x5878, 0x029a, 0x34c4, 0xb75e, 0x8100, 0xdbe2, 0xedbc,
135 0x91af, 0xa7f1, 0xfd13, 0xcb4d, 0x48d7, 0x7e89, 0x246b, 0x1235
145 static uint16_t DNP3ComputeCRC(
const uint8_t *buf, uint32_t
len)
147 const uint8_t *
byte = buf;
152 idx = (
crc ^ *byte) & 0xff;
153 crc = (crc_table[idx] ^ (
crc >> 8)) & 0xffff;
157 return ~
crc & 0xffff;
168 static int DNP3CheckCRC(
const uint8_t *block, uint32_t
len)
170 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
183 if (((
crc & 0xff) == block[crc_offset]) &&
184 ((
crc >> 8) == block[crc_offset + 1])) {
198 static int DNP3CheckLinkHeaderCRC(
const DNP3LinkHeader *header)
200 return DNP3CheckCRC((uint8_t *)header,
sizeof(DNP3LinkHeader));
211 static int DNP3CheckUserDataCRCs(
const uint8_t *data, uint32_t
len)
224 if (!DNP3CheckCRC(data +
offset, block_size)) {
240 static int DNP3CheckStartBytes(
const DNP3LinkHeader *header)
247 #define DNP3_BANNER "DNP3"
257 static int DNP3ContainsBanner(
const uint8_t *input, uint32_t
len)
265 static uint16_t DNP3ProbingParser(
Flow *f, uint8_t direction,
266 const uint8_t *input, uint32_t
len,
269 const DNP3LinkHeader *
const hdr = (
const DNP3LinkHeader *)input;
270 const bool toserver = (direction & STREAM_TOSERVER) != 0;
273 if (DNP3ContainsBanner(input,
len)) {
275 bool is_banner =
true;
277 for (uint32_t i = 0; i <
len && i < 0x100; i++) {
278 if (!isprint(input[i])) {
285 *rdir = STREAM_TOCLIENT;
292 if (
len <
sizeof(DNP3LinkHeader)) {
293 SCLogDebug(
"Length too small to be a DNP3 header.");
298 if (!DNP3CheckStartBytes(hdr)) {
305 SCLogDebug(
"Packet too small to be a valid DNP3 fragment.");
311 *rdir = toserver ? STREAM_TOCLIENT : STREAM_TOSERVER;
324 static int DNP3CalculateTransportLengthWithoutCRCs(uint32_t input_len)
367 static int DNP3ReassembleApplicationLayer(
const uint8_t *input,
368 uint32_t input_len, uint8_t **output, uint32_t *output_len)
370 int len = DNP3CalculateTransportLengthWithoutCRCs(input_len);
382 if (*output == NULL) {
389 uint8_t *ptr =
SCRealloc(*output, (
size_t)(*output_len +
len));
396 int offset = 0, block_size;
397 while ((uint32_t)
offset < input_len) {
402 block_size = input_len -
offset;
427 memcpy(*output + *output_len, input +
offset,
442 static void *DNP3StateAlloc(
void *orig_state,
AppProto proto_orig)
461 static void DNP3SetEvent(
DNP3State *dnp3, uint8_t event)
463 if (dnp3 && dnp3->
curr) {
468 SCLogWarning(
"Failed to set event, state or tx pointer was NULL.");
524 static uint32_t DNP3CalculateLinkLength(uint8_t length)
526 uint32_t frame_len = 0;
544 return frame_len +
sizeof(DNP3LinkHeader);
554 static int DNP3IsUserData(
const DNP3LinkHeader *header)
573 static int DNP3HasUserData(
const DNP3LinkHeader *header, uint8_t direction)
575 if (direction == STREAM_TOSERVER) {
577 sizeof(DNP3ApplicationHeader);
581 sizeof(DNP3ApplicationHeader) +
sizeof(DNP3InternalInd);
588 static void DNP3BufferReset(
DNP3Buffer *buffer)
603 static int DNP3BufferAdd(
DNP3Buffer *buffer,
const uint8_t *data, uint32_t
len)
605 if (buffer->
size == 0) {
634 static void DNP3BufferTrim(
DNP3Buffer *buffer)
637 DNP3BufferReset(buffer);
639 else if (buffer->
offset > 0) {
650 static void DNP3ObjectFree(
DNP3Object *
object)
652 if (object->
points != NULL) {
669 if (object->
points == NULL) {
670 DNP3ObjectFree(
object);
691 static int DNP3DecodeApplicationObjects(
DNP3Transaction *tx,
const uint8_t *buf,
692 uint32_t
len, DNP3ObjectList *objects)
696 if (buf == NULL ||
len == 0) {
703 if (
len <
sizeof(DNP3ObjHeader)) {
706 DNP3ObjHeader *header = (DNP3ObjHeader *)buf;
707 offset +=
sizeof(DNP3ObjHeader);
715 object->group = header->group;
716 object->variation = header->variation;
717 object->qualifier = header->qualifier;
727 if (
offset + (
sizeof(uint8_t) * 2) >
len) {
730 goto not_enough_data;
732 object->start = buf[
offset++];
733 object->stop = buf[
offset++];
734 object->count =
object->stop -
object->start + 1;
741 if (
offset + (
sizeof(uint16_t) * 2) >
len) {
744 goto not_enough_data;
747 offset +=
sizeof(uint16_t);
749 offset +=
sizeof(uint16_t);
750 object->count =
object->stop -
object->start + 1;
757 if (
offset + (
sizeof(uint32_t) * 2) >
len) {
760 goto not_enough_data;
763 offset +=
sizeof(uint32_t);
765 offset +=
sizeof(uint32_t);
766 object->count =
object->stop -
object->start + 1;
777 goto not_enough_data;
779 object->count = buf[
offset];
780 offset +=
sizeof(uint8_t);
786 goto not_enough_data;
789 offset +=
sizeof(uint16_t);
796 goto not_enough_data;
799 offset +=
sizeof(uint32_t);
806 goto not_enough_data;
808 object->count = *(uint8_t *)(buf +
offset);
809 offset +=
sizeof(uint8_t);
852 static void DNP3HandleUserDataRequest(
DNP3State *dnp3,
const uint8_t *input,
857 DNP3ApplicationHeader *ah;
860 lh = (DNP3LinkHeader *)input;
862 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
863 input_len -
sizeof(DNP3LinkHeader))) {
867 th = input[
sizeof(DNP3LinkHeader)];
871 if (ttx->lh.src == lh->src && ttx->lh.dst == lh->dst && ttx->is_request && !ttx->done &&
888 ah = (DNP3ApplicationHeader *)(input +
sizeof(DNP3LinkHeader) +
897 tx = DNP3TxAlloc(dnp3,
true);
906 if (!DNP3ReassembleApplicationLayer(input +
sizeof(DNP3LinkHeader),
922 if (DNP3DecodeApplicationObjects(tx, tx->
buffer +
sizeof(DNP3ApplicationHeader),
928 static void DNP3HandleUserDataResponse(
DNP3State *dnp3,
const uint8_t *input,
933 DNP3ApplicationHeader *ah;
934 DNP3InternalInd *iin;
938 lh = (DNP3LinkHeader *)input;
939 offset +=
sizeof(DNP3LinkHeader);
941 if (!DNP3CheckUserDataCRCs(input +
offset, input_len -
offset)) {
949 if (ttx->lh.src == lh->src && ttx->lh.dst == lh->dst && !ttx->is_request &&
966 ah = (DNP3ApplicationHeader *)(input +
offset);
967 offset +=
sizeof(DNP3ApplicationHeader);
968 iin = (DNP3InternalInd *)(input +
offset);
970 tx = DNP3TxAlloc(dnp3,
false);
982 if (!DNP3ReassembleApplicationLayer(input +
sizeof(DNP3LinkHeader),
994 offset =
sizeof(DNP3ApplicationHeader) +
sizeof(DNP3InternalInd);
995 if (DNP3DecodeApplicationObjects(
1007 static int DNP3HandleRequestLinkLayer(
DNP3State *dnp3,
const uint8_t *input,
1011 uint32_t processed = 0;
1016 if (input_len <
sizeof(DNP3LinkHeader)) {
1020 DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1022 if (!DNP3CheckStartBytes(header)) {
1026 if (!DNP3CheckLinkHeaderCRC(header)) {
1031 uint32_t frame_len = DNP3CalculateLinkLength(header->len);
1032 if (frame_len == 0) {
1036 if (input_len < frame_len) {
1042 if (!DNP3IsUserData(header)) {
1048 if (!DNP3HasUserData(header, STREAM_TOSERVER)) {
1053 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
1054 frame_len -
sizeof(DNP3LinkHeader))) {
1059 DNP3HandleUserDataRequest(dnp3, input, frame_len);
1064 input_len -= frame_len;
1065 processed += frame_len;
1084 StreamSlice stream_slice,
void *local_data)
1091 const uint8_t *input = StreamSliceGetData(&stream_slice);
1092 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1094 if (input_len == 0) {
1099 if (!DNP3BufferAdd(buffer, input, input_len)) {
1102 processed = DNP3HandleRequestLinkLayer(dnp3,
1105 if (processed < 0) {
1108 buffer->
offset += processed;
1109 DNP3BufferTrim(buffer);
1112 processed = DNP3HandleRequestLinkLayer(dnp3, input, input_len);
1113 if (processed < 0) {
1114 SCLogDebug(
"Failed to process request link layer.");
1119 input_len -= processed;
1123 if (!DNP3BufferAdd(buffer, input, input_len)) {
1133 DNP3BufferReset(buffer);
1143 static int DNP3HandleResponseLinkLayer(
DNP3State *dnp3,
const uint8_t *input,
1147 uint32_t processed = 0;
1152 if (input_len <
sizeof(DNP3LinkHeader)) {
1156 DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1158 if (!DNP3CheckStartBytes(header)) {
1162 if (!DNP3CheckLinkHeaderCRC(header)) {
1168 uint32_t frame_len = DNP3CalculateLinkLength(header->len);
1169 if (frame_len == 0) {
1173 if (input_len < frame_len) {
1179 if (!DNP3IsUserData(header)) {
1185 if (!DNP3HasUserData(header, STREAM_TOCLIENT)) {
1190 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
1191 frame_len -
sizeof(DNP3LinkHeader))) {
1196 DNP3HandleUserDataResponse(dnp3, input, frame_len);
1201 input_len -= frame_len;
1202 processed += frame_len;
1222 StreamSlice stream_slice,
void *local_data)
1230 const uint8_t *input = StreamSliceGetData(&stream_slice);
1231 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1234 if (!DNP3BufferAdd(buffer, input, input_len)) {
1237 processed = DNP3HandleResponseLinkLayer(dnp3,
1240 if (processed < 0) {
1243 buffer->
offset += processed;
1244 DNP3BufferTrim(buffer);
1249 if (DNP3ContainsBanner(input, input_len)) {
1253 processed = DNP3HandleResponseLinkLayer(dnp3, input, input_len);
1254 if (processed < 0) {
1258 input_len -= processed;
1262 if (!DNP3BufferAdd(buffer, input, input_len)) {
1274 DNP3BufferReset(buffer);
1278 static void *DNP3GetTx(
void *alstate, uint64_t tx_id)
1283 uint64_t tx_num = tx_id + 1;
1290 if (tx_num != tx->
tx_num) {
1299 static uint64_t DNP3GetTxCnt(
void *state)
1302 uint64_t count = ((uint64_t)((
DNP3State *)state)->transaction_max);
1309 static void DNP3TxFreeObjectList(DNP3ObjectList *objects)
1315 DNP3ObjectFree(
object);
1326 if (tx->
buffer != NULL) {
1330 SCAppLayerTxDataCleanup(&tx->
tx_data);
1332 DNP3TxFreeObjectList(&tx->
objects);
1344 static void DNP3StateTxFree(
void *state, uint64_t tx_id)
1349 uint64_t tx_num = tx_id + 1;
1353 if (tx->
tx_num != tx_num) {
1357 if (tx == dnp3->
curr) {
1361 if (tx->
tx_data.events != NULL) {
1386 static void DNP3StateFree(
void *state)
1391 if (state != NULL) {
1392 while ((tx =
TAILQ_FIRST(&dnp3->tx_list)) != NULL) {
1410 static int DNP3GetAlstateProgress(
void *tx, uint8_t direction)
1419 SCLogDebug(
"flooded: returning tx as done.");
1432 static int DNP3StateGetEventInfo(
1433 const char *event_name, uint8_t *event_id, AppLayerEventType *event_type)
1436 *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
1445 static int DNP3StateGetEventInfoById(
1446 uint8_t event_id,
const char **event_name, AppLayerEventType *event_type)
1449 if (*event_name == NULL) {
1451 "the DNP3 enum event map table.",
1456 *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
1467 static AppLayerStateData *DNP3GetStateData(
void *vstate)
1480 switch (prefix_code) {
1491 static AppLayerGetTxIterTuple DNP3GetTxIterator(
const uint8_t ipproto,
const AppProto alproto,
1495 AppLayerGetTxIterTuple no_tuple = { NULL, 0,
false };
1498 if (state->
un.
ptr == NULL) {
1504 while (tx_ptr->
tx_num < min_tx_id + 1) {
1510 if (tx_ptr->
tx_num >= max_tx_id + 1) {
1514 AppLayerGetTxIterTuple tuple = {
1516 .tx_id = tx_ptr->
tx_num - 1,
1517 .has_next = (state->
un.
ptr != NULL),
1532 const char *proto_name =
"dnp3";
1539 ALPROTO_DNP3, 0,
sizeof(DNP3LinkHeader), STREAM_TOSERVER,
1540 DNP3ProbingParser, DNP3ProbingParser);
1545 DNP3ProbingParser, DNP3ProbingParser)) {
1551 SCLogConfig(
"Protocol detection and parser disabled for DNP3.");
1565 DNP3StateAlloc, DNP3StateFree);
1574 DNP3GetAlstateProgress);
1578 DNP3StateGetEventInfo);
1580 DNP3StateGetEventInfoById);
1588 "Protocol detection still on.", proto_name);
1607 static void DNP3FixCrc(uint8_t *data, uint32_t
len)
1609 uint32_t block_size;
1617 uint16_t
crc = DNP3ComputeCRC(data, block_size);
1618 data[block_size + 1] = (
crc >> 8) & 0xff;
1619 data[block_size] =
crc & 0xff;
1628 static int DNP3ParserTestCheckCRC(
void)
1630 uint8_t request[] = {
1632 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1639 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1640 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1644 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1648 FAIL_IF(!DNP3CheckCRC(request,
sizeof(DNP3LinkHeader)));
1651 FAIL_IF(!DNP3CheckCRC(request +
sizeof(DNP3LinkHeader),
1654 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1657 FAIL_IF(DNP3CheckCRC(request,
sizeof(DNP3LinkHeader)));
1661 request[
sizeof(DNP3LinkHeader) + 3]++;
1662 FAIL_IF(DNP3CheckCRC(request +
sizeof(DNP3LinkHeader),
1672 static int DNP3CheckUserDataCRCsTest(
void)
1675 uint8_t data_valid[] = {
1676 0xff, 0xc9, 0x05, 0x0c,
1677 0x01, 0x28, 0x01, 0x00,
1678 0x00, 0x00, 0x01, 0x01,
1679 0x01, 0x00, 0x00, 0x00,
1682 0xff, 0xc9, 0x05, 0x0c,
1683 0x01, 0x28, 0x01, 0x00,
1684 0x00, 0x00, 0x01, 0x01,
1685 0x01, 0x00, 0x00, 0x00,
1688 0xff, 0xc9, 0x05, 0x0c,
1689 0x01, 0x28, 0x01, 0x00,
1690 0x00, 0x00, 0x01, 0x01,
1691 0x01, 0x00, 0x00, 0x00,
1694 0x00, 0x00, 0x00, 0x00,
1698 FAIL_IF(!DNP3CheckUserDataCRCs(data_valid,
sizeof(data_valid)));
1700 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1702 uint8_t data_invalid[] = {
1703 0xff, 0xc9, 0x05, 0x0c,
1704 0x01, 0x28, 0x01, 0x00,
1705 0x00, 0x00, 0x01, 0x01,
1706 0x01, 0x00, 0x00, 0x00,
1709 0xff, 0xc9, 0x05, 0x0c,
1710 0x01, 0x28, 0x01, 0x00,
1711 0x00, 0x00, 0x01, 0x01,
1712 0x01, 0x00, 0x00, 0x00,
1715 0xff, 0xc9, 0x05, 0x0c,
1716 0x01, 0x28, 0x01, 0x00,
1717 0x00, 0x00, 0x01, 0x01,
1718 0x01, 0x00, 0x00, 0x00,
1721 0x00, 0x00, 0x00, 0x00,
1725 FAIL_IF(DNP3CheckUserDataCRCs(data_invalid,
sizeof(data_invalid)));
1728 uint8_t one_byte_nocrc[] = { 0x01 };
1729 FAIL_IF(DNP3CheckUserDataCRCs(one_byte_nocrc,
sizeof(one_byte_nocrc)));
1732 uint8_t two_byte_nocrc[] = { 0x01, 0x02 };
1733 FAIL_IF(DNP3CheckUserDataCRCs(two_byte_nocrc,
sizeof(two_byte_nocrc)));
1737 uint8_t three_bytes_good_crc[] = { 0x00, 0x00, 0x00 };
1738 *(uint16_t *)(three_bytes_good_crc + 1) = DNP3ComputeCRC(
1739 three_bytes_good_crc, 1);
1740 FAIL_IF(!DNP3CheckUserDataCRCs(three_bytes_good_crc,
1741 sizeof(three_bytes_good_crc)));
1753 static int DNP3CalculateLinkLengthTest(
void)
1756 FAIL_IF(DNP3CalculateLinkLength(0) != 0);
1757 FAIL_IF(DNP3CalculateLinkLength(1) != 0);
1758 FAIL_IF(DNP3CalculateLinkLength(2) != 0);
1759 FAIL_IF(DNP3CalculateLinkLength(3) != 0);
1760 FAIL_IF(DNP3CalculateLinkLength(4) != 0);
1763 FAIL_IF(DNP3CalculateLinkLength(5) != 10);
1766 FAIL_IF(DNP3CalculateLinkLength(21) != 28);
1769 FAIL_IF(DNP3CalculateLinkLength(37) != 46);
1773 FAIL_IF(DNP3CalculateLinkLength(38) != 49);
1776 FAIL_IF(DNP3CalculateLinkLength(255) != 292);
1785 static int DNP3CalculateTransportLengthWithoutCRCsTest(
void)
1787 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(0) != -1);
1788 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(1) != -1);
1789 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(2) != 0);
1790 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(3) != 1);
1791 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(16) != 14);
1792 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(17) != 15);
1793 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(18) != 16);
1796 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(19) != -1);
1800 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(20) != 16);
1802 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(21) != 17);
1810 static int DNP3ParserCheckLinkHeaderCRC(
void)
1813 uint8_t request[] = {
1815 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1822 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1823 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1824 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1827 DNP3LinkHeader *header = (DNP3LinkHeader *)request;
1828 FAIL_IF(!DNP3CheckLinkHeaderCRC(header));
1830 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1833 FAIL_IF(DNP3CheckLinkHeaderCRC(header));
1842 static int DNP3ReassembleApplicationLayerTest01(
void)
1844 uint32_t reassembled_len = 0;
1845 uint8_t *output = NULL;
1847 uint8_t payload[] = {
1849 0xff, 0xc9, 0x05, 0x0c,
1850 0x01, 0x28, 0x01, 0x00,
1851 0x00, 0x00, 0x01, 0x01,
1852 0x01, 0x00, 0x00, 0x00,
1855 0xff, 0xc9, 0x05, 0x0c,
1856 0x01, 0x28, 0x01, 0x00,
1857 0x00, 0x00, 0x01, 0x01,
1858 0x01, 0x00, 0x00, 0x00,
1861 0xff, 0xc9, 0x05, 0x0c,
1862 0x01, 0x28, 0x01, 0x00,
1863 0x00, 0x00, 0x01, 0x01,
1864 0x01, 0x00, 0x00, 0x00,
1867 0x00, 0x00, 0x00, 0x00,
1872 uint8_t expected[] = {
1874 0x01, 0x28, 0x01, 0x00,
1875 0x00, 0x00, 0x01, 0x01,
1876 0x01, 0x00, 0x00, 0x00,
1878 0xff, 0xc9, 0x05, 0x0c,
1879 0x01, 0x28, 0x01, 0x00,
1880 0x00, 0x00, 0x01, 0x01,
1881 0x01, 0x00, 0x00, 0x00,
1883 0xff, 0xc9, 0x05, 0x0c,
1884 0x01, 0x28, 0x01, 0x00,
1885 0x00, 0x00, 0x01, 0x01,
1886 0x01, 0x00, 0x00, 0x00,
1888 0x00, 0x00, 0x00, 0x00,
1894 FAIL_IF(!DNP3ReassembleApplicationLayer(payload,
1895 sizeof(payload), &output, &reassembled_len));
1897 FAIL_IF(reassembled_len !=
sizeof(expected));
1898 FAIL_IF(memcmp(expected, output, reassembled_len));
1902 reassembled_len = 0;
1904 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 1, &output,
1907 FAIL_IF(reassembled_len != 0);
1910 reassembled_len = 0;
1912 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 2, &output,
1915 FAIL_IF(reassembled_len != 0);
1919 reassembled_len = 0;
1921 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 3, &output,
1924 FAIL_IF(reassembled_len != 0);
1927 reassembled_len = 0;
1929 FAIL_IF(!DNP3ReassembleApplicationLayer(payload, 4, &output,
1932 FAIL_IF(reassembled_len != 1);
1935 uint8_t short_payload1[] = {
1937 0xff, 0xc9, 0x05, 0x0c,
1938 0x01, 0x28, 0x01, 0x00,
1939 0x00, 0x00, 0x01, 0x01,
1940 0x01, 0x00, 0x00, 0x00,
1943 0xff, 0xc9, 0x05, 0x0c,
1944 0x01, 0x28, 0x01, 0x00,
1945 0x00, 0x00, 0x01, 0x01,
1946 0x01, 0x00, 0x00, 0x00,
1949 0xff, 0xc9, 0x05, 0x0c,
1950 0x01, 0x28, 0x01, 0x00,
1951 0x00, 0x00, 0x01, 0x01,
1952 0x01, 0x00, 0x00, 0x00,
1957 reassembled_len = 0;
1958 FAIL_IF(DNP3ReassembleApplicationLayer(short_payload1,
1959 sizeof(short_payload1), &output, &reassembled_len));
1962 uint8_t short_payload2[] = {
1964 0xff, 0xc9, 0x05, 0x0c,
1965 0x01, 0x28, 0x01, 0x00,
1966 0x00, 0x00, 0x01, 0x01,
1967 0x01, 0x00, 0x00, 0x00,
1970 0xff, 0xc9, 0x05, 0x0c,
1971 0x01, 0x28, 0x01, 0x00,
1972 0x00, 0x00, 0x01, 0x01,
1973 0x01, 0x00, 0x00, 0x00,
1976 0xff, 0xc9, 0x05, 0x0c,
1977 0x01, 0x28, 0x01, 0x00,
1978 0x00, 0x00, 0x01, 0x01,
1979 0x01, 0x00, 0x00, 0x00,
1984 reassembled_len = 0;
1985 FAIL_IF(DNP3ReassembleApplicationLayer(short_payload2,
1986 sizeof(short_payload2), &output, &reassembled_len));
1994 static int DNP3ProbingParserTest(
void)
1997 0x05, 0x64, 0x05, 0xc9, 0x03, 0x00, 0x04, 0x00,
2003 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt,
sizeof(pkt), &rdir) !=
ALPROTO_DNP3);
2006 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt,
sizeof(DNP3LinkHeader) - 1, &rdir) !=
ALPROTO_UNKNOWN);
2020 char mybanner[] =
"Welcome to DNP3 SCADA.";
2021 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, (uint8_t *)mybanner,
sizeof(mybanner) - 1,
2023 FAIL_IF(rdir != STREAM_TOCLIENT);
2031 static int DNP3ParserTestRequestResponse(
void)
2035 uint8_t request[] = {
2037 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2044 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2045 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2046 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2049 uint8_t response[] = {
2051 0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2058 0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2059 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2060 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2068 memset(&flow, 0,
sizeof(flow));
2069 memset(&ssn, 0,
sizeof(ssn));
2072 flow.
proto = IPPROTO_TCP;
2079 STREAM_TOSERVER, request,
sizeof(request)));
2095 STREAM_TOCLIENT, response,
sizeof(response)));
2114 static int DNP3ParserTestUnsolicitedResponseConfirm(
void)
2119 uint8_t response[] = {
2120 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2121 0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2122 0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2123 0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9
2127 uint8_t confirm[] = {
2128 0x05, 0x64, 0x08, 0xc4, 0x02, 0x00,
2129 0x01, 0x00, 0xd3, 0xb7, 0xc0, 0xda, 0x00, 0x6a,
2137 memset(&flow, 0,
sizeof(flow));
2138 memset(&ssn, 0,
sizeof(ssn));
2141 flow.
proto = IPPROTO_TCP;
2148 STREAM_TOCLIENT, response,
sizeof(response)));
2163 STREAM_TOSERVER, confirm,
sizeof(confirm)));
2184 static int DNP3ParserTestFlooded(
void)
2188 uint8_t request[] = {
2190 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2197 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2198 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2199 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2206 memset(&flow, 0,
sizeof(flow));
2207 memset(&ssn, 0,
sizeof(ssn));
2210 flow.
proto = IPPROTO_TCP;
2217 STREAM_TOSERVER, request,
sizeof(request)));
2231 FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2236 STREAM_TOSERVER, request,
sizeof(request)));
2240 FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2245 STREAM_TOSERVER, request,
sizeof(request)));
2250 FAIL_IF(!DNP3GetAlstateProgress(tx, 0));
2265 static int DNP3ParserTestPartialFrame(
void)
2271 uint8_t request_partial1[] = {
2273 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2280 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2283 uint8_t request_partial2[] = {
2285 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2286 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2289 uint8_t response_partial1[] = {
2291 0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2298 0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2301 uint8_t response_partial2[] = {
2302 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2303 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2311 memset(&flow, 0,
sizeof(flow));
2312 memset(&ssn, 0,
sizeof(ssn));
2314 flow.
proto = IPPROTO_TCP;
2322 STREAM_TOSERVER, request_partial1,
sizeof(request_partial1));
2332 sizeof(request_partial1)));
2336 FAIL_IF(DNP3GetTx(state, 0) != NULL);
2341 STREAM_TOSERVER, request_partial2,
sizeof(request_partial2));
2351 tx = DNP3GetTx(state, 0);
2362 STREAM_TOCLIENT, response_partial1,
sizeof(response_partial1));
2367 tx = DNP3GetTx(state, 1);
2373 STREAM_TOCLIENT, response_partial2,
sizeof(response_partial2));
2382 tx = DNP3GetTx(state, 1);
2396 static int DNP3ParserTestMultiFrame(
void)
2401 uint8_t unsol_response1[] = {
2402 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2403 0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2404 0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2405 0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9,
2409 uint8_t unsol_response2[] = {
2410 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2411 0x89, 0xe5, 0xc5, 0xfb, 0x82, 0x00, 0x00, 0x02,
2412 0x02, 0x17, 0x01, 0x0c, 0x01, 0xd8, 0x75, 0xd8,
2413 0x32, 0x4c, 0xc9, 0x3c, 0x01, 0xa1, 0xc9,
2416 uint8_t combined[
sizeof(unsol_response1) +
sizeof(unsol_response2)];
2417 memcpy(combined, unsol_response1,
sizeof(unsol_response1));
2418 memcpy(combined +
sizeof(unsol_response1), unsol_response2,
2419 sizeof(unsol_response2));
2426 memset(&flow, 0,
sizeof(flow));
2427 memset(&ssn, 0,
sizeof(ssn));
2429 flow.
proto = IPPROTO_TCP;
2435 STREAM_TOCLIENT, combined,
sizeof(combined));
2457 static int DNP3ParserTestParsePDU01(
void)
2461 const uint8_t pkt[] = {
2463 0x0b, 0xc4, 0x17, 0x00, 0xef, 0xff, 0xc4, 0x8f,
2464 0xe1, 0xc8, 0x01, 0x01, 0x00, 0x06, 0x77, 0x6e
2468 int pdus = DNP3HandleRequestLinkLayer(dnp3state, pkt,
sizeof(pkt));
2478 DNP3StateFree(dnp3state);
2485 static int DNP3ParserDecodeG70V3Test(
void)
2487 const uint8_t pkt[] = {
2489 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00, 0xc7, 0xee,
2490 0xc7, 0xc9, 0x1b, 0x46, 0x03, 0x5b, 0x01, 0x55,
2491 0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2492 0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2493 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2494 0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2495 0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2496 0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2497 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2498 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2499 0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2500 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2501 0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2502 0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2508 int bytes = DNP3HandleRequestLinkLayer(dnp3state, pkt,
sizeof(pkt));
2509 FAIL_IF(bytes !=
sizeof(pkt));
2528 "C:/temp/DNPDeviceConfiguration written to Remote Device.xml") == 0);
2529 DNP3StateFree(dnp3state);
2536 static int DNP3ParserUnknownEventAlertTest(
void)
2540 0x05, 0x64, 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00,
2550 0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2551 0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2552 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2553 0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2554 0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2555 0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2556 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2557 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2558 0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2559 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2560 0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2561 0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2565 DNP3FixCrc(pkt + 10,
sizeof(pkt) - 10);
2569 int bytes = DNP3HandleRequestLinkLayer(dnp3state, pkt,
sizeof(pkt));
2570 FAIL_IF(bytes !=
sizeof(pkt));
2572 DNP3StateFree(dnp3state);
2579 static int DNP3ParserIncorrectUserData(
void)
2581 uint8_t packet_bytes[] = {
2582 0x05, 0x64, 0x08, 0xc4, 0x03, 0x00, 0x04, 0x00,
2583 0xbf, 0xe9, 0xc1, 0xc1, 0x82, 0xc5, 0xee
2589 memset(&flow, 0,
sizeof(flow));
2590 memset(&ssn, 0,
sizeof(ssn));
2592 flow.
proto = IPPROTO_TCP;
2597 STREAM_TOCLIENT, packet_bytes,
sizeof(packet_bytes));
2612 UtRegisterTest(
"DNP3ParserTestCheckCRC", DNP3ParserTestCheckCRC);
2614 DNP3ParserCheckLinkHeaderCRC);
2615 UtRegisterTest(
"DNP3CheckUserDataCRCsTest", DNP3CheckUserDataCRCsTest);
2616 UtRegisterTest(
"DNP3CalculateLinkLengthTest", DNP3CalculateLinkLengthTest);
2618 DNP3CalculateTransportLengthWithoutCRCsTest);
2620 DNP3ReassembleApplicationLayerTest01);
2623 DNP3ParserTestRequestResponse);
2625 DNP3ParserTestUnsolicitedResponseConfirm);
2626 UtRegisterTest(
"DNP3ParserTestPartialFrame", DNP3ParserTestPartialFrame);
2627 UtRegisterTest(
"DNP3ParserTestMultiFrame", DNP3ParserTestMultiFrame);
2629 UtRegisterTest(
"DNP3ParserTestParsePDU01", DNP3ParserTestParsePDU01);
2630 UtRegisterTest(
"DNP3ParserDecodeG70V3Test", DNP3ParserDecodeG70V3Test);
2632 DNP3ParserUnknownEventAlertTest);
2633 UtRegisterTest(
"DNP3ParserIncorrectUserData", DNP3ParserIncorrectUserData);