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 &&
887 ah = (DNP3ApplicationHeader *)(input +
sizeof(DNP3LinkHeader) +
896 tx = DNP3TxAlloc(dnp3,
true);
905 if (!DNP3ReassembleApplicationLayer(input +
sizeof(DNP3LinkHeader),
921 if (DNP3DecodeApplicationObjects(tx, tx->
buffer +
sizeof(DNP3ApplicationHeader),
927 static void DNP3HandleUserDataResponse(
DNP3State *dnp3,
const uint8_t *input,
932 DNP3ApplicationHeader *ah;
933 DNP3InternalInd *iin;
937 lh = (DNP3LinkHeader *)input;
938 offset +=
sizeof(DNP3LinkHeader);
940 if (!DNP3CheckUserDataCRCs(input +
offset, input_len -
offset)) {
948 if (ttx->lh.src == lh->src && ttx->lh.dst == lh->dst && !ttx->is_request &&
964 ah = (DNP3ApplicationHeader *)(input +
offset);
965 offset +=
sizeof(DNP3ApplicationHeader);
966 iin = (DNP3InternalInd *)(input +
offset);
968 tx = DNP3TxAlloc(dnp3,
false);
980 if (!DNP3ReassembleApplicationLayer(input +
sizeof(DNP3LinkHeader),
992 offset =
sizeof(DNP3ApplicationHeader) +
sizeof(DNP3InternalInd);
993 if (DNP3DecodeApplicationObjects(
1005 static int DNP3HandleRequestLinkLayer(
DNP3State *dnp3,
const uint8_t *input,
1009 uint32_t processed = 0;
1014 if (input_len <
sizeof(DNP3LinkHeader)) {
1018 DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1020 if (!DNP3CheckStartBytes(header)) {
1024 if (!DNP3CheckLinkHeaderCRC(header)) {
1029 uint32_t frame_len = DNP3CalculateLinkLength(header->len);
1030 if (frame_len == 0) {
1034 if (input_len < frame_len) {
1040 if (!DNP3IsUserData(header)) {
1046 if (!DNP3HasUserData(header, STREAM_TOSERVER)) {
1051 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
1052 frame_len -
sizeof(DNP3LinkHeader))) {
1057 DNP3HandleUserDataRequest(dnp3, input, frame_len);
1062 input_len -= frame_len;
1063 processed += frame_len;
1082 StreamSlice stream_slice,
void *local_data)
1089 const uint8_t *input = StreamSliceGetData(&stream_slice);
1090 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1092 if (input_len == 0) {
1097 if (!DNP3BufferAdd(buffer, input, input_len)) {
1100 processed = DNP3HandleRequestLinkLayer(dnp3,
1103 if (processed < 0) {
1106 buffer->
offset += processed;
1107 DNP3BufferTrim(buffer);
1110 processed = DNP3HandleRequestLinkLayer(dnp3, input, input_len);
1111 if (processed < 0) {
1112 SCLogDebug(
"Failed to process request link layer.");
1117 input_len -= processed;
1121 if (!DNP3BufferAdd(buffer, input, input_len)) {
1131 DNP3BufferReset(buffer);
1141 static int DNP3HandleResponseLinkLayer(
DNP3State *dnp3,
const uint8_t *input,
1145 uint32_t processed = 0;
1150 if (input_len <
sizeof(DNP3LinkHeader)) {
1154 DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1156 if (!DNP3CheckStartBytes(header)) {
1160 if (!DNP3CheckLinkHeaderCRC(header)) {
1166 uint32_t frame_len = DNP3CalculateLinkLength(header->len);
1167 if (frame_len == 0) {
1171 if (input_len < frame_len) {
1177 if (!DNP3IsUserData(header)) {
1183 if (!DNP3HasUserData(header, STREAM_TOCLIENT)) {
1188 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
1189 frame_len -
sizeof(DNP3LinkHeader))) {
1194 DNP3HandleUserDataResponse(dnp3, input, frame_len);
1199 input_len -= frame_len;
1200 processed += frame_len;
1220 StreamSlice stream_slice,
void *local_data)
1228 const uint8_t *input = StreamSliceGetData(&stream_slice);
1229 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1232 if (!DNP3BufferAdd(buffer, input, input_len)) {
1235 processed = DNP3HandleResponseLinkLayer(dnp3,
1238 if (processed < 0) {
1241 buffer->
offset += processed;
1242 DNP3BufferTrim(buffer);
1247 if (DNP3ContainsBanner(input, input_len)) {
1251 processed = DNP3HandleResponseLinkLayer(dnp3, input, input_len);
1252 if (processed < 0) {
1256 input_len -= processed;
1260 if (!DNP3BufferAdd(buffer, input, input_len)) {
1272 DNP3BufferReset(buffer);
1276 static void *DNP3GetTx(
void *alstate, uint64_t tx_id)
1281 uint64_t tx_num = tx_id + 1;
1288 if (tx_num != tx->
tx_num) {
1297 static uint64_t DNP3GetTxCnt(
void *state)
1300 uint64_t count = ((uint64_t)((
DNP3State *)state)->transaction_max);
1307 static void DNP3TxFreeObjectList(DNP3ObjectList *objects)
1313 DNP3ObjectFree(
object);
1324 if (tx->
buffer != NULL) {
1330 if (tx->
tx_data.de_state != NULL) {
1334 DNP3TxFreeObjectList(&tx->
objects);
1346 static void DNP3StateTxFree(
void *state, uint64_t tx_id)
1351 uint64_t tx_num = tx_id + 1;
1355 if (tx->
tx_num != tx_num) {
1359 if (tx == dnp3->
curr) {
1363 if (tx->
tx_data.events != NULL) {
1388 static void DNP3StateFree(
void *state)
1393 if (state != NULL) {
1394 while ((tx =
TAILQ_FIRST(&dnp3->tx_list)) != NULL) {
1412 static int DNP3GetAlstateProgress(
void *tx, uint8_t direction)
1421 SCLogDebug(
"flooded: returning tx as done.");
1434 static int DNP3StateGetEventInfo(
1435 const char *event_name, uint8_t *event_id, AppLayerEventType *event_type)
1438 *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
1447 static int DNP3StateGetEventInfoById(
1448 uint8_t event_id,
const char **event_name, AppLayerEventType *event_type)
1451 if (*event_name == NULL) {
1453 "the DNP3 enum event map table.",
1458 *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
1469 static AppLayerStateData *DNP3GetStateData(
void *vstate)
1482 switch (prefix_code) {
1493 static AppLayerGetTxIterTuple DNP3GetTxIterator(
const uint8_t ipproto,
const AppProto alproto,
1497 AppLayerGetTxIterTuple no_tuple = { NULL, 0,
false };
1500 if (state->
un.
ptr == NULL) {
1506 while (tx_ptr->
tx_num < min_tx_id + 1) {
1512 if (tx_ptr->
tx_num >= max_tx_id + 1) {
1516 AppLayerGetTxIterTuple tuple = {
1518 .tx_id = tx_ptr->
tx_num - 1,
1519 .has_next = (state->
un.
ptr != NULL),
1534 const char *proto_name =
"dnp3";
1541 ALPROTO_DNP3, 0,
sizeof(DNP3LinkHeader), STREAM_TOSERVER,
1542 DNP3ProbingParser, DNP3ProbingParser);
1547 DNP3ProbingParser, DNP3ProbingParser)) {
1553 SCLogConfig(
"Protocol detection and parser disabled for DNP3.");
1567 DNP3StateAlloc, DNP3StateFree);
1576 DNP3GetAlstateProgress);
1580 DNP3StateGetEventInfo);
1582 DNP3StateGetEventInfoById);
1590 "Protocol detection still on.", proto_name);
1609 static void DNP3FixCrc(uint8_t *data, uint32_t
len)
1611 uint32_t block_size;
1619 uint16_t
crc = DNP3ComputeCRC(data, block_size);
1620 data[block_size + 1] = (
crc >> 8) & 0xff;
1621 data[block_size] =
crc & 0xff;
1630 static int DNP3ParserTestCheckCRC(
void)
1632 uint8_t request[] = {
1634 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1641 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1642 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1646 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1650 FAIL_IF(!DNP3CheckCRC(request,
sizeof(DNP3LinkHeader)));
1653 FAIL_IF(!DNP3CheckCRC(request +
sizeof(DNP3LinkHeader),
1656 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1659 FAIL_IF(DNP3CheckCRC(request,
sizeof(DNP3LinkHeader)));
1663 request[
sizeof(DNP3LinkHeader) + 3]++;
1664 FAIL_IF(DNP3CheckCRC(request +
sizeof(DNP3LinkHeader),
1674 static int DNP3CheckUserDataCRCsTest(
void)
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,
1684 0xff, 0xc9, 0x05, 0x0c,
1685 0x01, 0x28, 0x01, 0x00,
1686 0x00, 0x00, 0x01, 0x01,
1687 0x01, 0x00, 0x00, 0x00,
1690 0xff, 0xc9, 0x05, 0x0c,
1691 0x01, 0x28, 0x01, 0x00,
1692 0x00, 0x00, 0x01, 0x01,
1693 0x01, 0x00, 0x00, 0x00,
1696 0x00, 0x00, 0x00, 0x00,
1700 FAIL_IF(!DNP3CheckUserDataCRCs(data_valid,
sizeof(data_valid)));
1702 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
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,
1711 0xff, 0xc9, 0x05, 0x0c,
1712 0x01, 0x28, 0x01, 0x00,
1713 0x00, 0x00, 0x01, 0x01,
1714 0x01, 0x00, 0x00, 0x00,
1717 0xff, 0xc9, 0x05, 0x0c,
1718 0x01, 0x28, 0x01, 0x00,
1719 0x00, 0x00, 0x01, 0x01,
1720 0x01, 0x00, 0x00, 0x00,
1723 0x00, 0x00, 0x00, 0x00,
1727 FAIL_IF(DNP3CheckUserDataCRCs(data_invalid,
sizeof(data_invalid)));
1730 uint8_t one_byte_nocrc[] = { 0x01 };
1731 FAIL_IF(DNP3CheckUserDataCRCs(one_byte_nocrc,
sizeof(one_byte_nocrc)));
1734 uint8_t two_byte_nocrc[] = { 0x01, 0x02 };
1735 FAIL_IF(DNP3CheckUserDataCRCs(two_byte_nocrc,
sizeof(two_byte_nocrc)));
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)));
1755 static int DNP3CalculateLinkLengthTest(
void)
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);
1765 FAIL_IF(DNP3CalculateLinkLength(5) != 10);
1768 FAIL_IF(DNP3CalculateLinkLength(21) != 28);
1771 FAIL_IF(DNP3CalculateLinkLength(37) != 46);
1775 FAIL_IF(DNP3CalculateLinkLength(38) != 49);
1778 FAIL_IF(DNP3CalculateLinkLength(255) != 292);
1787 static int DNP3CalculateTransportLengthWithoutCRCsTest(
void)
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);
1798 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(19) != -1);
1802 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(20) != 16);
1804 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(21) != 17);
1812 static int DNP3ParserCheckLinkHeaderCRC(
void)
1815 uint8_t request[] = {
1817 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
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
1829 DNP3LinkHeader *header = (DNP3LinkHeader *)request;
1830 FAIL_IF(!DNP3CheckLinkHeaderCRC(header));
1832 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1835 FAIL_IF(DNP3CheckLinkHeaderCRC(header));
1844 static int DNP3ReassembleApplicationLayerTest01(
void)
1846 uint32_t reassembled_len = 0;
1847 uint8_t *output = NULL;
1849 uint8_t payload[] = {
1851 0xff, 0xc9, 0x05, 0x0c,
1852 0x01, 0x28, 0x01, 0x00,
1853 0x00, 0x00, 0x01, 0x01,
1854 0x01, 0x00, 0x00, 0x00,
1857 0xff, 0xc9, 0x05, 0x0c,
1858 0x01, 0x28, 0x01, 0x00,
1859 0x00, 0x00, 0x01, 0x01,
1860 0x01, 0x00, 0x00, 0x00,
1863 0xff, 0xc9, 0x05, 0x0c,
1864 0x01, 0x28, 0x01, 0x00,
1865 0x00, 0x00, 0x01, 0x01,
1866 0x01, 0x00, 0x00, 0x00,
1869 0x00, 0x00, 0x00, 0x00,
1874 uint8_t expected[] = {
1876 0x01, 0x28, 0x01, 0x00,
1877 0x00, 0x00, 0x01, 0x01,
1878 0x01, 0x00, 0x00, 0x00,
1880 0xff, 0xc9, 0x05, 0x0c,
1881 0x01, 0x28, 0x01, 0x00,
1882 0x00, 0x00, 0x01, 0x01,
1883 0x01, 0x00, 0x00, 0x00,
1885 0xff, 0xc9, 0x05, 0x0c,
1886 0x01, 0x28, 0x01, 0x00,
1887 0x00, 0x00, 0x01, 0x01,
1888 0x01, 0x00, 0x00, 0x00,
1890 0x00, 0x00, 0x00, 0x00,
1896 FAIL_IF(!DNP3ReassembleApplicationLayer(payload,
1897 sizeof(payload), &output, &reassembled_len));
1899 FAIL_IF(reassembled_len !=
sizeof(expected));
1900 FAIL_IF(memcmp(expected, output, reassembled_len));
1904 reassembled_len = 0;
1906 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 1, &output,
1909 FAIL_IF(reassembled_len != 0);
1912 reassembled_len = 0;
1914 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 2, &output,
1917 FAIL_IF(reassembled_len != 0);
1921 reassembled_len = 0;
1923 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 3, &output,
1926 FAIL_IF(reassembled_len != 0);
1929 reassembled_len = 0;
1931 FAIL_IF(!DNP3ReassembleApplicationLayer(payload, 4, &output,
1934 FAIL_IF(reassembled_len != 1);
1937 uint8_t short_payload1[] = {
1939 0xff, 0xc9, 0x05, 0x0c,
1940 0x01, 0x28, 0x01, 0x00,
1941 0x00, 0x00, 0x01, 0x01,
1942 0x01, 0x00, 0x00, 0x00,
1945 0xff, 0xc9, 0x05, 0x0c,
1946 0x01, 0x28, 0x01, 0x00,
1947 0x00, 0x00, 0x01, 0x01,
1948 0x01, 0x00, 0x00, 0x00,
1951 0xff, 0xc9, 0x05, 0x0c,
1952 0x01, 0x28, 0x01, 0x00,
1953 0x00, 0x00, 0x01, 0x01,
1954 0x01, 0x00, 0x00, 0x00,
1959 reassembled_len = 0;
1960 FAIL_IF(DNP3ReassembleApplicationLayer(short_payload1,
1961 sizeof(short_payload1), &output, &reassembled_len));
1964 uint8_t short_payload2[] = {
1966 0xff, 0xc9, 0x05, 0x0c,
1967 0x01, 0x28, 0x01, 0x00,
1968 0x00, 0x00, 0x01, 0x01,
1969 0x01, 0x00, 0x00, 0x00,
1972 0xff, 0xc9, 0x05, 0x0c,
1973 0x01, 0x28, 0x01, 0x00,
1974 0x00, 0x00, 0x01, 0x01,
1975 0x01, 0x00, 0x00, 0x00,
1978 0xff, 0xc9, 0x05, 0x0c,
1979 0x01, 0x28, 0x01, 0x00,
1980 0x00, 0x00, 0x01, 0x01,
1981 0x01, 0x00, 0x00, 0x00,
1986 reassembled_len = 0;
1987 FAIL_IF(DNP3ReassembleApplicationLayer(short_payload2,
1988 sizeof(short_payload2), &output, &reassembled_len));
1996 static int DNP3ProbingParserTest(
void)
1999 0x05, 0x64, 0x05, 0xc9, 0x03, 0x00, 0x04, 0x00,
2005 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt,
sizeof(pkt), &rdir) !=
ALPROTO_DNP3);
2008 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt,
sizeof(DNP3LinkHeader) - 1, &rdir) !=
ALPROTO_UNKNOWN);
2022 char mybanner[] =
"Welcome to DNP3 SCADA.";
2023 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, (uint8_t *)mybanner,
sizeof(mybanner) - 1,
2025 FAIL_IF(rdir != STREAM_TOCLIENT);
2033 static int DNP3ParserTestRequestResponse(
void)
2037 uint8_t request[] = {
2039 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
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
2051 uint8_t response[] = {
2053 0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
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,
2070 memset(&flow, 0,
sizeof(flow));
2071 memset(&ssn, 0,
sizeof(ssn));
2074 flow.
proto = IPPROTO_TCP;
2081 STREAM_TOSERVER, request,
sizeof(request)));
2097 STREAM_TOCLIENT, response,
sizeof(response)));
2116 static int DNP3ParserTestUnsolicitedResponseConfirm(
void)
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
2129 uint8_t confirm[] = {
2130 0x05, 0x64, 0x08, 0xc4, 0x02, 0x00,
2131 0x01, 0x00, 0xd3, 0xb7, 0xc0, 0xda, 0x00, 0x6a,
2139 memset(&flow, 0,
sizeof(flow));
2140 memset(&ssn, 0,
sizeof(ssn));
2143 flow.
proto = IPPROTO_TCP;
2150 STREAM_TOCLIENT, response,
sizeof(response)));
2165 STREAM_TOSERVER, confirm,
sizeof(confirm)));
2186 static int DNP3ParserTestFlooded(
void)
2190 uint8_t request[] = {
2192 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
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
2208 memset(&flow, 0,
sizeof(flow));
2209 memset(&ssn, 0,
sizeof(ssn));
2212 flow.
proto = IPPROTO_TCP;
2219 STREAM_TOSERVER, request,
sizeof(request)));
2233 FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2238 STREAM_TOSERVER, request,
sizeof(request)));
2242 FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2247 STREAM_TOSERVER, request,
sizeof(request)));
2252 FAIL_IF(!DNP3GetAlstateProgress(tx, 0));
2267 static int DNP3ParserTestPartialFrame(
void)
2273 uint8_t request_partial1[] = {
2275 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2282 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2285 uint8_t request_partial2[] = {
2287 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2288 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2291 uint8_t response_partial1[] = {
2293 0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2300 0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2303 uint8_t response_partial2[] = {
2304 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2305 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2313 memset(&flow, 0,
sizeof(flow));
2314 memset(&ssn, 0,
sizeof(ssn));
2316 flow.
proto = IPPROTO_TCP;
2324 STREAM_TOSERVER, request_partial1,
sizeof(request_partial1));
2334 sizeof(request_partial1)));
2338 FAIL_IF(DNP3GetTx(state, 0) != NULL);
2343 STREAM_TOSERVER, request_partial2,
sizeof(request_partial2));
2353 tx = DNP3GetTx(state, 0);
2364 STREAM_TOCLIENT, response_partial1,
sizeof(response_partial1));
2369 tx = DNP3GetTx(state, 1);
2375 STREAM_TOCLIENT, response_partial2,
sizeof(response_partial2));
2384 tx = DNP3GetTx(state, 1);
2398 static int DNP3ParserTestMultiFrame(
void)
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,
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,
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));
2428 memset(&flow, 0,
sizeof(flow));
2429 memset(&ssn, 0,
sizeof(ssn));
2431 flow.
proto = IPPROTO_TCP;
2437 STREAM_TOCLIENT, combined,
sizeof(combined));
2459 static int DNP3ParserTestParsePDU01(
void)
2463 const uint8_t pkt[] = {
2465 0x0b, 0xc4, 0x17, 0x00, 0xef, 0xff, 0xc4, 0x8f,
2466 0xe1, 0xc8, 0x01, 0x01, 0x00, 0x06, 0x77, 0x6e
2470 int pdus = DNP3HandleRequestLinkLayer(dnp3state, pkt,
sizeof(pkt));
2480 DNP3StateFree(dnp3state);
2487 static int DNP3ParserDecodeG70V3Test(
void)
2489 const uint8_t pkt[] = {
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,
2510 int bytes = DNP3HandleRequestLinkLayer(dnp3state, pkt,
sizeof(pkt));
2511 FAIL_IF(bytes !=
sizeof(pkt));
2530 "C:/temp/DNPDeviceConfiguration written to Remote Device.xml") == 0);
2531 DNP3StateFree(dnp3state);
2538 static int DNP3ParserUnknownEventAlertTest(
void)
2542 0x05, 0x64, 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00,
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,
2567 DNP3FixCrc(pkt + 10,
sizeof(pkt) - 10);
2571 int bytes = DNP3HandleRequestLinkLayer(dnp3state, pkt,
sizeof(pkt));
2572 FAIL_IF(bytes !=
sizeof(pkt));
2574 DNP3StateFree(dnp3state);
2581 static int DNP3ParserIncorrectUserData(
void)
2583 uint8_t packet_bytes[] = {
2584 0x05, 0x64, 0x08, 0xc4, 0x03, 0x00, 0x04, 0x00,
2585 0xbf, 0xe9, 0xc1, 0xc1, 0x82, 0xc5, 0xee
2591 memset(&flow, 0,
sizeof(flow));
2592 memset(&ssn, 0,
sizeof(ssn));
2594 flow.
proto = IPPROTO_TCP;
2599 STREAM_TOCLIENT, packet_bytes,
sizeof(packet_bytes));
2614 UtRegisterTest(
"DNP3ParserTestCheckCRC", DNP3ParserTestCheckCRC);
2616 DNP3ParserCheckLinkHeaderCRC);
2617 UtRegisterTest(
"DNP3CheckUserDataCRCsTest", DNP3CheckUserDataCRCsTest);
2618 UtRegisterTest(
"DNP3CalculateLinkLengthTest", DNP3CalculateLinkLengthTest);
2620 DNP3CalculateTransportLengthWithoutCRCsTest);
2622 DNP3ReassembleApplicationLayerTest01);
2625 DNP3ParserTestRequestResponse);
2627 DNP3ParserTestUnsolicitedResponseConfirm);
2628 UtRegisterTest(
"DNP3ParserTestPartialFrame", DNP3ParserTestPartialFrame);
2629 UtRegisterTest(
"DNP3ParserTestMultiFrame", DNP3ParserTestMultiFrame);
2631 UtRegisterTest(
"DNP3ParserTestParsePDU01", DNP3ParserTestParsePDU01);
2632 UtRegisterTest(
"DNP3ParserDecodeG70V3Test", DNP3ParserDecodeG70V3Test);
2634 DNP3ParserUnknownEventAlertTest);
2635 UtRegisterTest(
"DNP3ParserIncorrectUserData", DNP3ParserIncorrectUserData);