41 #define DNP3_DEFAULT_PORT "20000"
44 #define DNP3_START_BYTE0 0x05
45 #define DNP3_START_BYTE1 0x64
48 #define DNP3_MIN_LEN 5
51 #define DNP3_CRC_LEN 2
55 #define DNP3_BLOCK_SIZE 16
58 #define DNP3_MAX_TRAN_SEQNO 64
65 #define DNP3_LINK_HDR_LEN 5
81 #define DNP3_OBJ_PREFIX(x) ((x >> 4) & 0x7)
84 #define DNP3_OBJ_RANGE(x) (x & 0xf)
92 static uint64_t dnp3_max_tx = 32;
95 static uint64_t max_points = 16384;
98 static uint64_t dnp3_max_objects = 2048;
115 #define NEXT_TH_SEQNO(current) ((current + 1) % DNP3_MAX_TRAN_SEQNO)
119 static const uint16_t crc_table[256] = {
120 0x0000, 0x365e, 0x6cbc, 0x5ae2, 0xd978, 0xef26, 0xb5c4, 0x839a,
121 0xff89, 0xc9d7, 0x9335, 0xa56b, 0x26f1, 0x10af, 0x4a4d, 0x7c13,
122 0xb26b, 0x8435, 0xded7, 0xe889, 0x6b13, 0x5d4d, 0x07af, 0x31f1,
123 0x4de2, 0x7bbc, 0x215e, 0x1700, 0x949a, 0xa2c4, 0xf826, 0xce78,
124 0x29af, 0x1ff1, 0x4513, 0x734d, 0xf0d7, 0xc689, 0x9c6b, 0xaa35,
125 0xd626, 0xe078, 0xba9a, 0x8cc4, 0x0f5e, 0x3900, 0x63e2, 0x55bc,
126 0x9bc4, 0xad9a, 0xf778, 0xc126, 0x42bc, 0x74e2, 0x2e00, 0x185e,
127 0x644d, 0x5213, 0x08f1, 0x3eaf, 0xbd35, 0x8b6b, 0xd189, 0xe7d7,
128 0x535e, 0x6500, 0x3fe2, 0x09bc, 0x8a26, 0xbc78, 0xe69a, 0xd0c4,
129 0xacd7, 0x9a89, 0xc06b, 0xf635, 0x75af, 0x43f1, 0x1913, 0x2f4d,
130 0xe135, 0xd76b, 0x8d89, 0xbbd7, 0x384d, 0x0e13, 0x54f1, 0x62af,
131 0x1ebc, 0x28e2, 0x7200, 0x445e, 0xc7c4, 0xf19a, 0xab78, 0x9d26,
132 0x7af1, 0x4caf, 0x164d, 0x2013, 0xa389, 0x95d7, 0xcf35, 0xf96b,
133 0x8578, 0xb326, 0xe9c4, 0xdf9a, 0x5c00, 0x6a5e, 0x30bc, 0x06e2,
134 0xc89a, 0xfec4, 0xa426, 0x9278, 0x11e2, 0x27bc, 0x7d5e, 0x4b00,
135 0x3713, 0x014d, 0x5baf, 0x6df1, 0xee6b, 0xd835, 0x82d7, 0xb489,
136 0xa6bc, 0x90e2, 0xca00, 0xfc5e, 0x7fc4, 0x499a, 0x1378, 0x2526,
137 0x5935, 0x6f6b, 0x3589, 0x03d7, 0x804d, 0xb613, 0xecf1, 0xdaaf,
138 0x14d7, 0x2289, 0x786b, 0x4e35, 0xcdaf, 0xfbf1, 0xa113, 0x974d,
139 0xeb5e, 0xdd00, 0x87e2, 0xb1bc, 0x3226, 0x0478, 0x5e9a, 0x68c4,
140 0x8f13, 0xb94d, 0xe3af, 0xd5f1, 0x566b, 0x6035, 0x3ad7, 0x0c89,
141 0x709a, 0x46c4, 0x1c26, 0x2a78, 0xa9e2, 0x9fbc, 0xc55e, 0xf300,
142 0x3d78, 0x0b26, 0x51c4, 0x679a, 0xe400, 0xd25e, 0x88bc, 0xbee2,
143 0xc2f1, 0xf4af, 0xae4d, 0x9813, 0x1b89, 0x2dd7, 0x7735, 0x416b,
144 0xf5e2, 0xc3bc, 0x995e, 0xaf00, 0x2c9a, 0x1ac4, 0x4026, 0x7678,
145 0x0a6b, 0x3c35, 0x66d7, 0x5089, 0xd313, 0xe54d, 0xbfaf, 0x89f1,
146 0x4789, 0x71d7, 0x2b35, 0x1d6b, 0x9ef1, 0xa8af, 0xf24d, 0xc413,
147 0xb800, 0x8e5e, 0xd4bc, 0xe2e2, 0x6178, 0x5726, 0x0dc4, 0x3b9a,
148 0xdc4d, 0xea13, 0xb0f1, 0x86af, 0x0535, 0x336b, 0x6989, 0x5fd7,
149 0x23c4, 0x159a, 0x4f78, 0x7926, 0xfabc, 0xcce2, 0x9600, 0xa05e,
150 0x6e26, 0x5878, 0x029a, 0x34c4, 0xb75e, 0x8100, 0xdbe2, 0xedbc,
151 0x91af, 0xa7f1, 0xfd13, 0xcb4d, 0x48d7, 0x7e89, 0x246b, 0x1235
162 static uint16_t DNP3ComputeCRC(
const uint8_t *buf, uint32_t
len)
164 const uint8_t *
byte = buf;
169 idx = (
crc ^ *byte) & 0xff;
170 crc = (crc_table[idx] ^ (
crc >> 8)) & 0xffff;
174 return ~
crc & 0xffff;
185 static int DNP3CheckCRC(
const uint8_t *block, uint16_t
len)
187 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
200 if (((
crc & 0xff) == block[crc_offset]) &&
201 ((
crc >> 8) == block[crc_offset + 1])) {
215 static int DNP3CheckLinkHeaderCRC(
const DNP3LinkHeader *header)
217 return DNP3CheckCRC((uint8_t *)header,
sizeof(DNP3LinkHeader));
228 static int DNP3CheckUserDataCRCs(
const uint8_t *data, uint16_t
len)
241 if (!DNP3CheckCRC(data +
offset, block_size)) {
257 static int DNP3CheckStartBytes(
const DNP3LinkHeader *header)
264 #define DNP3_BANNER "DNP3"
274 static int DNP3ContainsBanner(
const uint8_t *input, uint32_t
len)
282 static uint16_t DNP3ProbingParser(
283 const Flow *f, uint8_t direction,
const uint8_t *input, uint32_t
len, uint8_t *rdir)
285 const DNP3LinkHeader *
const hdr = (
const DNP3LinkHeader *)input;
286 const bool toserver = (direction & STREAM_TOSERVER) != 0;
289 if (DNP3ContainsBanner(input,
len)) {
291 bool is_banner =
true;
293 for (uint32_t i = 0; i <
len && i < 0x100; i++) {
294 if (!isprint(input[i])) {
301 *rdir = STREAM_TOCLIENT;
308 if (
len <
sizeof(DNP3LinkHeader)) {
309 SCLogDebug(
"Length too small to be a DNP3 header.");
314 if (!DNP3CheckStartBytes(hdr)) {
321 SCLogDebug(
"Packet too small to be a valid DNP3 fragment.");
327 *rdir = toserver ? STREAM_TOCLIENT : STREAM_TOSERVER;
340 static int DNP3CalculateTransportLengthWithoutCRCs(uint16_t input_len)
383 static int DNP3ReassembleApplicationLayer(
384 const uint8_t *input, uint16_t input_len, uint8_t **output, uint16_t *output_len)
386 int len = DNP3CalculateTransportLengthWithoutCRCs(input_len);
398 if (*output == NULL) {
405 uint8_t *ptr =
SCRealloc(*output, (
size_t)(*output_len +
len));
412 uint16_t
offset = 0, block_size;
413 while (
offset < input_len) {
418 block_size = input_len -
offset;
443 memcpy(*output + *output_len, input +
offset,
458 static void *DNP3StateAlloc(
void *orig_state,
AppProto proto_orig)
487 static void DNP3SetEvent(
DNP3State *dnp3,
bool request, uint8_t event)
489 if (dnp3 != NULL && dnp3->
curr == NULL) {
495 if (dnp3 && dnp3->
curr) {
496 DNP3SetEventTx(dnp3->
curr, event);
499 SCLogWarning(
"Failed to set event, state or tx pointer was NULL.");
546 static uint16_t DNP3CalculateLinkLength(uint8_t
length)
548 uint16_t frame_len = 0;
566 return frame_len +
sizeof(DNP3LinkHeader);
576 static int DNP3IsUserData(
const DNP3LinkHeader *header)
595 static int DNP3HasUserData(
const DNP3LinkHeader *header, uint8_t direction)
597 if (direction == STREAM_TOSERVER) {
599 sizeof(DNP3ApplicationHeader);
603 sizeof(DNP3ApplicationHeader) +
sizeof(DNP3InternalInd);
610 static void DNP3Resync(
const uint8_t **input, uint32_t *input_len, uint32_t *processed)
614 while (skip + 1 < *input_len) {
634 static void DNP3BufferReset(
DNP3Buffer *buffer)
649 static int DNP3BufferAdd(
DNP3Buffer *buffer,
const uint8_t *data, uint32_t
len)
651 if (buffer->
size == 0) {
680 static void DNP3BufferTrim(
DNP3Buffer *buffer)
683 DNP3BufferReset(buffer);
685 else if (buffer->
offset > 0) {
696 static void DNP3ObjectFree(
DNP3Object *
object)
698 if (object->
points != NULL) {
715 if (object->
points == NULL) {
716 DNP3ObjectFree(
object);
737 static int DNP3DecodeApplicationObjects(
741 uint64_t point_count = 0;
742 uint64_t object_count = 0;
744 if (buf == NULL ||
len == 0) {
751 if (
len <
sizeof(DNP3ObjHeader)) {
754 DNP3ObjHeader *header = (DNP3ObjHeader *)buf;
755 offset +=
sizeof(DNP3ObjHeader);
758 if (++object_count > dnp3_max_objects) {
769 object->group = header->group;
770 object->variation = header->variation;
771 object->qualifier = header->qualifier;
781 if (
offset + (
sizeof(uint8_t) * 2) >
len) {
784 goto not_enough_data;
786 object->start = buf[
offset++];
787 object->stop = buf[
offset++];
788 object->count =
object->stop -
object->start + 1;
795 if (
offset + (
sizeof(uint16_t) * 2) >
len) {
798 goto not_enough_data;
801 offset +=
sizeof(uint16_t);
803 offset +=
sizeof(uint16_t);
804 object->count =
object->stop -
object->start + 1;
811 if (
offset + (
sizeof(uint32_t) * 2) >
len) {
814 goto not_enough_data;
817 offset +=
sizeof(uint32_t);
819 offset +=
sizeof(uint32_t);
820 object->count =
object->stop -
object->start + 1;
831 goto not_enough_data;
833 object->count = buf[
offset];
834 offset +=
sizeof(uint8_t);
840 goto not_enough_data;
843 offset +=
sizeof(uint16_t);
850 goto not_enough_data;
853 offset +=
sizeof(uint32_t);
860 goto not_enough_data;
862 object->count = *(uint8_t *)(buf +
offset);
863 offset +=
sizeof(uint8_t);
880 point_count +=
object->count;
881 if (point_count > max_points) {
913 static void DNP3HandleUserDataRequest(
914 Flow *f,
DNP3State *dnp3,
const uint8_t *input, uint16_t input_len)
918 DNP3ApplicationHeader *ah;
921 lh = (DNP3LinkHeader *)input;
923 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
924 input_len -
sizeof(DNP3LinkHeader))) {
928 th = input[
sizeof(DNP3LinkHeader)];
932 if (ttx->lh.src == lh->src && ttx->lh.dst == lh->dst && ttx->is_request && !ttx->done &&
949 ah = (DNP3ApplicationHeader *)(input +
sizeof(DNP3LinkHeader) +
958 tx = DNP3TxAlloc(dnp3,
true);
968 if (!DNP3ReassembleApplicationLayer(input +
sizeof(DNP3LinkHeader),
991 if (DNP3DecodeApplicationObjects(tx, tx->
buffer +
sizeof(DNP3ApplicationHeader),
1000 static void DNP3HandleUserDataResponse(
1001 Flow *f,
DNP3State *dnp3,
const uint8_t *input, uint16_t input_len)
1005 DNP3ApplicationHeader *ah;
1006 DNP3InternalInd *iin;
1010 lh = (DNP3LinkHeader *)input;
1011 offset +=
sizeof(DNP3LinkHeader);
1013 if (!DNP3CheckUserDataCRCs(input +
offset, input_len -
offset)) {
1021 if (ttx->lh.src == lh->src && ttx->lh.dst == lh->dst && !ttx->is_request &&
1038 ah = (DNP3ApplicationHeader *)(input +
offset);
1039 offset +=
sizeof(DNP3ApplicationHeader);
1040 iin = (DNP3InternalInd *)(input +
offset);
1042 tx = DNP3TxAlloc(dnp3,
false);
1055 if (!DNP3ReassembleApplicationLayer(input +
sizeof(DNP3LinkHeader),
1074 offset =
sizeof(DNP3ApplicationHeader) +
sizeof(DNP3InternalInd);
1075 if (DNP3DecodeApplicationObjects(
1090 static int DNP3HandleRequestLinkLayer(
1091 Flow *f,
DNP3State *dnp3,
const uint8_t *input, uint32_t input_len)
1094 uint32_t processed = 0;
1099 if (input_len <
sizeof(DNP3LinkHeader)) {
1103 DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1105 if (!DNP3CheckStartBytes(header)) {
1110 if (!DNP3CheckLinkHeaderCRC(header)) {
1112 DNP3Resync(&input, &input_len, &processed);
1116 uint16_t frame_len = DNP3CalculateLinkLength(header->len);
1117 if (frame_len == 0) {
1119 DNP3Resync(&input, &input_len, &processed);
1122 if (input_len < frame_len) {
1128 if (!DNP3IsUserData(header)) {
1134 if (!DNP3HasUserData(header, STREAM_TOSERVER)) {
1139 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
1140 frame_len -
sizeof(DNP3LinkHeader))) {
1145 DNP3HandleUserDataRequest(f, dnp3, input, frame_len);
1150 input_len -= frame_len;
1151 processed += frame_len;
1173 const uint8_t *input = StreamSliceGetData(&stream_slice);
1174 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1176 if (input_len == 0) {
1181 if (!DNP3BufferAdd(buffer, input, input_len)) {
1184 processed = DNP3HandleRequestLinkLayer(
1186 if (processed < 0) {
1189 buffer->
offset += processed;
1190 DNP3BufferTrim(buffer);
1193 processed = DNP3HandleRequestLinkLayer(f, dnp3, input, input_len);
1194 if (processed < 0) {
1195 SCLogDebug(
"Failed to process request link layer.");
1200 input_len -= processed;
1204 if (!DNP3BufferAdd(buffer, input, input_len)) {
1214 DNP3BufferReset(buffer);
1224 static int DNP3HandleResponseLinkLayer(
1225 Flow *f,
DNP3State *dnp3,
const uint8_t *input, uint32_t input_len)
1228 uint32_t processed = 0;
1233 if (input_len <
sizeof(DNP3LinkHeader)) {
1237 DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1239 if (!DNP3CheckStartBytes(header)) {
1244 if (!DNP3CheckLinkHeaderCRC(header)) {
1246 DNP3Resync(&input, &input_len, &processed);
1251 uint16_t frame_len = DNP3CalculateLinkLength(header->len);
1252 if (frame_len == 0) {
1254 DNP3Resync(&input, &input_len, &processed);
1257 if (input_len < frame_len) {
1263 if (!DNP3IsUserData(header)) {
1269 if (!DNP3HasUserData(header, STREAM_TOCLIENT)) {
1274 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
1275 frame_len -
sizeof(DNP3LinkHeader))) {
1280 DNP3HandleUserDataResponse(f, dnp3, input, frame_len);
1285 input_len -= frame_len;
1286 processed += frame_len;
1310 const uint8_t *input = StreamSliceGetData(&stream_slice);
1311 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1314 if (!DNP3BufferAdd(buffer, input, input_len)) {
1317 processed = DNP3HandleResponseLinkLayer(
1319 if (processed < 0) {
1322 buffer->
offset += processed;
1323 DNP3BufferTrim(buffer);
1328 if (DNP3ContainsBanner(input, input_len)) {
1332 processed = DNP3HandleResponseLinkLayer(f, dnp3, input, input_len);
1333 if (processed < 0) {
1337 input_len -= processed;
1341 if (!DNP3BufferAdd(buffer, input, input_len)) {
1353 DNP3BufferReset(buffer);
1357 static void *DNP3GetTx(
void *alstate, uint64_t tx_id)
1362 uint64_t tx_num = tx_id + 1;
1369 if (tx_num != tx->
tx_num) {
1378 static uint64_t DNP3GetTxCnt(
void *state)
1381 uint64_t count = ((uint64_t)((
DNP3State *)state)->transaction_max);
1388 static void DNP3TxFreeObjectList(DNP3ObjectList *objects)
1394 DNP3ObjectFree(
object);
1405 if (tx->
buffer != NULL) {
1411 DNP3TxFreeObjectList(&tx->
objects);
1423 static void DNP3StateTxFree(
void *state, uint64_t tx_id)
1428 uint64_t tx_num = tx_id + 1;
1432 if (tx->
tx_num != tx_num) {
1436 if (tx == dnp3->
curr) {
1465 static void DNP3StateFree(
void *state)
1470 if (state != NULL) {
1471 while ((tx =
TAILQ_FIRST(&dnp3->tx_list)) != NULL) {
1489 static int DNP3GetAlstateProgress(
void *tx, uint8_t direction)
1497 SCLogDebug(
"flooded: returning tx as done.");
1510 static int DNP3StateGetEventInfo(
1523 static int DNP3StateGetEventInfoById(
1527 if (*event_name == NULL) {
1529 "the DNP3 enum event map table.",
1558 switch (prefix_code) {
1576 if (state->
un.
ptr == NULL) {
1582 while (tx_ptr->
tx_num < min_tx_id + 1) {
1588 if (tx_ptr->
tx_num >= max_tx_id + 1) {
1594 .tx_id = tx_ptr->
tx_num - 1,
1595 .has_next = (state->
un.
ptr != NULL),
1610 const char *proto_name =
"dnp3";
1617 sizeof(DNP3LinkHeader), STREAM_TOSERVER, DNP3ProbingParser, DNP3ProbingParser);
1621 0,
sizeof(DNP3LinkHeader), DNP3ProbingParser, DNP3ProbingParser)) {
1627 SCLogConfig(
"Protocol detection and parser disabled for DNP3.");
1640 DNP3StateAlloc, DNP3StateFree);
1649 DNP3GetAlstateProgress);
1653 DNP3StateGetEventInfo);
1655 DNP3StateGetEventInfoById);
1663 if (
SCConfGetInt(
"app-layer.protocols.dnp3.max-tx", &value)) {
1664 dnp3_max_tx = (uint64_t)value;
1668 if (
SCConfGetInt(
"app-layer.protocols.dnp3.max-points", &value)) {
1670 max_points = (uint64_t)value;
1675 if (
SCConfGetInt(
"app-layer.protocols.dnp3.max-objects", &value)) {
1677 dnp3_max_objects = (uint64_t)value;
1682 "Protocol detection still on.", proto_name);
1701 static void DNP3FixCrc(uint8_t *data, uint32_t
len)
1703 uint32_t block_size;
1711 uint16_t
crc = DNP3ComputeCRC(data, block_size);
1712 data[block_size + 1] = (
crc >> 8) & 0xff;
1713 data[block_size] =
crc & 0xff;
1722 static int DNP3ParserTestCheckCRC(
void)
1724 uint8_t request[] = {
1726 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1733 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1734 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1738 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1742 FAIL_IF(!DNP3CheckCRC(request,
sizeof(DNP3LinkHeader)));
1745 FAIL_IF(!DNP3CheckCRC(request +
sizeof(DNP3LinkHeader),
1748 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1751 FAIL_IF(DNP3CheckCRC(request,
sizeof(DNP3LinkHeader)));
1755 request[
sizeof(DNP3LinkHeader) + 3]++;
1756 FAIL_IF(DNP3CheckCRC(request +
sizeof(DNP3LinkHeader),
1766 static int DNP3CheckUserDataCRCsTest(
void)
1769 uint8_t data_valid[] = {
1770 0xff, 0xc9, 0x05, 0x0c,
1771 0x01, 0x28, 0x01, 0x00,
1772 0x00, 0x00, 0x01, 0x01,
1773 0x01, 0x00, 0x00, 0x00,
1776 0xff, 0xc9, 0x05, 0x0c,
1777 0x01, 0x28, 0x01, 0x00,
1778 0x00, 0x00, 0x01, 0x01,
1779 0x01, 0x00, 0x00, 0x00,
1782 0xff, 0xc9, 0x05, 0x0c,
1783 0x01, 0x28, 0x01, 0x00,
1784 0x00, 0x00, 0x01, 0x01,
1785 0x01, 0x00, 0x00, 0x00,
1788 0x00, 0x00, 0x00, 0x00,
1792 FAIL_IF(!DNP3CheckUserDataCRCs(data_valid,
sizeof(data_valid)));
1794 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1796 uint8_t data_invalid[] = {
1797 0xff, 0xc9, 0x05, 0x0c,
1798 0x01, 0x28, 0x01, 0x00,
1799 0x00, 0x00, 0x01, 0x01,
1800 0x01, 0x00, 0x00, 0x00,
1803 0xff, 0xc9, 0x05, 0x0c,
1804 0x01, 0x28, 0x01, 0x00,
1805 0x00, 0x00, 0x01, 0x01,
1806 0x01, 0x00, 0x00, 0x00,
1809 0xff, 0xc9, 0x05, 0x0c,
1810 0x01, 0x28, 0x01, 0x00,
1811 0x00, 0x00, 0x01, 0x01,
1812 0x01, 0x00, 0x00, 0x00,
1815 0x00, 0x00, 0x00, 0x00,
1819 FAIL_IF(DNP3CheckUserDataCRCs(data_invalid,
sizeof(data_invalid)));
1822 uint8_t one_byte_nocrc[] = { 0x01 };
1823 FAIL_IF(DNP3CheckUserDataCRCs(one_byte_nocrc,
sizeof(one_byte_nocrc)));
1826 uint8_t two_byte_nocrc[] = { 0x01, 0x02 };
1827 FAIL_IF(DNP3CheckUserDataCRCs(two_byte_nocrc,
sizeof(two_byte_nocrc)));
1831 uint8_t three_bytes_good_crc[] = { 0x00, 0x00, 0x00 };
1832 *(uint16_t *)(three_bytes_good_crc + 1) = DNP3ComputeCRC(
1833 three_bytes_good_crc, 1);
1834 FAIL_IF(!DNP3CheckUserDataCRCs(three_bytes_good_crc,
1835 sizeof(three_bytes_good_crc)));
1847 static int DNP3CalculateLinkLengthTest(
void)
1850 FAIL_IF(DNP3CalculateLinkLength(0) != 0);
1851 FAIL_IF(DNP3CalculateLinkLength(1) != 0);
1852 FAIL_IF(DNP3CalculateLinkLength(2) != 0);
1853 FAIL_IF(DNP3CalculateLinkLength(3) != 0);
1854 FAIL_IF(DNP3CalculateLinkLength(4) != 0);
1857 FAIL_IF(DNP3CalculateLinkLength(5) != 10);
1860 FAIL_IF(DNP3CalculateLinkLength(21) != 28);
1863 FAIL_IF(DNP3CalculateLinkLength(37) != 46);
1867 FAIL_IF(DNP3CalculateLinkLength(38) != 49);
1870 FAIL_IF(DNP3CalculateLinkLength(255) != 292);
1879 static int DNP3CalculateTransportLengthWithoutCRCsTest(
void)
1881 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(0) != -1);
1882 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(1) != -1);
1883 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(2) != 0);
1884 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(3) != 1);
1885 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(16) != 14);
1886 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(17) != 15);
1887 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(18) != 16);
1890 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(19) != -1);
1894 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(20) != 16);
1896 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(21) != 17);
1904 static int DNP3ParserCheckLinkHeaderCRC(
void)
1907 uint8_t request[] = {
1909 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1916 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1917 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1918 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1921 DNP3LinkHeader *header = (DNP3LinkHeader *)request;
1922 FAIL_IF(!DNP3CheckLinkHeaderCRC(header));
1924 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1927 FAIL_IF(DNP3CheckLinkHeaderCRC(header));
1936 static int DNP3ReassembleApplicationLayerTest01(
void)
1938 uint16_t reassembled_len = 0;
1939 uint8_t *output = NULL;
1941 uint8_t payload[] = {
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,
1955 0xff, 0xc9, 0x05, 0x0c,
1956 0x01, 0x28, 0x01, 0x00,
1957 0x00, 0x00, 0x01, 0x01,
1958 0x01, 0x00, 0x00, 0x00,
1961 0x00, 0x00, 0x00, 0x00,
1966 uint8_t expected[] = {
1968 0x01, 0x28, 0x01, 0x00,
1969 0x00, 0x00, 0x01, 0x01,
1970 0x01, 0x00, 0x00, 0x00,
1972 0xff, 0xc9, 0x05, 0x0c,
1973 0x01, 0x28, 0x01, 0x00,
1974 0x00, 0x00, 0x01, 0x01,
1975 0x01, 0x00, 0x00, 0x00,
1977 0xff, 0xc9, 0x05, 0x0c,
1978 0x01, 0x28, 0x01, 0x00,
1979 0x00, 0x00, 0x01, 0x01,
1980 0x01, 0x00, 0x00, 0x00,
1982 0x00, 0x00, 0x00, 0x00,
1988 FAIL_IF(!DNP3ReassembleApplicationLayer(payload,
1989 sizeof(payload), &output, &reassembled_len));
1991 FAIL_IF(reassembled_len !=
sizeof(expected));
1992 FAIL_IF(memcmp(expected, output, reassembled_len));
1996 reassembled_len = 0;
1998 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 1, &output,
2001 FAIL_IF(reassembled_len != 0);
2004 reassembled_len = 0;
2006 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 2, &output,
2009 FAIL_IF(reassembled_len != 0);
2013 reassembled_len = 0;
2015 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 3, &output,
2018 FAIL_IF(reassembled_len != 0);
2021 reassembled_len = 0;
2023 FAIL_IF(!DNP3ReassembleApplicationLayer(payload, 4, &output,
2026 FAIL_IF(reassembled_len != 1);
2029 uint8_t short_payload1[] = {
2031 0xff, 0xc9, 0x05, 0x0c,
2032 0x01, 0x28, 0x01, 0x00,
2033 0x00, 0x00, 0x01, 0x01,
2034 0x01, 0x00, 0x00, 0x00,
2037 0xff, 0xc9, 0x05, 0x0c,
2038 0x01, 0x28, 0x01, 0x00,
2039 0x00, 0x00, 0x01, 0x01,
2040 0x01, 0x00, 0x00, 0x00,
2043 0xff, 0xc9, 0x05, 0x0c,
2044 0x01, 0x28, 0x01, 0x00,
2045 0x00, 0x00, 0x01, 0x01,
2046 0x01, 0x00, 0x00, 0x00,
2051 reassembled_len = 0;
2052 FAIL_IF(DNP3ReassembleApplicationLayer(short_payload1,
2053 sizeof(short_payload1), &output, &reassembled_len));
2056 uint8_t short_payload2[] = {
2058 0xff, 0xc9, 0x05, 0x0c,
2059 0x01, 0x28, 0x01, 0x00,
2060 0x00, 0x00, 0x01, 0x01,
2061 0x01, 0x00, 0x00, 0x00,
2064 0xff, 0xc9, 0x05, 0x0c,
2065 0x01, 0x28, 0x01, 0x00,
2066 0x00, 0x00, 0x01, 0x01,
2067 0x01, 0x00, 0x00, 0x00,
2070 0xff, 0xc9, 0x05, 0x0c,
2071 0x01, 0x28, 0x01, 0x00,
2072 0x00, 0x00, 0x01, 0x01,
2073 0x01, 0x00, 0x00, 0x00,
2078 reassembled_len = 0;
2079 FAIL_IF(DNP3ReassembleApplicationLayer(short_payload2,
2080 sizeof(short_payload2), &output, &reassembled_len));
2090 static int DNP3ProbingParserTest(
void)
2093 0x05, 0x64, 0x05, 0xc9, 0x03, 0x00, 0x04, 0x00,
2099 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt,
sizeof(pkt), &rdir) !=
ALPROTO_DNP3);
2102 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt,
sizeof(DNP3LinkHeader) - 1, &rdir) !=
ALPROTO_UNKNOWN);
2116 char mybanner[] =
"Welcome to DNP3 SCADA.";
2117 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, (uint8_t *)mybanner,
sizeof(mybanner) - 1,
2119 FAIL_IF(rdir != STREAM_TOCLIENT);
2127 static int DNP3ParserTestRequestResponse(
void)
2131 uint8_t request[] = {
2133 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2140 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2141 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2142 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2145 uint8_t response[] = {
2147 0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2154 0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2155 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2156 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2164 memset(&flow, 0,
sizeof(flow));
2165 memset(&ssn, 0,
sizeof(ssn));
2168 flow.
proto = IPPROTO_TCP;
2175 STREAM_TOSERVER, request,
sizeof(request)));
2191 STREAM_TOCLIENT, response,
sizeof(response)));
2210 static int DNP3ParserTestUnsolicitedResponseConfirm(
void)
2215 uint8_t response[] = {
2216 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2217 0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2218 0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2219 0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9
2223 uint8_t confirm[] = {
2224 0x05, 0x64, 0x08, 0xc4, 0x02, 0x00,
2225 0x01, 0x00, 0xd3, 0xb7, 0xc0, 0xda, 0x00, 0x6a,
2233 memset(&flow, 0,
sizeof(flow));
2234 memset(&ssn, 0,
sizeof(ssn));
2237 flow.
proto = IPPROTO_TCP;
2244 STREAM_TOCLIENT, response,
sizeof(response)));
2259 STREAM_TOSERVER, confirm,
sizeof(confirm)));
2280 static int DNP3ParserTestFlooded(
void)
2284 uint8_t request[] = {
2286 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2293 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2294 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2295 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2302 memset(&flow, 0,
sizeof(flow));
2303 memset(&ssn, 0,
sizeof(ssn));
2306 flow.
proto = IPPROTO_TCP;
2313 STREAM_TOSERVER, request,
sizeof(request)));
2327 FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2329 for (uint64_t i = 0; i < dnp3_max_tx - 1; i++) {
2332 STREAM_TOSERVER, request,
sizeof(request)));
2336 FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2341 STREAM_TOSERVER, request,
sizeof(request)));
2346 FAIL_IF(!DNP3GetAlstateProgress(tx, 0));
2361 static int DNP3ParserTestPartialFrame(
void)
2367 uint8_t request_partial1[] = {
2369 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2376 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2379 uint8_t request_partial2[] = {
2381 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2382 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2385 uint8_t response_partial1[] = {
2387 0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2394 0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2397 uint8_t response_partial2[] = {
2398 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2399 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2407 memset(&flow, 0,
sizeof(flow));
2408 memset(&ssn, 0,
sizeof(ssn));
2410 flow.
proto = IPPROTO_TCP;
2418 STREAM_TOSERVER, request_partial1,
sizeof(request_partial1));
2428 sizeof(request_partial1)));
2432 FAIL_IF(DNP3GetTx(state, 0) != NULL);
2437 STREAM_TOSERVER, request_partial2,
sizeof(request_partial2));
2447 tx = DNP3GetTx(state, 0);
2458 STREAM_TOCLIENT, response_partial1,
sizeof(response_partial1));
2463 tx = DNP3GetTx(state, 1);
2469 STREAM_TOCLIENT, response_partial2,
sizeof(response_partial2));
2478 tx = DNP3GetTx(state, 1);
2492 static int DNP3ParserTestMultiFrame(
void)
2497 uint8_t unsol_response1[] = {
2498 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2499 0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2500 0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2501 0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9,
2505 uint8_t unsol_response2[] = {
2506 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2507 0x89, 0xe5, 0xc5, 0xfb, 0x82, 0x00, 0x00, 0x02,
2508 0x02, 0x17, 0x01, 0x0c, 0x01, 0xd8, 0x75, 0xd8,
2509 0x32, 0x4c, 0xc9, 0x3c, 0x01, 0xa1, 0xc9,
2512 uint8_t combined[
sizeof(unsol_response1) +
sizeof(unsol_response2)];
2513 memcpy(combined, unsol_response1,
sizeof(unsol_response1));
2514 memcpy(combined +
sizeof(unsol_response1), unsol_response2,
2515 sizeof(unsol_response2));
2522 memset(&flow, 0,
sizeof(flow));
2523 memset(&ssn, 0,
sizeof(ssn));
2525 flow.
proto = IPPROTO_TCP;
2531 STREAM_TOCLIENT, combined,
sizeof(combined));
2553 static int DNP3ParserTestParsePDU01(
void)
2557 const uint8_t pkt[] = {
2559 0x0b, 0xc4, 0x17, 0x00, 0xef, 0xff, 0xc4, 0x8f,
2560 0xe1, 0xc8, 0x01, 0x01, 0x00, 0x06, 0x77, 0x6e
2564 int pdus = DNP3HandleRequestLinkLayer(NULL, dnp3state, pkt,
sizeof(pkt));
2574 DNP3StateFree(dnp3state);
2581 static int DNP3ParserObjectStructSizeTest(
void)
2583 const size_t max_point_size = 1024;
2600 static int DNP3ParserDecodeG70V2Test(
void)
2602 const uint8_t input[] = {
2625 const uint8_t *buf = input;
2626 uint16_t
len =
sizeof(input);
2648 static int DNP3ParserDecodeG70V2TruncatedTest(
void)
2650 const uint8_t input[] = {
2670 const uint8_t *buf = input;
2671 uint16_t
len =
sizeof(input);
2686 static int DNP3ParserDecodeG70V3Test(
void)
2688 const uint8_t pkt[] = {
2690 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00, 0xc7, 0xee,
2691 0xc7, 0xc9, 0x1b, 0x46, 0x03, 0x5b, 0x01, 0x55,
2692 0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2693 0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2694 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2695 0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2696 0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2697 0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2698 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2699 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2700 0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2701 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2702 0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2703 0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2709 int bytes = DNP3HandleRequestLinkLayer(NULL, dnp3state, pkt,
sizeof(pkt));
2710 FAIL_IF(bytes !=
sizeof(pkt));
2729 "C:/temp/DNPDeviceConfiguration written to Remote Device.xml") == 0);
2730 DNP3StateFree(dnp3state);
2737 static int DNP3ParserUnknownEventAlertTest(
void)
2741 0x05, 0x64, 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00,
2751 0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2752 0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2753 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2754 0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2755 0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2756 0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2757 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2758 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2759 0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2760 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2761 0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2762 0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2766 DNP3FixCrc(pkt + 10,
sizeof(pkt) - 10);
2770 int bytes = DNP3HandleRequestLinkLayer(NULL, dnp3state, pkt,
sizeof(pkt));
2771 FAIL_IF(bytes !=
sizeof(pkt));
2773 DNP3StateFree(dnp3state);
2780 static int DNP3ParserIncorrectUserData(
void)
2782 uint8_t packet_bytes[] = {
2783 0x05, 0x64, 0x08, 0xc4, 0x03, 0x00, 0x04, 0x00,
2784 0xbf, 0xe9, 0xc1, 0xc1, 0x82, 0xc5, 0xee
2790 memset(&flow, 0,
sizeof(flow));
2791 memset(&ssn, 0,
sizeof(ssn));
2793 flow.
proto = IPPROTO_TCP;
2798 STREAM_TOCLIENT, packet_bytes,
sizeof(packet_bytes));
2813 UtRegisterTest(
"DNP3ParserTestCheckCRC", DNP3ParserTestCheckCRC);
2815 DNP3ParserCheckLinkHeaderCRC);
2816 UtRegisterTest(
"DNP3CheckUserDataCRCsTest", DNP3CheckUserDataCRCsTest);
2817 UtRegisterTest(
"DNP3CalculateLinkLengthTest", DNP3CalculateLinkLengthTest);
2819 DNP3CalculateTransportLengthWithoutCRCsTest);
2821 DNP3ReassembleApplicationLayerTest01);
2824 DNP3ParserTestRequestResponse);
2826 DNP3ParserTestUnsolicitedResponseConfirm);
2827 UtRegisterTest(
"DNP3ParserTestPartialFrame", DNP3ParserTestPartialFrame);
2828 UtRegisterTest(
"DNP3ParserTestMultiFrame", DNP3ParserTestMultiFrame);
2830 UtRegisterTest(
"DNP3ParserTestParsePDU01", DNP3ParserTestParsePDU01);
2831 UtRegisterTest(
"DNP3ParserObjectStructSizeTest", DNP3ParserObjectStructSizeTest);
2832 UtRegisterTest(
"DNP3ParserDecodeG70V2Test", DNP3ParserDecodeG70V2Test);
2833 UtRegisterTest(
"DNP3ParserDecodeG70V2TruncatedTest", DNP3ParserDecodeG70V2TruncatedTest);
2834 UtRegisterTest(
"DNP3ParserDecodeG70V3Test", DNP3ParserDecodeG70V3Test);
2836 DNP3ParserUnknownEventAlertTest);
2837 UtRegisterTest(
"DNP3ParserIncorrectUserData", DNP3ParserIncorrectUserData);