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)
93 static uint64_t dnp3_max_tx = 32;
96 static uint64_t max_points = 16384;
99 static uint64_t dnp3_max_objects = 2048;
116 #define NEXT_TH_SEQNO(current) ((current + 1) % DNP3_MAX_TRAN_SEQNO)
120 static const uint16_t crc_table[256] = {
121 0x0000, 0x365e, 0x6cbc, 0x5ae2, 0xd978, 0xef26, 0xb5c4, 0x839a,
122 0xff89, 0xc9d7, 0x9335, 0xa56b, 0x26f1, 0x10af, 0x4a4d, 0x7c13,
123 0xb26b, 0x8435, 0xded7, 0xe889, 0x6b13, 0x5d4d, 0x07af, 0x31f1,
124 0x4de2, 0x7bbc, 0x215e, 0x1700, 0x949a, 0xa2c4, 0xf826, 0xce78,
125 0x29af, 0x1ff1, 0x4513, 0x734d, 0xf0d7, 0xc689, 0x9c6b, 0xaa35,
126 0xd626, 0xe078, 0xba9a, 0x8cc4, 0x0f5e, 0x3900, 0x63e2, 0x55bc,
127 0x9bc4, 0xad9a, 0xf778, 0xc126, 0x42bc, 0x74e2, 0x2e00, 0x185e,
128 0x644d, 0x5213, 0x08f1, 0x3eaf, 0xbd35, 0x8b6b, 0xd189, 0xe7d7,
129 0x535e, 0x6500, 0x3fe2, 0x09bc, 0x8a26, 0xbc78, 0xe69a, 0xd0c4,
130 0xacd7, 0x9a89, 0xc06b, 0xf635, 0x75af, 0x43f1, 0x1913, 0x2f4d,
131 0xe135, 0xd76b, 0x8d89, 0xbbd7, 0x384d, 0x0e13, 0x54f1, 0x62af,
132 0x1ebc, 0x28e2, 0x7200, 0x445e, 0xc7c4, 0xf19a, 0xab78, 0x9d26,
133 0x7af1, 0x4caf, 0x164d, 0x2013, 0xa389, 0x95d7, 0xcf35, 0xf96b,
134 0x8578, 0xb326, 0xe9c4, 0xdf9a, 0x5c00, 0x6a5e, 0x30bc, 0x06e2,
135 0xc89a, 0xfec4, 0xa426, 0x9278, 0x11e2, 0x27bc, 0x7d5e, 0x4b00,
136 0x3713, 0x014d, 0x5baf, 0x6df1, 0xee6b, 0xd835, 0x82d7, 0xb489,
137 0xa6bc, 0x90e2, 0xca00, 0xfc5e, 0x7fc4, 0x499a, 0x1378, 0x2526,
138 0x5935, 0x6f6b, 0x3589, 0x03d7, 0x804d, 0xb613, 0xecf1, 0xdaaf,
139 0x14d7, 0x2289, 0x786b, 0x4e35, 0xcdaf, 0xfbf1, 0xa113, 0x974d,
140 0xeb5e, 0xdd00, 0x87e2, 0xb1bc, 0x3226, 0x0478, 0x5e9a, 0x68c4,
141 0x8f13, 0xb94d, 0xe3af, 0xd5f1, 0x566b, 0x6035, 0x3ad7, 0x0c89,
142 0x709a, 0x46c4, 0x1c26, 0x2a78, 0xa9e2, 0x9fbc, 0xc55e, 0xf300,
143 0x3d78, 0x0b26, 0x51c4, 0x679a, 0xe400, 0xd25e, 0x88bc, 0xbee2,
144 0xc2f1, 0xf4af, 0xae4d, 0x9813, 0x1b89, 0x2dd7, 0x7735, 0x416b,
145 0xf5e2, 0xc3bc, 0x995e, 0xaf00, 0x2c9a, 0x1ac4, 0x4026, 0x7678,
146 0x0a6b, 0x3c35, 0x66d7, 0x5089, 0xd313, 0xe54d, 0xbfaf, 0x89f1,
147 0x4789, 0x71d7, 0x2b35, 0x1d6b, 0x9ef1, 0xa8af, 0xf24d, 0xc413,
148 0xb800, 0x8e5e, 0xd4bc, 0xe2e2, 0x6178, 0x5726, 0x0dc4, 0x3b9a,
149 0xdc4d, 0xea13, 0xb0f1, 0x86af, 0x0535, 0x336b, 0x6989, 0x5fd7,
150 0x23c4, 0x159a, 0x4f78, 0x7926, 0xfabc, 0xcce2, 0x9600, 0xa05e,
151 0x6e26, 0x5878, 0x029a, 0x34c4, 0xb75e, 0x8100, 0xdbe2, 0xedbc,
152 0x91af, 0xa7f1, 0xfd13, 0xcb4d, 0x48d7, 0x7e89, 0x246b, 0x1235
163 static uint16_t DNP3ComputeCRC(
const uint8_t *buf, uint32_t
len)
165 const uint8_t *
byte = buf;
170 idx = (
crc ^ *byte) & 0xff;
171 crc = (crc_table[idx] ^ (
crc >> 8)) & 0xffff;
175 return ~
crc & 0xffff;
186 static int DNP3CheckCRC(
const uint8_t *block, uint16_t
len)
188 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
201 if (((
crc & 0xff) == block[crc_offset]) &&
202 ((
crc >> 8) == block[crc_offset + 1])) {
216 static int DNP3CheckLinkHeaderCRC(
const DNP3LinkHeader *header)
218 return DNP3CheckCRC((uint8_t *)header,
sizeof(DNP3LinkHeader));
229 static int DNP3CheckUserDataCRCs(
const uint8_t *data, uint16_t
len)
242 if (!DNP3CheckCRC(data +
offset, block_size)) {
258 static int DNP3CheckStartBytes(
const DNP3LinkHeader *header)
265 #define DNP3_BANNER "DNP3"
275 static int DNP3ContainsBanner(
const uint8_t *input, uint32_t
len)
283 static uint16_t DNP3ProbingParser(
284 const Flow *
f, uint8_t direction,
const uint8_t *input, uint32_t
len, uint8_t *rdir)
286 const DNP3LinkHeader *
const hdr = (
const DNP3LinkHeader *)input;
287 const bool toserver = (direction & STREAM_TOSERVER) != 0;
290 if (DNP3ContainsBanner(input,
len)) {
292 bool is_banner =
true;
294 for (uint32_t i = 0; i <
len && i < 0x100; i++) {
295 if (!isprint(input[i])) {
302 *rdir = STREAM_TOCLIENT;
309 if (
len <
sizeof(DNP3LinkHeader)) {
310 SCLogDebug(
"Length too small to be a DNP3 header.");
315 if (!DNP3CheckStartBytes(hdr)) {
322 SCLogDebug(
"Packet too small to be a valid DNP3 fragment.");
328 *rdir = toserver ? STREAM_TOCLIENT : STREAM_TOSERVER;
341 static int DNP3CalculateTransportLengthWithoutCRCs(uint16_t input_len)
384 static int DNP3ReassembleApplicationLayer(
385 const uint8_t *input, uint16_t input_len, uint8_t **output, uint16_t *output_len)
387 int len = DNP3CalculateTransportLengthWithoutCRCs(input_len);
399 if (*output == NULL) {
406 uint8_t *ptr =
SCRealloc(*output, (
size_t)(*output_len +
len));
413 uint16_t
offset = 0, block_size;
414 while (
offset < input_len) {
419 block_size = input_len -
offset;
444 memcpy(*output + *output_len, input +
offset,
459 static void *DNP3StateAlloc(
void *orig_state,
AppProto proto_orig)
488 static void DNP3SetEvent(
DNP3State *dnp3,
bool request, uint8_t event)
490 if (dnp3 != NULL && dnp3->
curr == NULL) {
496 if (dnp3 && dnp3->
curr) {
497 DNP3SetEventTx(dnp3->
curr, event);
500 SCLogWarning(
"Failed to set event, state or tx pointer was NULL.");
547 static uint16_t DNP3CalculateLinkLength(uint8_t
length)
549 uint16_t frame_len = 0;
567 return frame_len +
sizeof(DNP3LinkHeader);
577 static int DNP3IsUserData(
const DNP3LinkHeader *header)
596 static int DNP3HasUserData(
const DNP3LinkHeader *header, uint8_t direction)
598 if (direction == STREAM_TOSERVER) {
600 sizeof(DNP3ApplicationHeader);
604 sizeof(DNP3ApplicationHeader) +
sizeof(DNP3InternalInd);
611 static void DNP3Resync(
const uint8_t **input, uint32_t *input_len, uint32_t *processed)
615 while (skip + 1 < *input_len) {
635 static void DNP3BufferReset(
DNP3Buffer *buffer)
650 static int DNP3BufferAdd(
DNP3Buffer *buffer,
const uint8_t *data, uint32_t
len)
652 if (buffer->
size == 0) {
681 static void DNP3BufferTrim(
DNP3Buffer *buffer)
684 DNP3BufferReset(buffer);
686 else if (buffer->
offset > 0) {
697 static void DNP3ObjectFree(
DNP3Object *
object)
699 if (object->
points != NULL) {
716 if (object->
points == NULL) {
717 DNP3ObjectFree(
object);
738 static int DNP3DecodeApplicationObjects(
742 uint64_t point_count = 0;
743 uint64_t object_count = 0;
745 if (buf == NULL ||
len == 0) {
752 if (
len <
sizeof(DNP3ObjHeader)) {
755 DNP3ObjHeader *header = (DNP3ObjHeader *)buf;
756 offset +=
sizeof(DNP3ObjHeader);
759 if (++object_count > dnp3_max_objects) {
770 object->group = header->group;
771 object->variation = header->variation;
772 object->qualifier = header->qualifier;
782 if (
offset + (
sizeof(uint8_t) * 2) >
len) {
785 goto not_enough_data;
787 object->start = buf[
offset++];
788 object->stop = buf[
offset++];
789 object->count =
object->stop -
object->start + 1;
796 if (
offset + (
sizeof(uint16_t) * 2) >
len) {
799 goto not_enough_data;
802 offset +=
sizeof(uint16_t);
804 offset +=
sizeof(uint16_t);
805 object->count =
object->stop -
object->start + 1;
812 if (
offset + (
sizeof(uint32_t) * 2) >
len) {
815 goto not_enough_data;
818 offset +=
sizeof(uint32_t);
820 offset +=
sizeof(uint32_t);
821 object->count =
object->stop -
object->start + 1;
832 goto not_enough_data;
834 object->count = buf[
offset];
835 offset +=
sizeof(uint8_t);
841 goto not_enough_data;
844 offset +=
sizeof(uint16_t);
851 goto not_enough_data;
854 offset +=
sizeof(uint32_t);
861 goto not_enough_data;
863 object->count = *(uint8_t *)(buf +
offset);
864 offset +=
sizeof(uint8_t);
881 point_count +=
object->count;
882 if (point_count > max_points) {
914 static void DNP3HandleUserDataRequest(
915 Flow *
f,
DNP3State *dnp3,
const uint8_t *input, uint16_t input_len)
919 DNP3ApplicationHeader *ah;
922 lh = (DNP3LinkHeader *)input;
924 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
925 input_len -
sizeof(DNP3LinkHeader))) {
929 th = input[
sizeof(DNP3LinkHeader)];
933 if (ttx->lh.src == lh->src && ttx->lh.dst == lh->dst && ttx->is_request && !ttx->done &&
950 ah = (DNP3ApplicationHeader *)(input +
sizeof(DNP3LinkHeader) +
959 tx = DNP3TxAlloc(dnp3,
true);
969 if (!DNP3ReassembleApplicationLayer(input +
sizeof(DNP3LinkHeader),
992 if (DNP3DecodeApplicationObjects(tx, tx->
buffer +
sizeof(DNP3ApplicationHeader),
1001 static void DNP3HandleUserDataResponse(
1002 Flow *
f,
DNP3State *dnp3,
const uint8_t *input, uint16_t input_len)
1006 DNP3ApplicationHeader *ah;
1007 DNP3InternalInd *iin;
1011 lh = (DNP3LinkHeader *)input;
1012 offset +=
sizeof(DNP3LinkHeader);
1014 if (!DNP3CheckUserDataCRCs(input +
offset, input_len -
offset)) {
1022 if (ttx->lh.src == lh->src && ttx->lh.dst == lh->dst && !ttx->is_request &&
1039 ah = (DNP3ApplicationHeader *)(input +
offset);
1040 offset +=
sizeof(DNP3ApplicationHeader);
1041 iin = (DNP3InternalInd *)(input +
offset);
1043 tx = DNP3TxAlloc(dnp3,
false);
1056 if (!DNP3ReassembleApplicationLayer(input +
sizeof(DNP3LinkHeader),
1075 offset =
sizeof(DNP3ApplicationHeader) +
sizeof(DNP3InternalInd);
1076 if (DNP3DecodeApplicationObjects(
1091 static int DNP3HandleRequestLinkLayer(
1092 Flow *
f,
DNP3State *dnp3,
const uint8_t *input, uint32_t input_len)
1095 uint32_t processed = 0;
1100 if (input_len <
sizeof(DNP3LinkHeader)) {
1104 DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1106 if (!DNP3CheckStartBytes(header)) {
1111 if (!DNP3CheckLinkHeaderCRC(header)) {
1113 DNP3Resync(&input, &input_len, &processed);
1117 uint16_t frame_len = DNP3CalculateLinkLength(header->len);
1118 if (frame_len == 0) {
1120 DNP3Resync(&input, &input_len, &processed);
1123 if (input_len < frame_len) {
1129 if (!DNP3IsUserData(header)) {
1135 if (!DNP3HasUserData(header, STREAM_TOSERVER)) {
1140 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
1141 frame_len -
sizeof(DNP3LinkHeader))) {
1146 DNP3HandleUserDataRequest(
f, dnp3, input, frame_len);
1151 input_len -= frame_len;
1152 processed += frame_len;
1174 const uint8_t *input = StreamSliceGetData(&stream_slice);
1175 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1177 if (input_len == 0) {
1182 if (!DNP3BufferAdd(buffer, input, input_len)) {
1185 processed = DNP3HandleRequestLinkLayer(
1187 if (processed < 0) {
1190 buffer->
offset += processed;
1191 DNP3BufferTrim(buffer);
1194 processed = DNP3HandleRequestLinkLayer(
f, dnp3, input, input_len);
1195 if (processed < 0) {
1196 SCLogDebug(
"Failed to process request link layer.");
1201 input_len -= processed;
1205 if (!DNP3BufferAdd(buffer, input, input_len)) {
1215 DNP3BufferReset(buffer);
1225 static int DNP3HandleResponseLinkLayer(
1226 Flow *
f,
DNP3State *dnp3,
const uint8_t *input, uint32_t input_len)
1229 uint32_t processed = 0;
1234 if (input_len <
sizeof(DNP3LinkHeader)) {
1238 DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1240 if (!DNP3CheckStartBytes(header)) {
1245 if (!DNP3CheckLinkHeaderCRC(header)) {
1247 DNP3Resync(&input, &input_len, &processed);
1252 uint16_t frame_len = DNP3CalculateLinkLength(header->len);
1253 if (frame_len == 0) {
1255 DNP3Resync(&input, &input_len, &processed);
1258 if (input_len < frame_len) {
1264 if (!DNP3IsUserData(header)) {
1270 if (!DNP3HasUserData(header, STREAM_TOCLIENT)) {
1275 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
1276 frame_len -
sizeof(DNP3LinkHeader))) {
1281 DNP3HandleUserDataResponse(
f, dnp3, input, frame_len);
1286 input_len -= frame_len;
1287 processed += frame_len;
1311 const uint8_t *input = StreamSliceGetData(&stream_slice);
1312 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1315 if (!DNP3BufferAdd(buffer, input, input_len)) {
1318 processed = DNP3HandleResponseLinkLayer(
1320 if (processed < 0) {
1323 buffer->
offset += processed;
1324 DNP3BufferTrim(buffer);
1329 if (DNP3ContainsBanner(input, input_len)) {
1333 processed = DNP3HandleResponseLinkLayer(
f, dnp3, input, input_len);
1334 if (processed < 0) {
1338 input_len -= processed;
1342 if (!DNP3BufferAdd(buffer, input, input_len)) {
1354 DNP3BufferReset(buffer);
1358 static void *DNP3GetTx(
void *alstate, uint64_t tx_id)
1363 uint64_t tx_num = tx_id + 1;
1370 if (tx_num != tx->
tx_num) {
1379 static uint64_t DNP3GetTxCnt(
void *state)
1382 uint64_t count = ((uint64_t)((
DNP3State *)state)->transaction_max);
1389 static void DNP3TxFreeObjectList(DNP3ObjectList *objects)
1395 DNP3ObjectFree(
object);
1406 if (tx->
buffer != NULL) {
1412 DNP3TxFreeObjectList(&tx->
objects);
1424 static void DNP3StateTxFree(
void *state, uint64_t tx_id)
1429 uint64_t tx_num = tx_id + 1;
1433 if (tx->
tx_num != tx_num) {
1437 if (tx == dnp3->
curr) {
1466 static void DNP3StateFree(
void *state)
1471 if (state != NULL) {
1472 while ((tx =
TAILQ_FIRST(&dnp3->tx_list)) != NULL) {
1490 static int DNP3GetAlstateProgress(
void *tx, uint8_t direction)
1498 SCLogDebug(
"flooded: returning tx as done.");
1511 static int DNP3StateGetEventInfo(
1524 static int DNP3StateGetEventInfoById(
1528 if (*event_name == NULL) {
1530 "the DNP3 enum event map table.",
1559 switch (prefix_code) {
1577 if (state->
un.
ptr == NULL) {
1583 while (tx_ptr->
tx_num < min_tx_id + 1) {
1589 if (tx_ptr->
tx_num >= max_tx_id + 1) {
1595 .tx_id = tx_ptr->
tx_num - 1,
1596 .has_next = (state->
un.
ptr != NULL),
1611 const char *proto_name =
"dnp3";
1618 sizeof(DNP3LinkHeader), STREAM_TOSERVER, DNP3ProbingParser, DNP3ProbingParser);
1622 0,
sizeof(DNP3LinkHeader), DNP3ProbingParser, DNP3ProbingParser)) {
1628 SCLogConfig(
"Protocol detection and parser disabled for DNP3.");
1641 DNP3StateAlloc, DNP3StateFree);
1650 DNP3GetAlstateProgress);
1654 DNP3StateGetEventInfo);
1656 DNP3StateGetEventInfoById);
1664 if (
SCConfGetInt(
"app-layer.protocols.dnp3.max-tx", &value)) {
1665 dnp3_max_tx = (uint64_t)value;
1669 if (
SCConfGetInt(
"app-layer.protocols.dnp3.max-points", &value)) {
1671 max_points = (uint64_t)value;
1676 if (
SCConfGetInt(
"app-layer.protocols.dnp3.max-objects", &value)) {
1678 dnp3_max_objects = (uint64_t)value;
1683 "Protocol detection still on.", proto_name);
1703 static void DNP3FixCrc(uint8_t *data, uint32_t
len)
1705 uint32_t block_size;
1713 uint16_t
crc = DNP3ComputeCRC(data, block_size);
1714 data[block_size + 1] = (
crc >> 8) & 0xff;
1715 data[block_size] =
crc & 0xff;
1724 static int DNP3ParserTestCheckCRC(
void)
1726 uint8_t request[] = {
1728 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1735 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1736 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1740 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1744 FAIL_IF(!DNP3CheckCRC(request,
sizeof(DNP3LinkHeader)));
1747 FAIL_IF(!DNP3CheckCRC(request +
sizeof(DNP3LinkHeader),
1750 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1753 FAIL_IF(DNP3CheckCRC(request,
sizeof(DNP3LinkHeader)));
1757 request[
sizeof(DNP3LinkHeader) + 3]++;
1758 FAIL_IF(DNP3CheckCRC(request +
sizeof(DNP3LinkHeader),
1768 static int DNP3CheckUserDataCRCsTest(
void)
1771 uint8_t data_valid[] = {
1772 0xff, 0xc9, 0x05, 0x0c,
1773 0x01, 0x28, 0x01, 0x00,
1774 0x00, 0x00, 0x01, 0x01,
1775 0x01, 0x00, 0x00, 0x00,
1778 0xff, 0xc9, 0x05, 0x0c,
1779 0x01, 0x28, 0x01, 0x00,
1780 0x00, 0x00, 0x01, 0x01,
1781 0x01, 0x00, 0x00, 0x00,
1784 0xff, 0xc9, 0x05, 0x0c,
1785 0x01, 0x28, 0x01, 0x00,
1786 0x00, 0x00, 0x01, 0x01,
1787 0x01, 0x00, 0x00, 0x00,
1790 0x00, 0x00, 0x00, 0x00,
1794 FAIL_IF(!DNP3CheckUserDataCRCs(data_valid,
sizeof(data_valid)));
1796 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1798 uint8_t data_invalid[] = {
1799 0xff, 0xc9, 0x05, 0x0c,
1800 0x01, 0x28, 0x01, 0x00,
1801 0x00, 0x00, 0x01, 0x01,
1802 0x01, 0x00, 0x00, 0x00,
1805 0xff, 0xc9, 0x05, 0x0c,
1806 0x01, 0x28, 0x01, 0x00,
1807 0x00, 0x00, 0x01, 0x01,
1808 0x01, 0x00, 0x00, 0x00,
1811 0xff, 0xc9, 0x05, 0x0c,
1812 0x01, 0x28, 0x01, 0x00,
1813 0x00, 0x00, 0x01, 0x01,
1814 0x01, 0x00, 0x00, 0x00,
1817 0x00, 0x00, 0x00, 0x00,
1821 FAIL_IF(DNP3CheckUserDataCRCs(data_invalid,
sizeof(data_invalid)));
1824 uint8_t one_byte_nocrc[] = { 0x01 };
1825 FAIL_IF(DNP3CheckUserDataCRCs(one_byte_nocrc,
sizeof(one_byte_nocrc)));
1828 uint8_t two_byte_nocrc[] = { 0x01, 0x02 };
1829 FAIL_IF(DNP3CheckUserDataCRCs(two_byte_nocrc,
sizeof(two_byte_nocrc)));
1833 uint8_t three_bytes_good_crc[] = { 0x00, 0x00, 0x00 };
1834 *(uint16_t *)(three_bytes_good_crc + 1) = DNP3ComputeCRC(
1835 three_bytes_good_crc, 1);
1836 FAIL_IF(!DNP3CheckUserDataCRCs(three_bytes_good_crc,
1837 sizeof(three_bytes_good_crc)));
1849 static int DNP3CalculateLinkLengthTest(
void)
1852 FAIL_IF(DNP3CalculateLinkLength(0) != 0);
1853 FAIL_IF(DNP3CalculateLinkLength(1) != 0);
1854 FAIL_IF(DNP3CalculateLinkLength(2) != 0);
1855 FAIL_IF(DNP3CalculateLinkLength(3) != 0);
1856 FAIL_IF(DNP3CalculateLinkLength(4) != 0);
1859 FAIL_IF(DNP3CalculateLinkLength(5) != 10);
1862 FAIL_IF(DNP3CalculateLinkLength(21) != 28);
1865 FAIL_IF(DNP3CalculateLinkLength(37) != 46);
1869 FAIL_IF(DNP3CalculateLinkLength(38) != 49);
1872 FAIL_IF(DNP3CalculateLinkLength(255) != 292);
1881 static int DNP3CalculateTransportLengthWithoutCRCsTest(
void)
1883 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(0) != -1);
1884 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(1) != -1);
1885 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(2) != 0);
1886 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(3) != 1);
1887 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(16) != 14);
1888 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(17) != 15);
1889 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(18) != 16);
1892 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(19) != -1);
1896 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(20) != 16);
1898 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(21) != 17);
1906 static int DNP3ParserCheckLinkHeaderCRC(
void)
1909 uint8_t request[] = {
1911 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1918 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1919 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1920 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1923 DNP3LinkHeader *header = (DNP3LinkHeader *)request;
1924 FAIL_IF(!DNP3CheckLinkHeaderCRC(header));
1926 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1929 FAIL_IF(DNP3CheckLinkHeaderCRC(header));
1938 static int DNP3ReassembleApplicationLayerTest01(
void)
1940 uint16_t reassembled_len = 0;
1941 uint8_t *output = NULL;
1943 uint8_t payload[] = {
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,
1957 0xff, 0xc9, 0x05, 0x0c,
1958 0x01, 0x28, 0x01, 0x00,
1959 0x00, 0x00, 0x01, 0x01,
1960 0x01, 0x00, 0x00, 0x00,
1963 0x00, 0x00, 0x00, 0x00,
1968 uint8_t expected[] = {
1970 0x01, 0x28, 0x01, 0x00,
1971 0x00, 0x00, 0x01, 0x01,
1972 0x01, 0x00, 0x00, 0x00,
1974 0xff, 0xc9, 0x05, 0x0c,
1975 0x01, 0x28, 0x01, 0x00,
1976 0x00, 0x00, 0x01, 0x01,
1977 0x01, 0x00, 0x00, 0x00,
1979 0xff, 0xc9, 0x05, 0x0c,
1980 0x01, 0x28, 0x01, 0x00,
1981 0x00, 0x00, 0x01, 0x01,
1982 0x01, 0x00, 0x00, 0x00,
1984 0x00, 0x00, 0x00, 0x00,
1990 FAIL_IF(!DNP3ReassembleApplicationLayer(payload,
1991 sizeof(payload), &output, &reassembled_len));
1993 FAIL_IF(reassembled_len !=
sizeof(expected));
1994 FAIL_IF(memcmp(expected, output, reassembled_len));
1998 reassembled_len = 0;
2000 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 1, &output,
2003 FAIL_IF(reassembled_len != 0);
2006 reassembled_len = 0;
2008 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 2, &output,
2011 FAIL_IF(reassembled_len != 0);
2015 reassembled_len = 0;
2017 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 3, &output,
2020 FAIL_IF(reassembled_len != 0);
2023 reassembled_len = 0;
2025 FAIL_IF(!DNP3ReassembleApplicationLayer(payload, 4, &output,
2028 FAIL_IF(reassembled_len != 1);
2031 uint8_t short_payload1[] = {
2033 0xff, 0xc9, 0x05, 0x0c,
2034 0x01, 0x28, 0x01, 0x00,
2035 0x00, 0x00, 0x01, 0x01,
2036 0x01, 0x00, 0x00, 0x00,
2039 0xff, 0xc9, 0x05, 0x0c,
2040 0x01, 0x28, 0x01, 0x00,
2041 0x00, 0x00, 0x01, 0x01,
2042 0x01, 0x00, 0x00, 0x00,
2045 0xff, 0xc9, 0x05, 0x0c,
2046 0x01, 0x28, 0x01, 0x00,
2047 0x00, 0x00, 0x01, 0x01,
2048 0x01, 0x00, 0x00, 0x00,
2053 reassembled_len = 0;
2054 FAIL_IF(DNP3ReassembleApplicationLayer(short_payload1,
2055 sizeof(short_payload1), &output, &reassembled_len));
2058 uint8_t short_payload2[] = {
2060 0xff, 0xc9, 0x05, 0x0c,
2061 0x01, 0x28, 0x01, 0x00,
2062 0x00, 0x00, 0x01, 0x01,
2063 0x01, 0x00, 0x00, 0x00,
2066 0xff, 0xc9, 0x05, 0x0c,
2067 0x01, 0x28, 0x01, 0x00,
2068 0x00, 0x00, 0x01, 0x01,
2069 0x01, 0x00, 0x00, 0x00,
2072 0xff, 0xc9, 0x05, 0x0c,
2073 0x01, 0x28, 0x01, 0x00,
2074 0x00, 0x00, 0x01, 0x01,
2075 0x01, 0x00, 0x00, 0x00,
2080 reassembled_len = 0;
2081 FAIL_IF(DNP3ReassembleApplicationLayer(short_payload2,
2082 sizeof(short_payload2), &output, &reassembled_len));
2092 static int DNP3ProbingParserTest(
void)
2095 0x05, 0x64, 0x05, 0xc9, 0x03, 0x00, 0x04, 0x00,
2101 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt,
sizeof(pkt), &rdir) !=
ALPROTO_DNP3);
2104 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt,
sizeof(DNP3LinkHeader) - 1, &rdir) !=
ALPROTO_UNKNOWN);
2118 char mybanner[] =
"Welcome to DNP3 SCADA.";
2119 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, (uint8_t *)mybanner,
sizeof(mybanner) - 1,
2121 FAIL_IF(rdir != STREAM_TOCLIENT);
2129 static int DNP3ParserTestRequestResponse(
void)
2133 uint8_t request[] = {
2135 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2142 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2143 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2144 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2147 uint8_t response[] = {
2149 0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2156 0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2157 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2158 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2166 memset(&flow, 0,
sizeof(flow));
2167 memset(&
ssn, 0,
sizeof(
ssn));
2170 flow.
proto = IPPROTO_TCP;
2177 STREAM_TOSERVER, request,
sizeof(request)));
2193 STREAM_TOCLIENT, response,
sizeof(response)));
2212 static int DNP3ParserTestUnsolicitedResponseConfirm(
void)
2217 uint8_t response[] = {
2218 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2219 0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2220 0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2221 0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9
2225 uint8_t confirm[] = {
2226 0x05, 0x64, 0x08, 0xc4, 0x02, 0x00,
2227 0x01, 0x00, 0xd3, 0xb7, 0xc0, 0xda, 0x00, 0x6a,
2235 memset(&flow, 0,
sizeof(flow));
2236 memset(&
ssn, 0,
sizeof(
ssn));
2239 flow.
proto = IPPROTO_TCP;
2246 STREAM_TOCLIENT, response,
sizeof(response)));
2261 STREAM_TOSERVER, confirm,
sizeof(confirm)));
2282 static int DNP3ParserTestFlooded(
void)
2286 uint8_t request[] = {
2288 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2295 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2296 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2297 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2304 memset(&flow, 0,
sizeof(flow));
2305 memset(&
ssn, 0,
sizeof(
ssn));
2308 flow.
proto = IPPROTO_TCP;
2315 STREAM_TOSERVER, request,
sizeof(request)));
2329 FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2331 for (uint64_t i = 0; i < dnp3_max_tx - 1; i++) {
2334 STREAM_TOSERVER, request,
sizeof(request)));
2338 FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2343 STREAM_TOSERVER, request,
sizeof(request)));
2348 FAIL_IF(!DNP3GetAlstateProgress(tx, 0));
2363 static int DNP3ParserTestPartialFrame(
void)
2369 uint8_t request_partial1[] = {
2371 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2378 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2381 uint8_t request_partial2[] = {
2383 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2384 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2387 uint8_t response_partial1[] = {
2389 0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2396 0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2399 uint8_t response_partial2[] = {
2400 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2401 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2409 memset(&flow, 0,
sizeof(flow));
2410 memset(&
ssn, 0,
sizeof(
ssn));
2412 flow.
proto = IPPROTO_TCP;
2420 STREAM_TOSERVER, request_partial1,
sizeof(request_partial1));
2430 sizeof(request_partial1)));
2434 FAIL_IF(DNP3GetTx(state, 0) != NULL);
2439 STREAM_TOSERVER, request_partial2,
sizeof(request_partial2));
2449 tx = DNP3GetTx(state, 0);
2460 STREAM_TOCLIENT, response_partial1,
sizeof(response_partial1));
2465 tx = DNP3GetTx(state, 1);
2471 STREAM_TOCLIENT, response_partial2,
sizeof(response_partial2));
2480 tx = DNP3GetTx(state, 1);
2494 static int DNP3ParserTestMultiFrame(
void)
2499 uint8_t unsol_response1[] = {
2500 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2501 0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2502 0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2503 0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9,
2507 uint8_t unsol_response2[] = {
2508 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2509 0x89, 0xe5, 0xc5, 0xfb, 0x82, 0x00, 0x00, 0x02,
2510 0x02, 0x17, 0x01, 0x0c, 0x01, 0xd8, 0x75, 0xd8,
2511 0x32, 0x4c, 0xc9, 0x3c, 0x01, 0xa1, 0xc9,
2514 uint8_t combined[
sizeof(unsol_response1) +
sizeof(unsol_response2)];
2515 memcpy(combined, unsol_response1,
sizeof(unsol_response1));
2516 memcpy(combined +
sizeof(unsol_response1), unsol_response2,
2517 sizeof(unsol_response2));
2524 memset(&flow, 0,
sizeof(flow));
2525 memset(&
ssn, 0,
sizeof(
ssn));
2527 flow.
proto = IPPROTO_TCP;
2533 STREAM_TOCLIENT, combined,
sizeof(combined));
2555 static int DNP3ParserTestParsePDU01(
void)
2559 const uint8_t pkt[] = {
2561 0x0b, 0xc4, 0x17, 0x00, 0xef, 0xff, 0xc4, 0x8f,
2562 0xe1, 0xc8, 0x01, 0x01, 0x00, 0x06, 0x77, 0x6e
2566 int pdus = DNP3HandleRequestLinkLayer(NULL, dnp3state, pkt,
sizeof(pkt));
2576 DNP3StateFree(dnp3state);
2583 static int DNP3ParserObjectStructSizeTest(
void)
2585 const size_t max_point_size = 1024;
2602 static int DNP3ParserDecodeG70V2Test(
void)
2604 const uint8_t input[] = {
2627 const uint8_t *buf = input;
2628 uint16_t
len =
sizeof(input);
2650 static int DNP3ParserDecodeG70V2TruncatedTest(
void)
2652 const uint8_t input[] = {
2672 const uint8_t *buf = input;
2673 uint16_t
len =
sizeof(input);
2688 static int DNP3ParserDecodeG70V3Test(
void)
2690 const uint8_t pkt[] = {
2692 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00, 0xc7, 0xee,
2693 0xc7, 0xc9, 0x1b, 0x46, 0x03, 0x5b, 0x01, 0x55,
2694 0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2695 0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2696 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2697 0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2698 0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2699 0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2700 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2701 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2702 0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2703 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2704 0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2705 0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2711 int bytes = DNP3HandleRequestLinkLayer(NULL, dnp3state, pkt,
sizeof(pkt));
2712 FAIL_IF(bytes !=
sizeof(pkt));
2731 "C:/temp/DNPDeviceConfiguration written to Remote Device.xml") == 0);
2732 DNP3StateFree(dnp3state);
2739 static int DNP3ParserUnknownEventAlertTest(
void)
2743 0x05, 0x64, 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00,
2753 0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2754 0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2755 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2756 0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2757 0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2758 0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2759 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2760 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2761 0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2762 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2763 0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2764 0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2768 DNP3FixCrc(pkt + 10,
sizeof(pkt) - 10);
2772 int bytes = DNP3HandleRequestLinkLayer(NULL, dnp3state, pkt,
sizeof(pkt));
2773 FAIL_IF(bytes !=
sizeof(pkt));
2775 DNP3StateFree(dnp3state);
2782 static int DNP3ParserIncorrectUserData(
void)
2784 uint8_t packet_bytes[] = {
2785 0x05, 0x64, 0x08, 0xc4, 0x03, 0x00, 0x04, 0x00,
2786 0xbf, 0xe9, 0xc1, 0xc1, 0x82, 0xc5, 0xee
2792 memset(&flow, 0,
sizeof(flow));
2793 memset(&
ssn, 0,
sizeof(
ssn));
2795 flow.
proto = IPPROTO_TCP;
2800 STREAM_TOCLIENT, packet_bytes,
sizeof(packet_bytes));
2815 UtRegisterTest(
"DNP3ParserTestCheckCRC", DNP3ParserTestCheckCRC);
2817 DNP3ParserCheckLinkHeaderCRC);
2818 UtRegisterTest(
"DNP3CheckUserDataCRCsTest", DNP3CheckUserDataCRCsTest);
2819 UtRegisterTest(
"DNP3CalculateLinkLengthTest", DNP3CalculateLinkLengthTest);
2821 DNP3CalculateTransportLengthWithoutCRCsTest);
2823 DNP3ReassembleApplicationLayerTest01);
2826 DNP3ParserTestRequestResponse);
2828 DNP3ParserTestUnsolicitedResponseConfirm);
2829 UtRegisterTest(
"DNP3ParserTestPartialFrame", DNP3ParserTestPartialFrame);
2830 UtRegisterTest(
"DNP3ParserTestMultiFrame", DNP3ParserTestMultiFrame);
2832 UtRegisterTest(
"DNP3ParserTestParsePDU01", DNP3ParserTestParsePDU01);
2833 UtRegisterTest(
"DNP3ParserObjectStructSizeTest", DNP3ParserObjectStructSizeTest);
2834 UtRegisterTest(
"DNP3ParserDecodeG70V2Test", DNP3ParserDecodeG70V2Test);
2835 UtRegisterTest(
"DNP3ParserDecodeG70V2TruncatedTest", DNP3ParserDecodeG70V2TruncatedTest);
2836 UtRegisterTest(
"DNP3ParserDecodeG70V3Test", DNP3ParserDecodeG70V3Test);
2838 DNP3ParserUnknownEventAlertTest);
2839 UtRegisterTest(
"DNP3ParserIncorrectUserData", DNP3ParserIncorrectUserData);