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) {
1332 if (tx->
tx_data.de_state != NULL) {
1336 DNP3TxFreeObjectList(&tx->
objects);
1348 static void DNP3StateTxFree(
void *state, uint64_t tx_id)
1353 uint64_t tx_num = tx_id + 1;
1357 if (tx->
tx_num != tx_num) {
1361 if (tx == dnp3->
curr) {
1365 if (tx->
tx_data.events != NULL) {
1390 static void DNP3StateFree(
void *state)
1395 if (state != NULL) {
1396 while ((tx =
TAILQ_FIRST(&dnp3->tx_list)) != NULL) {
1414 static int DNP3GetAlstateProgress(
void *tx, uint8_t direction)
1423 SCLogDebug(
"flooded: returning tx as done.");
1436 static int DNP3StateGetEventInfo(
1437 const char *event_name, uint8_t *event_id, AppLayerEventType *event_type)
1440 *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
1449 static int DNP3StateGetEventInfoById(
1450 uint8_t event_id,
const char **event_name, AppLayerEventType *event_type)
1453 if (*event_name == NULL) {
1455 "the DNP3 enum event map table.",
1460 *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
1471 static AppLayerStateData *DNP3GetStateData(
void *vstate)
1484 switch (prefix_code) {
1495 static AppLayerGetTxIterTuple DNP3GetTxIterator(
const uint8_t ipproto,
const AppProto alproto,
1499 AppLayerGetTxIterTuple no_tuple = { NULL, 0,
false };
1502 if (state->
un.
ptr == NULL) {
1508 while (tx_ptr->
tx_num < min_tx_id + 1) {
1514 if (tx_ptr->
tx_num >= max_tx_id + 1) {
1518 AppLayerGetTxIterTuple tuple = {
1520 .tx_id = tx_ptr->
tx_num - 1,
1521 .has_next = (state->
un.
ptr != NULL),
1536 const char *proto_name =
"dnp3";
1543 ALPROTO_DNP3, 0,
sizeof(DNP3LinkHeader), STREAM_TOSERVER,
1544 DNP3ProbingParser, DNP3ProbingParser);
1549 DNP3ProbingParser, DNP3ProbingParser)) {
1555 SCLogConfig(
"Protocol detection and parser disabled for DNP3.");
1569 DNP3StateAlloc, DNP3StateFree);
1578 DNP3GetAlstateProgress);
1582 DNP3StateGetEventInfo);
1584 DNP3StateGetEventInfoById);
1592 "Protocol detection still on.", proto_name);
1611 static void DNP3FixCrc(uint8_t *data, uint32_t
len)
1613 uint32_t block_size;
1621 uint16_t
crc = DNP3ComputeCRC(data, block_size);
1622 data[block_size + 1] = (
crc >> 8) & 0xff;
1623 data[block_size] =
crc & 0xff;
1632 static int DNP3ParserTestCheckCRC(
void)
1634 uint8_t request[] = {
1636 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1643 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1644 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1648 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1652 FAIL_IF(!DNP3CheckCRC(request,
sizeof(DNP3LinkHeader)));
1655 FAIL_IF(!DNP3CheckCRC(request +
sizeof(DNP3LinkHeader),
1658 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1661 FAIL_IF(DNP3CheckCRC(request,
sizeof(DNP3LinkHeader)));
1665 request[
sizeof(DNP3LinkHeader) + 3]++;
1666 FAIL_IF(DNP3CheckCRC(request +
sizeof(DNP3LinkHeader),
1676 static int DNP3CheckUserDataCRCsTest(
void)
1679 uint8_t data_valid[] = {
1680 0xff, 0xc9, 0x05, 0x0c,
1681 0x01, 0x28, 0x01, 0x00,
1682 0x00, 0x00, 0x01, 0x01,
1683 0x01, 0x00, 0x00, 0x00,
1686 0xff, 0xc9, 0x05, 0x0c,
1687 0x01, 0x28, 0x01, 0x00,
1688 0x00, 0x00, 0x01, 0x01,
1689 0x01, 0x00, 0x00, 0x00,
1692 0xff, 0xc9, 0x05, 0x0c,
1693 0x01, 0x28, 0x01, 0x00,
1694 0x00, 0x00, 0x01, 0x01,
1695 0x01, 0x00, 0x00, 0x00,
1698 0x00, 0x00, 0x00, 0x00,
1702 FAIL_IF(!DNP3CheckUserDataCRCs(data_valid,
sizeof(data_valid)));
1704 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1706 uint8_t data_invalid[] = {
1707 0xff, 0xc9, 0x05, 0x0c,
1708 0x01, 0x28, 0x01, 0x00,
1709 0x00, 0x00, 0x01, 0x01,
1710 0x01, 0x00, 0x00, 0x00,
1713 0xff, 0xc9, 0x05, 0x0c,
1714 0x01, 0x28, 0x01, 0x00,
1715 0x00, 0x00, 0x01, 0x01,
1716 0x01, 0x00, 0x00, 0x00,
1719 0xff, 0xc9, 0x05, 0x0c,
1720 0x01, 0x28, 0x01, 0x00,
1721 0x00, 0x00, 0x01, 0x01,
1722 0x01, 0x00, 0x00, 0x00,
1725 0x00, 0x00, 0x00, 0x00,
1729 FAIL_IF(DNP3CheckUserDataCRCs(data_invalid,
sizeof(data_invalid)));
1732 uint8_t one_byte_nocrc[] = { 0x01 };
1733 FAIL_IF(DNP3CheckUserDataCRCs(one_byte_nocrc,
sizeof(one_byte_nocrc)));
1736 uint8_t two_byte_nocrc[] = { 0x01, 0x02 };
1737 FAIL_IF(DNP3CheckUserDataCRCs(two_byte_nocrc,
sizeof(two_byte_nocrc)));
1741 uint8_t three_bytes_good_crc[] = { 0x00, 0x00, 0x00 };
1742 *(uint16_t *)(three_bytes_good_crc + 1) = DNP3ComputeCRC(
1743 three_bytes_good_crc, 1);
1744 FAIL_IF(!DNP3CheckUserDataCRCs(three_bytes_good_crc,
1745 sizeof(three_bytes_good_crc)));
1757 static int DNP3CalculateLinkLengthTest(
void)
1760 FAIL_IF(DNP3CalculateLinkLength(0) != 0);
1761 FAIL_IF(DNP3CalculateLinkLength(1) != 0);
1762 FAIL_IF(DNP3CalculateLinkLength(2) != 0);
1763 FAIL_IF(DNP3CalculateLinkLength(3) != 0);
1764 FAIL_IF(DNP3CalculateLinkLength(4) != 0);
1767 FAIL_IF(DNP3CalculateLinkLength(5) != 10);
1770 FAIL_IF(DNP3CalculateLinkLength(21) != 28);
1773 FAIL_IF(DNP3CalculateLinkLength(37) != 46);
1777 FAIL_IF(DNP3CalculateLinkLength(38) != 49);
1780 FAIL_IF(DNP3CalculateLinkLength(255) != 292);
1789 static int DNP3CalculateTransportLengthWithoutCRCsTest(
void)
1791 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(0) != -1);
1792 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(1) != -1);
1793 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(2) != 0);
1794 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(3) != 1);
1795 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(16) != 14);
1796 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(17) != 15);
1797 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(18) != 16);
1800 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(19) != -1);
1804 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(20) != 16);
1806 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(21) != 17);
1814 static int DNP3ParserCheckLinkHeaderCRC(
void)
1817 uint8_t request[] = {
1819 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1826 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1827 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1828 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1831 DNP3LinkHeader *header = (DNP3LinkHeader *)request;
1832 FAIL_IF(!DNP3CheckLinkHeaderCRC(header));
1834 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1837 FAIL_IF(DNP3CheckLinkHeaderCRC(header));
1846 static int DNP3ReassembleApplicationLayerTest01(
void)
1848 uint32_t reassembled_len = 0;
1849 uint8_t *output = NULL;
1851 uint8_t payload[] = {
1853 0xff, 0xc9, 0x05, 0x0c,
1854 0x01, 0x28, 0x01, 0x00,
1855 0x00, 0x00, 0x01, 0x01,
1856 0x01, 0x00, 0x00, 0x00,
1859 0xff, 0xc9, 0x05, 0x0c,
1860 0x01, 0x28, 0x01, 0x00,
1861 0x00, 0x00, 0x01, 0x01,
1862 0x01, 0x00, 0x00, 0x00,
1865 0xff, 0xc9, 0x05, 0x0c,
1866 0x01, 0x28, 0x01, 0x00,
1867 0x00, 0x00, 0x01, 0x01,
1868 0x01, 0x00, 0x00, 0x00,
1871 0x00, 0x00, 0x00, 0x00,
1876 uint8_t expected[] = {
1878 0x01, 0x28, 0x01, 0x00,
1879 0x00, 0x00, 0x01, 0x01,
1880 0x01, 0x00, 0x00, 0x00,
1882 0xff, 0xc9, 0x05, 0x0c,
1883 0x01, 0x28, 0x01, 0x00,
1884 0x00, 0x00, 0x01, 0x01,
1885 0x01, 0x00, 0x00, 0x00,
1887 0xff, 0xc9, 0x05, 0x0c,
1888 0x01, 0x28, 0x01, 0x00,
1889 0x00, 0x00, 0x01, 0x01,
1890 0x01, 0x00, 0x00, 0x00,
1892 0x00, 0x00, 0x00, 0x00,
1898 FAIL_IF(!DNP3ReassembleApplicationLayer(payload,
1899 sizeof(payload), &output, &reassembled_len));
1901 FAIL_IF(reassembled_len !=
sizeof(expected));
1902 FAIL_IF(memcmp(expected, output, reassembled_len));
1906 reassembled_len = 0;
1908 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 1, &output,
1911 FAIL_IF(reassembled_len != 0);
1914 reassembled_len = 0;
1916 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 2, &output,
1919 FAIL_IF(reassembled_len != 0);
1923 reassembled_len = 0;
1925 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 3, &output,
1928 FAIL_IF(reassembled_len != 0);
1931 reassembled_len = 0;
1933 FAIL_IF(!DNP3ReassembleApplicationLayer(payload, 4, &output,
1936 FAIL_IF(reassembled_len != 1);
1939 uint8_t short_payload1[] = {
1941 0xff, 0xc9, 0x05, 0x0c,
1942 0x01, 0x28, 0x01, 0x00,
1943 0x00, 0x00, 0x01, 0x01,
1944 0x01, 0x00, 0x00, 0x00,
1947 0xff, 0xc9, 0x05, 0x0c,
1948 0x01, 0x28, 0x01, 0x00,
1949 0x00, 0x00, 0x01, 0x01,
1950 0x01, 0x00, 0x00, 0x00,
1953 0xff, 0xc9, 0x05, 0x0c,
1954 0x01, 0x28, 0x01, 0x00,
1955 0x00, 0x00, 0x01, 0x01,
1956 0x01, 0x00, 0x00, 0x00,
1961 reassembled_len = 0;
1962 FAIL_IF(DNP3ReassembleApplicationLayer(short_payload1,
1963 sizeof(short_payload1), &output, &reassembled_len));
1966 uint8_t short_payload2[] = {
1968 0xff, 0xc9, 0x05, 0x0c,
1969 0x01, 0x28, 0x01, 0x00,
1970 0x00, 0x00, 0x01, 0x01,
1971 0x01, 0x00, 0x00, 0x00,
1974 0xff, 0xc9, 0x05, 0x0c,
1975 0x01, 0x28, 0x01, 0x00,
1976 0x00, 0x00, 0x01, 0x01,
1977 0x01, 0x00, 0x00, 0x00,
1980 0xff, 0xc9, 0x05, 0x0c,
1981 0x01, 0x28, 0x01, 0x00,
1982 0x00, 0x00, 0x01, 0x01,
1983 0x01, 0x00, 0x00, 0x00,
1988 reassembled_len = 0;
1989 FAIL_IF(DNP3ReassembleApplicationLayer(short_payload2,
1990 sizeof(short_payload2), &output, &reassembled_len));
1998 static int DNP3ProbingParserTest(
void)
2001 0x05, 0x64, 0x05, 0xc9, 0x03, 0x00, 0x04, 0x00,
2007 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt,
sizeof(pkt), &rdir) !=
ALPROTO_DNP3);
2010 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt,
sizeof(DNP3LinkHeader) - 1, &rdir) !=
ALPROTO_UNKNOWN);
2024 char mybanner[] =
"Welcome to DNP3 SCADA.";
2025 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, (uint8_t *)mybanner,
sizeof(mybanner) - 1,
2027 FAIL_IF(rdir != STREAM_TOCLIENT);
2035 static int DNP3ParserTestRequestResponse(
void)
2039 uint8_t request[] = {
2041 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2048 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2049 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2050 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2053 uint8_t response[] = {
2055 0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2062 0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2063 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2064 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2072 memset(&flow, 0,
sizeof(flow));
2073 memset(&ssn, 0,
sizeof(ssn));
2076 flow.
proto = IPPROTO_TCP;
2083 STREAM_TOSERVER, request,
sizeof(request)));
2099 STREAM_TOCLIENT, response,
sizeof(response)));
2118 static int DNP3ParserTestUnsolicitedResponseConfirm(
void)
2123 uint8_t response[] = {
2124 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2125 0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2126 0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2127 0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9
2131 uint8_t confirm[] = {
2132 0x05, 0x64, 0x08, 0xc4, 0x02, 0x00,
2133 0x01, 0x00, 0xd3, 0xb7, 0xc0, 0xda, 0x00, 0x6a,
2141 memset(&flow, 0,
sizeof(flow));
2142 memset(&ssn, 0,
sizeof(ssn));
2145 flow.
proto = IPPROTO_TCP;
2152 STREAM_TOCLIENT, response,
sizeof(response)));
2167 STREAM_TOSERVER, confirm,
sizeof(confirm)));
2188 static int DNP3ParserTestFlooded(
void)
2192 uint8_t request[] = {
2194 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2201 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2202 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2203 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2210 memset(&flow, 0,
sizeof(flow));
2211 memset(&ssn, 0,
sizeof(ssn));
2214 flow.
proto = IPPROTO_TCP;
2221 STREAM_TOSERVER, request,
sizeof(request)));
2235 FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2240 STREAM_TOSERVER, request,
sizeof(request)));
2244 FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2249 STREAM_TOSERVER, request,
sizeof(request)));
2254 FAIL_IF(!DNP3GetAlstateProgress(tx, 0));
2269 static int DNP3ParserTestPartialFrame(
void)
2275 uint8_t request_partial1[] = {
2277 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2284 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2287 uint8_t request_partial2[] = {
2289 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2290 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2293 uint8_t response_partial1[] = {
2295 0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2302 0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2305 uint8_t response_partial2[] = {
2306 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2307 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2315 memset(&flow, 0,
sizeof(flow));
2316 memset(&ssn, 0,
sizeof(ssn));
2318 flow.
proto = IPPROTO_TCP;
2326 STREAM_TOSERVER, request_partial1,
sizeof(request_partial1));
2336 sizeof(request_partial1)));
2340 FAIL_IF(DNP3GetTx(state, 0) != NULL);
2345 STREAM_TOSERVER, request_partial2,
sizeof(request_partial2));
2355 tx = DNP3GetTx(state, 0);
2366 STREAM_TOCLIENT, response_partial1,
sizeof(response_partial1));
2371 tx = DNP3GetTx(state, 1);
2377 STREAM_TOCLIENT, response_partial2,
sizeof(response_partial2));
2386 tx = DNP3GetTx(state, 1);
2400 static int DNP3ParserTestMultiFrame(
void)
2405 uint8_t unsol_response1[] = {
2406 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2407 0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2408 0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2409 0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9,
2413 uint8_t unsol_response2[] = {
2414 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2415 0x89, 0xe5, 0xc5, 0xfb, 0x82, 0x00, 0x00, 0x02,
2416 0x02, 0x17, 0x01, 0x0c, 0x01, 0xd8, 0x75, 0xd8,
2417 0x32, 0x4c, 0xc9, 0x3c, 0x01, 0xa1, 0xc9,
2420 uint8_t combined[
sizeof(unsol_response1) +
sizeof(unsol_response2)];
2421 memcpy(combined, unsol_response1,
sizeof(unsol_response1));
2422 memcpy(combined +
sizeof(unsol_response1), unsol_response2,
2423 sizeof(unsol_response2));
2430 memset(&flow, 0,
sizeof(flow));
2431 memset(&ssn, 0,
sizeof(ssn));
2433 flow.
proto = IPPROTO_TCP;
2439 STREAM_TOCLIENT, combined,
sizeof(combined));
2461 static int DNP3ParserTestParsePDU01(
void)
2465 const uint8_t pkt[] = {
2467 0x0b, 0xc4, 0x17, 0x00, 0xef, 0xff, 0xc4, 0x8f,
2468 0xe1, 0xc8, 0x01, 0x01, 0x00, 0x06, 0x77, 0x6e
2472 int pdus = DNP3HandleRequestLinkLayer(dnp3state, pkt,
sizeof(pkt));
2482 DNP3StateFree(dnp3state);
2489 static int DNP3ParserDecodeG70V3Test(
void)
2491 const uint8_t pkt[] = {
2493 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00, 0xc7, 0xee,
2494 0xc7, 0xc9, 0x1b, 0x46, 0x03, 0x5b, 0x01, 0x55,
2495 0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2496 0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2497 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2498 0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2499 0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2500 0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2501 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2502 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2503 0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2504 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2505 0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2506 0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2512 int bytes = DNP3HandleRequestLinkLayer(dnp3state, pkt,
sizeof(pkt));
2513 FAIL_IF(bytes !=
sizeof(pkt));
2532 "C:/temp/DNPDeviceConfiguration written to Remote Device.xml") == 0);
2533 DNP3StateFree(dnp3state);
2540 static int DNP3ParserUnknownEventAlertTest(
void)
2544 0x05, 0x64, 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00,
2554 0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2555 0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2557 0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2558 0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2559 0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2560 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2561 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2562 0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2563 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2564 0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2565 0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2569 DNP3FixCrc(pkt + 10,
sizeof(pkt) - 10);
2573 int bytes = DNP3HandleRequestLinkLayer(dnp3state, pkt,
sizeof(pkt));
2574 FAIL_IF(bytes !=
sizeof(pkt));
2576 DNP3StateFree(dnp3state);
2583 static int DNP3ParserIncorrectUserData(
void)
2585 uint8_t packet_bytes[] = {
2586 0x05, 0x64, 0x08, 0xc4, 0x03, 0x00, 0x04, 0x00,
2587 0xbf, 0xe9, 0xc1, 0xc1, 0x82, 0xc5, 0xee
2593 memset(&flow, 0,
sizeof(flow));
2594 memset(&ssn, 0,
sizeof(ssn));
2596 flow.
proto = IPPROTO_TCP;
2601 STREAM_TOCLIENT, packet_bytes,
sizeof(packet_bytes));
2616 UtRegisterTest(
"DNP3ParserTestCheckCRC", DNP3ParserTestCheckCRC);
2618 DNP3ParserCheckLinkHeaderCRC);
2619 UtRegisterTest(
"DNP3CheckUserDataCRCsTest", DNP3CheckUserDataCRCsTest);
2620 UtRegisterTest(
"DNP3CalculateLinkLengthTest", DNP3CalculateLinkLengthTest);
2622 DNP3CalculateTransportLengthWithoutCRCsTest);
2624 DNP3ReassembleApplicationLayerTest01);
2627 DNP3ParserTestRequestResponse);
2629 DNP3ParserTestUnsolicitedResponseConfirm);
2630 UtRegisterTest(
"DNP3ParserTestPartialFrame", DNP3ParserTestPartialFrame);
2631 UtRegisterTest(
"DNP3ParserTestMultiFrame", DNP3ParserTestMultiFrame);
2633 UtRegisterTest(
"DNP3ParserTestParsePDU01", DNP3ParserTestParsePDU01);
2634 UtRegisterTest(
"DNP3ParserDecodeG70V3Test", DNP3ParserDecodeG70V3Test);
2636 DNP3ParserUnknownEventAlertTest);
2637 UtRegisterTest(
"DNP3ParserIncorrectUserData", DNP3ParserIncorrectUserData);