38 #define DNP3_DEFAULT_REQ_FLOOD_COUNT 500
40 #define DNP3_DEFAULT_PORT "20000"
43 #define DNP3_START_BYTE0 0x05
44 #define DNP3_START_BYTE1 0x64
47 #define DNP3_MIN_LEN 5
50 #define DNP3_CRC_LEN 2
54 #define DNP3_BLOCK_SIZE 16
57 #define DNP3_MAX_TRAN_SEQNO 64
60 #define DNP3_MAX_APP_SEQNO 16
64 #define DNP3_LINK_HDR_LEN 5
73 #define DNP3_RESERVED_ADDR_MIN 0xfff0
74 #define DNP3_RESERVED_ADDR_MAX 0xfffb
77 #define DNP3_SRC_ADDR_MAX 0xfff0
79 #define DNP3_OBJ_TIME_SIZE 6
80 #define DNP3_OBJ_G12_V1_SIZE 11
81 #define DNP3_OBJ_G12_V2_SIZE 11
82 #define DNP3_OBJ_G12_V3_SIZE 1
85 #define DNP3_OBJ_PREFIX(x) ((x >> 4) & 0x7)
88 #define DNP3_OBJ_RANGE(x) (x & 0xf)
102 #define NEXT_TH_SEQNO(current) ((current + 1) % DNP3_MAX_TRAN_SEQNO)
105 #define NEXT_APP_SEQNO(current) ((current + 1) % DNP3_MAX_APP_SEQNO)
109 static const uint16_t crc_table[256] = {
110 0x0000, 0x365e, 0x6cbc, 0x5ae2, 0xd978, 0xef26, 0xb5c4, 0x839a,
111 0xff89, 0xc9d7, 0x9335, 0xa56b, 0x26f1, 0x10af, 0x4a4d, 0x7c13,
112 0xb26b, 0x8435, 0xded7, 0xe889, 0x6b13, 0x5d4d, 0x07af, 0x31f1,
113 0x4de2, 0x7bbc, 0x215e, 0x1700, 0x949a, 0xa2c4, 0xf826, 0xce78,
114 0x29af, 0x1ff1, 0x4513, 0x734d, 0xf0d7, 0xc689, 0x9c6b, 0xaa35,
115 0xd626, 0xe078, 0xba9a, 0x8cc4, 0x0f5e, 0x3900, 0x63e2, 0x55bc,
116 0x9bc4, 0xad9a, 0xf778, 0xc126, 0x42bc, 0x74e2, 0x2e00, 0x185e,
117 0x644d, 0x5213, 0x08f1, 0x3eaf, 0xbd35, 0x8b6b, 0xd189, 0xe7d7,
118 0x535e, 0x6500, 0x3fe2, 0x09bc, 0x8a26, 0xbc78, 0xe69a, 0xd0c4,
119 0xacd7, 0x9a89, 0xc06b, 0xf635, 0x75af, 0x43f1, 0x1913, 0x2f4d,
120 0xe135, 0xd76b, 0x8d89, 0xbbd7, 0x384d, 0x0e13, 0x54f1, 0x62af,
121 0x1ebc, 0x28e2, 0x7200, 0x445e, 0xc7c4, 0xf19a, 0xab78, 0x9d26,
122 0x7af1, 0x4caf, 0x164d, 0x2013, 0xa389, 0x95d7, 0xcf35, 0xf96b,
123 0x8578, 0xb326, 0xe9c4, 0xdf9a, 0x5c00, 0x6a5e, 0x30bc, 0x06e2,
124 0xc89a, 0xfec4, 0xa426, 0x9278, 0x11e2, 0x27bc, 0x7d5e, 0x4b00,
125 0x3713, 0x014d, 0x5baf, 0x6df1, 0xee6b, 0xd835, 0x82d7, 0xb489,
126 0xa6bc, 0x90e2, 0xca00, 0xfc5e, 0x7fc4, 0x499a, 0x1378, 0x2526,
127 0x5935, 0x6f6b, 0x3589, 0x03d7, 0x804d, 0xb613, 0xecf1, 0xdaaf,
128 0x14d7, 0x2289, 0x786b, 0x4e35, 0xcdaf, 0xfbf1, 0xa113, 0x974d,
129 0xeb5e, 0xdd00, 0x87e2, 0xb1bc, 0x3226, 0x0478, 0x5e9a, 0x68c4,
130 0x8f13, 0xb94d, 0xe3af, 0xd5f1, 0x566b, 0x6035, 0x3ad7, 0x0c89,
131 0x709a, 0x46c4, 0x1c26, 0x2a78, 0xa9e2, 0x9fbc, 0xc55e, 0xf300,
132 0x3d78, 0x0b26, 0x51c4, 0x679a, 0xe400, 0xd25e, 0x88bc, 0xbee2,
133 0xc2f1, 0xf4af, 0xae4d, 0x9813, 0x1b89, 0x2dd7, 0x7735, 0x416b,
134 0xf5e2, 0xc3bc, 0x995e, 0xaf00, 0x2c9a, 0x1ac4, 0x4026, 0x7678,
135 0x0a6b, 0x3c35, 0x66d7, 0x5089, 0xd313, 0xe54d, 0xbfaf, 0x89f1,
136 0x4789, 0x71d7, 0x2b35, 0x1d6b, 0x9ef1, 0xa8af, 0xf24d, 0xc413,
137 0xb800, 0x8e5e, 0xd4bc, 0xe2e2, 0x6178, 0x5726, 0x0dc4, 0x3b9a,
138 0xdc4d, 0xea13, 0xb0f1, 0x86af, 0x0535, 0x336b, 0x6989, 0x5fd7,
139 0x23c4, 0x159a, 0x4f78, 0x7926, 0xfabc, 0xcce2, 0x9600, 0xa05e,
140 0x6e26, 0x5878, 0x029a, 0x34c4, 0xb75e, 0x8100, 0xdbe2, 0xedbc,
141 0x91af, 0xa7f1, 0xfd13, 0xcb4d, 0x48d7, 0x7e89, 0x246b, 0x1235
151 static uint16_t DNP3ComputeCRC(
const uint8_t *buf, uint32_t
len)
153 const uint8_t *
byte = buf;
158 idx = (
crc ^ *byte) & 0xff;
159 crc = (crc_table[idx] ^ (
crc >> 8)) & 0xffff;
163 return ~
crc & 0xffff;
174 static int DNP3CheckCRC(
const uint8_t *block, uint32_t
len)
176 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
189 if (((
crc & 0xff) == block[crc_offset]) &&
190 ((
crc >> 8) == block[crc_offset + 1])) {
204 static int DNP3CheckLinkHeaderCRC(
const DNP3LinkHeader *header)
206 return DNP3CheckCRC((uint8_t *)header,
sizeof(DNP3LinkHeader));
217 static int DNP3CheckUserDataCRCs(
const uint8_t *data, uint32_t
len)
230 if (!DNP3CheckCRC(data +
offset, block_size)) {
246 static int DNP3CheckStartBytes(
const DNP3LinkHeader *header)
253 #define DNP3_BANNER "DNP3"
263 static int DNP3ContainsBanner(
const uint8_t *input, uint32_t
len)
271 static uint16_t DNP3ProbingParser(
Flow *f, uint8_t direction,
272 const uint8_t *input, uint32_t
len,
275 const DNP3LinkHeader *
const hdr = (
const DNP3LinkHeader *)input;
276 const bool toserver = (direction & STREAM_TOSERVER) != 0;
279 if (DNP3ContainsBanner(input,
len)) {
281 bool is_banner =
true;
283 for (uint32_t i = 0; i <
len && i < 0x100; i++) {
284 if (!isprint(input[i])) {
291 *rdir = STREAM_TOCLIENT;
298 if (
len <
sizeof(DNP3LinkHeader)) {
299 SCLogDebug(
"Length too small to be a DNP3 header.");
304 if (!DNP3CheckStartBytes(hdr)) {
311 SCLogDebug(
"Packet too small to be a valid DNP3 fragment.");
317 *rdir = toserver ? STREAM_TOCLIENT : STREAM_TOSERVER;
330 static int DNP3CalculateTransportLengthWithoutCRCs(uint32_t input_len)
373 static int DNP3ReassembleApplicationLayer(
const uint8_t *input,
374 uint32_t input_len, uint8_t **output, uint32_t *output_len)
376 int len = DNP3CalculateTransportLengthWithoutCRCs(input_len);
388 if (*output == NULL) {
395 uint8_t *ptr =
SCRealloc(*output, (
size_t)(*output_len +
len));
402 int offset = 0, block_size;
403 while ((uint32_t)
offset < input_len) {
408 block_size = input_len -
offset;
433 memcpy(*output + *output_len, input +
offset,
448 static void *DNP3StateAlloc(
void *orig_state,
AppProto proto_orig)
467 static void DNP3SetEvent(
DNP3State *dnp3, uint8_t event)
469 if (dnp3 && dnp3->
curr) {
525 static uint32_t DNP3CalculateLinkLength(uint8_t length)
527 uint32_t frame_len = 0;
545 return frame_len +
sizeof(DNP3LinkHeader);
555 static int DNP3IsUserData(
const DNP3LinkHeader *header)
574 static int DNP3HasUserData(
const DNP3LinkHeader *header, uint8_t direction)
576 if (direction == STREAM_TOSERVER) {
578 sizeof(DNP3ApplicationHeader);
582 sizeof(DNP3ApplicationHeader) +
sizeof(DNP3InternalInd);
589 static void DNP3BufferReset(
DNP3Buffer *buffer)
604 static int DNP3BufferAdd(
DNP3Buffer *buffer,
const uint8_t *data, uint32_t
len)
606 if (buffer->
size == 0) {
635 static void DNP3BufferTrim(
DNP3Buffer *buffer)
638 DNP3BufferReset(buffer);
640 else if (buffer->
offset > 0) {
651 static void DNP3ObjectFree(
DNP3Object *
object)
653 if (object->
points != NULL) {
670 if (object->
points == NULL) {
671 DNP3ObjectFree(
object);
692 static int DNP3DecodeApplicationObjects(
DNP3Transaction *tx,
const uint8_t *buf,
693 uint32_t
len, DNP3ObjectList *objects)
697 if (buf == NULL ||
len == 0) {
704 if (
len <
sizeof(DNP3ObjHeader)) {
707 DNP3ObjHeader *header = (DNP3ObjHeader *)buf;
708 offset +=
sizeof(DNP3ObjHeader);
716 object->group = header->group;
717 object->variation = header->variation;
718 object->qualifier = header->qualifier;
728 if (
offset + (
sizeof(uint8_t) * 2) >
len) {
731 goto not_enough_data;
733 object->start = buf[
offset++];
734 object->stop = buf[
offset++];
735 object->count =
object->stop -
object->start + 1;
742 if (
offset + (
sizeof(uint16_t) * 2) >
len) {
745 goto not_enough_data;
748 offset +=
sizeof(uint16_t);
750 offset +=
sizeof(uint16_t);
751 object->count =
object->stop -
object->start + 1;
758 if (
offset + (
sizeof(uint32_t) * 2) >
len) {
761 goto not_enough_data;
764 offset +=
sizeof(uint32_t);
766 offset +=
sizeof(uint32_t);
767 object->count =
object->stop -
object->start + 1;
778 goto not_enough_data;
780 object->count = buf[
offset];
781 offset +=
sizeof(uint8_t);
787 goto not_enough_data;
790 offset +=
sizeof(uint16_t);
797 goto not_enough_data;
800 offset +=
sizeof(uint32_t);
807 goto not_enough_data;
809 object->count = *(uint8_t *)(buf +
offset);
810 offset +=
sizeof(uint8_t);
853 static void DNP3HandleUserDataRequest(
DNP3State *dnp3,
const uint8_t *input,
858 DNP3ApplicationHeader *ah;
861 lh = (DNP3LinkHeader *)input;
863 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
864 input_len -
sizeof(DNP3LinkHeader))) {
868 th = input[
sizeof(DNP3LinkHeader)];
872 if (ttx->request_lh.src == lh->src &&
873 ttx->request_lh.dst == lh->dst &&
875 !ttx->request_done &&
892 ah = (DNP3ApplicationHeader *)(input +
sizeof(DNP3LinkHeader) +
901 tx = DNP3TxAlloc(dnp3);
912 if (!DNP3ReassembleApplicationLayer(input +
sizeof(DNP3LinkHeader),
913 input_len -
sizeof(DNP3LinkHeader),
942 if (DNP3DecodeApplicationObjects(
950 static void DNP3HandleUserDataResponse(
DNP3State *dnp3,
const uint8_t *input,
955 DNP3ApplicationHeader *ah;
956 DNP3InternalInd *iin;
960 lh = (DNP3LinkHeader *)input;
961 offset +=
sizeof(DNP3LinkHeader);
963 if (!DNP3CheckUserDataCRCs(input +
offset, input_len -
offset)) {
971 if (ttx->response_lh.src == lh->src &&
972 ttx->response_lh.dst == lh->dst &&
973 ttx->has_response && !ttx->response_done &&
990 ah = (DNP3ApplicationHeader *)(input +
offset);
991 offset +=
sizeof(DNP3ApplicationHeader);
992 iin = (DNP3InternalInd *)(input +
offset);
995 tx = DNP3TxAlloc(dnp3);
1008 if (ttx->has_request &&
1009 ttx->request_done &&
1010 ttx->request_lh.src == lh->dst &&
1011 ttx->request_lh.dst == lh->src &&
1012 !ttx->has_response &&
1013 !ttx->response_done &&
1031 if (!DNP3ReassembleApplicationLayer(input +
sizeof(DNP3LinkHeader),
1032 input_len -
sizeof(DNP3LinkHeader),
1044 offset =
sizeof(DNP3ApplicationHeader) +
sizeof(DNP3InternalInd);
1058 static int DNP3HandleRequestLinkLayer(
DNP3State *dnp3,
const uint8_t *input,
1062 uint32_t processed = 0;
1067 if (input_len <
sizeof(DNP3LinkHeader)) {
1071 DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1073 if (!DNP3CheckStartBytes(header)) {
1077 if (!DNP3CheckLinkHeaderCRC(header)) {
1082 uint32_t frame_len = DNP3CalculateLinkLength(header->len);
1083 if (frame_len == 0) {
1087 if (input_len < frame_len) {
1093 if (!DNP3IsUserData(header)) {
1099 if (!DNP3HasUserData(header, STREAM_TOSERVER)) {
1104 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
1105 frame_len -
sizeof(DNP3LinkHeader))) {
1110 DNP3HandleUserDataRequest(dnp3, input, frame_len);
1115 input_len -= frame_len;
1116 processed += frame_len;
1135 StreamSlice stream_slice,
void *local_data)
1142 const uint8_t *input = StreamSliceGetData(&stream_slice);
1143 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1145 if (input_len == 0) {
1150 if (!DNP3BufferAdd(buffer, input, input_len)) {
1152 "DNP3 request data");
1155 processed = DNP3HandleRequestLinkLayer(dnp3,
1158 if (processed < 0) {
1161 buffer->
offset += processed;
1162 DNP3BufferTrim(buffer);
1165 processed = DNP3HandleRequestLinkLayer(dnp3, input, input_len);
1166 if (processed < 0) {
1167 SCLogDebug(
"Failed to process request link layer.");
1172 input_len -= processed;
1176 if (!DNP3BufferAdd(buffer, input, input_len)) {
1178 "Failed to allocate memory to buffer DNP3 request data");
1188 DNP3BufferReset(buffer);
1198 static int DNP3HandleResponseLinkLayer(
DNP3State *dnp3,
const uint8_t *input,
1202 uint32_t processed = 0;
1207 if (input_len <
sizeof(DNP3LinkHeader)) {
1211 DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1213 if (!DNP3CheckStartBytes(header)) {
1217 if (!DNP3CheckLinkHeaderCRC(header)) {
1223 uint32_t frame_len = DNP3CalculateLinkLength(header->len);
1224 if (frame_len == 0) {
1228 if (input_len < frame_len) {
1234 if (!DNP3IsUserData(header)) {
1240 if (!DNP3HasUserData(header, STREAM_TOCLIENT)) {
1245 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
1246 frame_len -
sizeof(DNP3LinkHeader))) {
1251 DNP3HandleUserDataResponse(dnp3, input, frame_len);
1256 input_len -= frame_len;
1257 processed += frame_len;
1277 StreamSlice stream_slice,
void *local_data)
1285 const uint8_t *input = StreamSliceGetData(&stream_slice);
1286 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1289 if (!DNP3BufferAdd(buffer, input, input_len)) {
1291 "DNP3 response data");
1294 processed = DNP3HandleResponseLinkLayer(dnp3,
1297 if (processed < 0) {
1300 buffer->
offset += processed;
1301 DNP3BufferTrim(buffer);
1306 if (DNP3ContainsBanner(input, input_len)) {
1310 processed = DNP3HandleResponseLinkLayer(dnp3, input, input_len);
1311 if (processed < 0) {
1315 input_len -= processed;
1319 if (!DNP3BufferAdd(buffer, input, input_len)) {
1321 "Failed to allocate memory to buffer DNP3 response data");
1333 DNP3BufferReset(buffer);
1337 static void *DNP3GetTx(
void *alstate, uint64_t tx_id)
1342 uint64_t tx_num = tx_id + 1;
1349 if (tx_num != tx->
tx_num) {
1358 static uint64_t DNP3GetTxCnt(
void *state)
1361 uint64_t count = ((uint64_t)((
DNP3State *)state)->transaction_max);
1368 static void DNP3TxFreeObjectList(DNP3ObjectList *objects)
1374 DNP3ObjectFree(
object);
1395 if (tx->
tx_data.de_state != NULL) {
1412 static void DNP3StateTxFree(
void *state, uint64_t tx_id)
1417 uint64_t tx_num = tx_id + 1;
1421 if (tx->
tx_num != tx_num) {
1425 if (tx == dnp3->
curr) {
1429 if (tx->
tx_data.events != NULL) {
1454 static void DNP3StateFree(
void *state)
1459 if (state != NULL) {
1460 while ((tx =
TAILQ_FIRST(&dnp3->tx_list)) != NULL) {
1478 static int DNP3GetAlstateProgress(
void *tx, uint8_t direction)
1487 SCLogDebug(
"flooded: returning tx as done.");
1494 else if (direction & STREAM_TOSERVER && dnp3tx->
request_done) {
1504 static int DNP3StateGetEventInfo(
const char *event_name,
int *event_id,
1508 if (*event_id == -1) {
1510 "the DNP3 enum event map table.", event_name);
1522 static int DNP3StateGetEventInfoById(
int event_id,
const char **event_name,
1526 if (*event_name == NULL) {
1528 "the DNP3 enum event map table.", event_id);
1537 static AppLayerTxData *DNP3GetTxData(
void *vtx)
1550 switch (prefix_code) {
1568 const char *proto_name =
"dnp3";
1575 ALPROTO_DNP3, 0,
sizeof(DNP3LinkHeader), STREAM_TOSERVER,
1576 DNP3ProbingParser, DNP3ProbingParser);
1581 DNP3ProbingParser, DNP3ProbingParser)) {
1587 SCLogConfig(
"Protocol detection and parser disabled for DNP3.");
1601 DNP3StateAlloc, DNP3StateFree);
1609 DNP3GetAlstateProgress);
1613 DNP3StateGetEventInfo);
1615 DNP3StateGetEventInfoById);
1622 "Protocol detection still on.", proto_name);
1641 static void DNP3FixCrc(uint8_t *data, uint32_t
len)
1643 uint32_t block_size;
1651 uint16_t
crc = DNP3ComputeCRC(data, block_size);
1652 data[block_size + 1] = (
crc >> 8) & 0xff;
1653 data[block_size] =
crc & 0xff;
1662 static int DNP3ParserTestCheckCRC(
void)
1664 uint8_t request[] = {
1666 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1673 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1674 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1678 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1682 FAIL_IF(!DNP3CheckCRC(request,
sizeof(DNP3LinkHeader)));
1685 FAIL_IF(!DNP3CheckCRC(request +
sizeof(DNP3LinkHeader),
1688 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1691 FAIL_IF(DNP3CheckCRC(request,
sizeof(DNP3LinkHeader)));
1695 request[
sizeof(DNP3LinkHeader) + 3]++;
1696 FAIL_IF(DNP3CheckCRC(request +
sizeof(DNP3LinkHeader),
1706 static int DNP3CheckUserDataCRCsTest(
void)
1709 uint8_t data_valid[] = {
1710 0xff, 0xc9, 0x05, 0x0c,
1711 0x01, 0x28, 0x01, 0x00,
1712 0x00, 0x00, 0x01, 0x01,
1713 0x01, 0x00, 0x00, 0x00,
1716 0xff, 0xc9, 0x05, 0x0c,
1717 0x01, 0x28, 0x01, 0x00,
1718 0x00, 0x00, 0x01, 0x01,
1719 0x01, 0x00, 0x00, 0x00,
1722 0xff, 0xc9, 0x05, 0x0c,
1723 0x01, 0x28, 0x01, 0x00,
1724 0x00, 0x00, 0x01, 0x01,
1725 0x01, 0x00, 0x00, 0x00,
1728 0x00, 0x00, 0x00, 0x00,
1732 FAIL_IF(!DNP3CheckUserDataCRCs(data_valid,
sizeof(data_valid)));
1734 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1736 uint8_t data_invalid[] = {
1737 0xff, 0xc9, 0x05, 0x0c,
1738 0x01, 0x28, 0x01, 0x00,
1739 0x00, 0x00, 0x01, 0x01,
1740 0x01, 0x00, 0x00, 0x00,
1743 0xff, 0xc9, 0x05, 0x0c,
1744 0x01, 0x28, 0x01, 0x00,
1745 0x00, 0x00, 0x01, 0x01,
1746 0x01, 0x00, 0x00, 0x00,
1749 0xff, 0xc9, 0x05, 0x0c,
1750 0x01, 0x28, 0x01, 0x00,
1751 0x00, 0x00, 0x01, 0x01,
1752 0x01, 0x00, 0x00, 0x00,
1755 0x00, 0x00, 0x00, 0x00,
1759 FAIL_IF(DNP3CheckUserDataCRCs(data_invalid,
sizeof(data_invalid)));
1762 uint8_t one_byte_nocrc[] = { 0x01 };
1763 FAIL_IF(DNP3CheckUserDataCRCs(one_byte_nocrc,
sizeof(one_byte_nocrc)));
1766 uint8_t two_byte_nocrc[] = { 0x01, 0x02 };
1767 FAIL_IF(DNP3CheckUserDataCRCs(two_byte_nocrc,
sizeof(two_byte_nocrc)));
1771 uint8_t three_bytes_good_crc[] = { 0x00, 0x00, 0x00 };
1772 *(uint16_t *)(three_bytes_good_crc + 1) = DNP3ComputeCRC(
1773 three_bytes_good_crc, 1);
1774 FAIL_IF(!DNP3CheckUserDataCRCs(three_bytes_good_crc,
1775 sizeof(three_bytes_good_crc)));
1787 static int DNP3CalculateLinkLengthTest(
void)
1790 FAIL_IF(DNP3CalculateLinkLength(0) != 0);
1791 FAIL_IF(DNP3CalculateLinkLength(1) != 0);
1792 FAIL_IF(DNP3CalculateLinkLength(2) != 0);
1793 FAIL_IF(DNP3CalculateLinkLength(3) != 0);
1794 FAIL_IF(DNP3CalculateLinkLength(4) != 0);
1797 FAIL_IF(DNP3CalculateLinkLength(5) != 10);
1800 FAIL_IF(DNP3CalculateLinkLength(21) != 28);
1803 FAIL_IF(DNP3CalculateLinkLength(37) != 46);
1807 FAIL_IF(DNP3CalculateLinkLength(38) != 49);
1810 FAIL_IF(DNP3CalculateLinkLength(255) != 292);
1819 static int DNP3CalculateTransportLengthWithoutCRCsTest(
void)
1821 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(0) != -1);
1822 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(1) != -1);
1823 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(2) != 0);
1824 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(3) != 1);
1825 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(16) != 14);
1826 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(17) != 15);
1827 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(18) != 16);
1830 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(19) != -1);
1834 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(20) != 16);
1836 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(21) != 17);
1844 static int DNP3ParserCheckLinkHeaderCRC(
void)
1847 uint8_t request[] = {
1849 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1856 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1857 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1858 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1861 DNP3LinkHeader *header = (DNP3LinkHeader *)request;
1862 FAIL_IF(!DNP3CheckLinkHeaderCRC(header));
1864 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1867 FAIL_IF(DNP3CheckLinkHeaderCRC(header));
1876 static int DNP3ReassembleApplicationLayerTest01(
void)
1878 uint32_t reassembled_len = 0;
1879 uint8_t *output = NULL;
1881 uint8_t payload[] = {
1883 0xff, 0xc9, 0x05, 0x0c,
1884 0x01, 0x28, 0x01, 0x00,
1885 0x00, 0x00, 0x01, 0x01,
1886 0x01, 0x00, 0x00, 0x00,
1889 0xff, 0xc9, 0x05, 0x0c,
1890 0x01, 0x28, 0x01, 0x00,
1891 0x00, 0x00, 0x01, 0x01,
1892 0x01, 0x00, 0x00, 0x00,
1895 0xff, 0xc9, 0x05, 0x0c,
1896 0x01, 0x28, 0x01, 0x00,
1897 0x00, 0x00, 0x01, 0x01,
1898 0x01, 0x00, 0x00, 0x00,
1901 0x00, 0x00, 0x00, 0x00,
1906 uint8_t expected[] = {
1908 0x01, 0x28, 0x01, 0x00,
1909 0x00, 0x00, 0x01, 0x01,
1910 0x01, 0x00, 0x00, 0x00,
1912 0xff, 0xc9, 0x05, 0x0c,
1913 0x01, 0x28, 0x01, 0x00,
1914 0x00, 0x00, 0x01, 0x01,
1915 0x01, 0x00, 0x00, 0x00,
1917 0xff, 0xc9, 0x05, 0x0c,
1918 0x01, 0x28, 0x01, 0x00,
1919 0x00, 0x00, 0x01, 0x01,
1920 0x01, 0x00, 0x00, 0x00,
1922 0x00, 0x00, 0x00, 0x00,
1928 FAIL_IF(!DNP3ReassembleApplicationLayer(payload,
1929 sizeof(payload), &output, &reassembled_len));
1931 FAIL_IF(reassembled_len !=
sizeof(expected));
1932 FAIL_IF(memcmp(expected, output, reassembled_len));
1936 reassembled_len = 0;
1938 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 1, &output,
1941 FAIL_IF(reassembled_len != 0);
1944 reassembled_len = 0;
1946 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 2, &output,
1949 FAIL_IF(reassembled_len != 0);
1953 reassembled_len = 0;
1955 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 3, &output,
1958 FAIL_IF(reassembled_len != 0);
1961 reassembled_len = 0;
1963 FAIL_IF(!DNP3ReassembleApplicationLayer(payload, 4, &output,
1966 FAIL_IF(reassembled_len != 1);
1969 uint8_t short_payload1[] = {
1971 0xff, 0xc9, 0x05, 0x0c,
1972 0x01, 0x28, 0x01, 0x00,
1973 0x00, 0x00, 0x01, 0x01,
1974 0x01, 0x00, 0x00, 0x00,
1977 0xff, 0xc9, 0x05, 0x0c,
1978 0x01, 0x28, 0x01, 0x00,
1979 0x00, 0x00, 0x01, 0x01,
1980 0x01, 0x00, 0x00, 0x00,
1983 0xff, 0xc9, 0x05, 0x0c,
1984 0x01, 0x28, 0x01, 0x00,
1985 0x00, 0x00, 0x01, 0x01,
1986 0x01, 0x00, 0x00, 0x00,
1991 reassembled_len = 0;
1992 FAIL_IF(DNP3ReassembleApplicationLayer(short_payload1,
1993 sizeof(short_payload1), &output, &reassembled_len));
1996 uint8_t short_payload2[] = {
1998 0xff, 0xc9, 0x05, 0x0c,
1999 0x01, 0x28, 0x01, 0x00,
2000 0x00, 0x00, 0x01, 0x01,
2001 0x01, 0x00, 0x00, 0x00,
2004 0xff, 0xc9, 0x05, 0x0c,
2005 0x01, 0x28, 0x01, 0x00,
2006 0x00, 0x00, 0x01, 0x01,
2007 0x01, 0x00, 0x00, 0x00,
2010 0xff, 0xc9, 0x05, 0x0c,
2011 0x01, 0x28, 0x01, 0x00,
2012 0x00, 0x00, 0x01, 0x01,
2013 0x01, 0x00, 0x00, 0x00,
2018 reassembled_len = 0;
2019 FAIL_IF(DNP3ReassembleApplicationLayer(short_payload2,
2020 sizeof(short_payload2), &output, &reassembled_len));
2028 static int DNP3ProbingParserTest(
void)
2031 0x05, 0x64, 0x05, 0xc9, 0x03, 0x00, 0x04, 0x00,
2037 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt,
sizeof(pkt), &rdir) !=
ALPROTO_DNP3);
2040 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt,
sizeof(DNP3LinkHeader) - 1, &rdir) !=
ALPROTO_UNKNOWN);
2054 char mybanner[] =
"Welcome to DNP3 SCADA.";
2055 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, (uint8_t *)mybanner,
sizeof(mybanner) - 1,
2057 FAIL_IF(rdir != STREAM_TOCLIENT);
2065 static int DNP3ParserTestRequestResponse(
void)
2069 uint8_t request[] = {
2071 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2078 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2079 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2080 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2083 uint8_t response[] = {
2085 0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2092 0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2093 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2094 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2102 memset(&flow, 0,
sizeof(flow));
2103 memset(&ssn, 0,
sizeof(ssn));
2106 flow.
proto = IPPROTO_TCP;
2113 STREAM_TOSERVER, request,
sizeof(request)));
2129 STREAM_TOCLIENT, response,
sizeof(response)));
2131 FAIL_IF(DNP3GetTx(state, 0) != tx);
2146 static int DNP3ParserTestUnsolicitedResponseConfirm(
void)
2151 uint8_t response[] = {
2152 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2153 0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2154 0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2155 0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9
2159 uint8_t confirm[] = {
2160 0x05, 0x64, 0x08, 0xc4, 0x02, 0x00,
2161 0x01, 0x00, 0xd3, 0xb7, 0xc0, 0xda, 0x00, 0x6a,
2169 memset(&flow, 0,
sizeof(flow));
2170 memset(&ssn, 0,
sizeof(ssn));
2173 flow.
proto = IPPROTO_TCP;
2180 STREAM_TOCLIENT, response,
sizeof(response)));
2197 STREAM_TOSERVER, confirm,
sizeof(confirm)));
2199 FAIL_IF(DNP3GetTx(state, 0) != tx);
2213 static int DNP3ParserTestFlooded(
void)
2217 uint8_t request[] = {
2219 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2226 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2227 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2228 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2235 memset(&flow, 0,
sizeof(flow));
2236 memset(&ssn, 0,
sizeof(ssn));
2239 flow.
proto = IPPROTO_TCP;
2246 STREAM_TOSERVER, request,
sizeof(request)));
2264 STREAM_TOSERVER, request,
sizeof(request)));
2268 FAIL_IF(DNP3GetAlstateProgress(tx, 0));
2273 STREAM_TOSERVER, request,
sizeof(request)));
2278 FAIL_IF(!DNP3GetAlstateProgress(tx, 0));
2296 static int DNP3ParserTestPartialFrame(
void)
2302 uint8_t request_partial1[] = {
2304 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2311 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2314 uint8_t request_partial2[] = {
2316 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2317 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2320 uint8_t response_partial1[] = {
2322 0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2329 0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2332 uint8_t response_partial2[] = {
2333 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2334 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2342 memset(&flow, 0,
sizeof(flow));
2343 memset(&ssn, 0,
sizeof(ssn));
2345 flow.
proto = IPPROTO_TCP;
2353 STREAM_TOSERVER, request_partial1,
sizeof(request_partial1));
2363 sizeof(request_partial1)));
2367 FAIL_IF(DNP3GetTx(state, 0) != NULL);
2372 STREAM_TOSERVER, request_partial2,
sizeof(request_partial2));
2382 tx = DNP3GetTx(state, 0);
2393 STREAM_TOCLIENT, response_partial1,
sizeof(response_partial1));
2403 STREAM_TOCLIENT, response_partial2,
sizeof(response_partial2));
2425 static int DNP3ParserTestMultiFrame(
void)
2430 uint8_t unsol_response1[] = {
2431 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2432 0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2433 0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2434 0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9,
2438 uint8_t unsol_response2[] = {
2439 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2440 0x89, 0xe5, 0xc5, 0xfb, 0x82, 0x00, 0x00, 0x02,
2441 0x02, 0x17, 0x01, 0x0c, 0x01, 0xd8, 0x75, 0xd8,
2442 0x32, 0x4c, 0xc9, 0x3c, 0x01, 0xa1, 0xc9,
2445 uint8_t combined[
sizeof(unsol_response1) +
sizeof(unsol_response2)];
2446 memcpy(combined, unsol_response1,
sizeof(unsol_response1));
2447 memcpy(combined +
sizeof(unsol_response1), unsol_response2,
2448 sizeof(unsol_response2));
2455 memset(&flow, 0,
sizeof(flow));
2456 memset(&ssn, 0,
sizeof(ssn));
2458 flow.
proto = IPPROTO_TCP;
2464 STREAM_TOCLIENT, combined,
sizeof(combined));
2486 static int DNP3ParserTestParsePDU01(
void)
2490 const uint8_t pkt[] = {
2492 0x0b, 0xc4, 0x17, 0x00, 0xef, 0xff, 0xc4, 0x8f,
2493 0xe1, 0xc8, 0x01, 0x01, 0x00, 0x06, 0x77, 0x6e
2497 int pdus = DNP3HandleRequestLinkLayer(dnp3state, pkt,
sizeof(pkt));
2507 DNP3StateFree(dnp3state);
2514 static int DNP3ParserDecodeG70V3Test(
void)
2516 const uint8_t pkt[] = {
2518 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00, 0xc7, 0xee,
2519 0xc7, 0xc9, 0x1b, 0x46, 0x03, 0x5b, 0x01, 0x55,
2520 0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2521 0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2522 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2523 0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2524 0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2525 0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2526 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2527 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2528 0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2529 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2530 0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2531 0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2537 int bytes = DNP3HandleRequestLinkLayer(dnp3state, pkt,
sizeof(pkt));
2538 FAIL_IF(bytes !=
sizeof(pkt));
2557 "C:/temp/DNPDeviceConfiguration written to Remote Device.xml") == 0);
2558 DNP3StateFree(dnp3state);
2565 static int DNP3ParserUnknownEventAlertTest(
void)
2569 0x05, 0x64, 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00,
2579 0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2580 0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2582 0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2583 0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2584 0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2585 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2586 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2587 0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2588 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2589 0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2590 0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2594 DNP3FixCrc(pkt + 10,
sizeof(pkt) - 10);
2598 int bytes = DNP3HandleRequestLinkLayer(dnp3state, pkt,
sizeof(pkt));
2599 FAIL_IF(bytes !=
sizeof(pkt));
2601 DNP3StateFree(dnp3state);
2608 static int DNP3ParserIncorrectUserData(
void)
2610 uint8_t packet_bytes[] = {
2611 0x05, 0x64, 0x08, 0xc4, 0x03, 0x00, 0x04, 0x00,
2612 0xbf, 0xe9, 0xc1, 0xc1, 0x82, 0xc5, 0xee
2618 memset(&flow, 0,
sizeof(flow));
2619 memset(&ssn, 0,
sizeof(ssn));
2621 flow.
proto = IPPROTO_TCP;
2626 STREAM_TOCLIENT, packet_bytes,
sizeof(packet_bytes));
2641 UtRegisterTest(
"DNP3ParserTestCheckCRC", DNP3ParserTestCheckCRC);
2643 DNP3ParserCheckLinkHeaderCRC);
2644 UtRegisterTest(
"DNP3CheckUserDataCRCsTest", DNP3CheckUserDataCRCsTest);
2645 UtRegisterTest(
"DNP3CalculateLinkLengthTest", DNP3CalculateLinkLengthTest);
2647 DNP3CalculateTransportLengthWithoutCRCsTest);
2649 DNP3ReassembleApplicationLayerTest01);
2652 DNP3ParserTestRequestResponse);
2654 DNP3ParserTestUnsolicitedResponseConfirm);
2655 UtRegisterTest(
"DNP3ParserTestPartialFrame", DNP3ParserTestPartialFrame);
2656 UtRegisterTest(
"DNP3ParserTestMultiFrame", DNP3ParserTestMultiFrame);
2658 UtRegisterTest(
"DNP3ParserTestParsePDU01", DNP3ParserTestParsePDU01);
2659 UtRegisterTest(
"DNP3ParserDecodeG70V3Test", DNP3ParserDecodeG70V3Test);
2661 DNP3ParserUnknownEventAlertTest);
2662 UtRegisterTest(
"DNP3ParserIncorrectUserData", DNP3ParserIncorrectUserData);