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) {
474 SCLogWarning(
"Failed to set event, state or tx pointer was NULL.");
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->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 &&
965 ah = (DNP3ApplicationHeader *)(input +
offset);
966 offset +=
sizeof(DNP3ApplicationHeader);
967 iin = (DNP3InternalInd *)(input +
offset);
969 tx = DNP3TxAlloc(dnp3,
false);
981 if (!DNP3ReassembleApplicationLayer(input +
sizeof(DNP3LinkHeader),
993 offset =
sizeof(DNP3ApplicationHeader) +
sizeof(DNP3InternalInd);
994 if (DNP3DecodeApplicationObjects(
1006 static int DNP3HandleRequestLinkLayer(
DNP3State *dnp3,
const uint8_t *input,
1010 uint32_t processed = 0;
1015 if (input_len <
sizeof(DNP3LinkHeader)) {
1019 DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1021 if (!DNP3CheckStartBytes(header)) {
1025 if (!DNP3CheckLinkHeaderCRC(header)) {
1030 uint32_t frame_len = DNP3CalculateLinkLength(header->len);
1031 if (frame_len == 0) {
1035 if (input_len < frame_len) {
1041 if (!DNP3IsUserData(header)) {
1047 if (!DNP3HasUserData(header, STREAM_TOSERVER)) {
1052 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
1053 frame_len -
sizeof(DNP3LinkHeader))) {
1058 DNP3HandleUserDataRequest(dnp3, input, frame_len);
1063 input_len -= frame_len;
1064 processed += frame_len;
1083 StreamSlice stream_slice,
void *local_data)
1090 const uint8_t *input = StreamSliceGetData(&stream_slice);
1091 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1093 if (input_len == 0) {
1098 if (!DNP3BufferAdd(buffer, input, input_len)) {
1101 processed = DNP3HandleRequestLinkLayer(dnp3,
1104 if (processed < 0) {
1107 buffer->
offset += processed;
1108 DNP3BufferTrim(buffer);
1111 processed = DNP3HandleRequestLinkLayer(dnp3, input, input_len);
1112 if (processed < 0) {
1113 SCLogDebug(
"Failed to process request link layer.");
1118 input_len -= processed;
1122 if (!DNP3BufferAdd(buffer, input, input_len)) {
1132 DNP3BufferReset(buffer);
1142 static int DNP3HandleResponseLinkLayer(
DNP3State *dnp3,
const uint8_t *input,
1146 uint32_t processed = 0;
1151 if (input_len <
sizeof(DNP3LinkHeader)) {
1155 DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1157 if (!DNP3CheckStartBytes(header)) {
1161 if (!DNP3CheckLinkHeaderCRC(header)) {
1167 uint32_t frame_len = DNP3CalculateLinkLength(header->len);
1168 if (frame_len == 0) {
1172 if (input_len < frame_len) {
1178 if (!DNP3IsUserData(header)) {
1184 if (!DNP3HasUserData(header, STREAM_TOCLIENT)) {
1189 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
1190 frame_len -
sizeof(DNP3LinkHeader))) {
1195 DNP3HandleUserDataResponse(dnp3, input, frame_len);
1200 input_len -= frame_len;
1201 processed += frame_len;
1221 StreamSlice stream_slice,
void *local_data)
1229 const uint8_t *input = StreamSliceGetData(&stream_slice);
1230 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1233 if (!DNP3BufferAdd(buffer, input, input_len)) {
1236 processed = DNP3HandleResponseLinkLayer(dnp3,
1239 if (processed < 0) {
1242 buffer->
offset += processed;
1243 DNP3BufferTrim(buffer);
1248 if (DNP3ContainsBanner(input, input_len)) {
1252 processed = DNP3HandleResponseLinkLayer(dnp3, input, input_len);
1253 if (processed < 0) {
1257 input_len -= processed;
1261 if (!DNP3BufferAdd(buffer, input, input_len)) {
1273 DNP3BufferReset(buffer);
1277 static void *DNP3GetTx(
void *alstate, uint64_t tx_id)
1282 uint64_t tx_num = tx_id + 1;
1289 if (tx_num != tx->
tx_num) {
1298 static uint64_t DNP3GetTxCnt(
void *state)
1301 uint64_t count = ((uint64_t)((
DNP3State *)state)->transaction_max);
1308 static void DNP3TxFreeObjectList(DNP3ObjectList *objects)
1314 DNP3ObjectFree(
object);
1325 if (tx->
buffer != NULL) {
1331 if (tx->
tx_data.de_state != NULL) {
1335 DNP3TxFreeObjectList(&tx->
objects);
1347 static void DNP3StateTxFree(
void *state, uint64_t tx_id)
1352 uint64_t tx_num = tx_id + 1;
1356 if (tx->
tx_num != tx_num) {
1360 if (tx == dnp3->
curr) {
1364 if (tx->
tx_data.events != NULL) {
1389 static void DNP3StateFree(
void *state)
1394 if (state != NULL) {
1395 while ((tx =
TAILQ_FIRST(&dnp3->tx_list)) != NULL) {
1413 static int DNP3GetAlstateProgress(
void *tx, uint8_t direction)
1422 SCLogDebug(
"flooded: returning tx as done.");
1442 if (direction & STREAM_TOSERVER) {
1446 }
else if (direction & STREAM_TOCLIENT) {
1458 static int DNP3StateGetEventInfo(
const char *event_name,
int *event_id,
1462 if (*event_id == -1) {
1464 "the DNP3 enum event map table.",
1477 static int DNP3StateGetEventInfoById(
int event_id,
const char **event_name,
1481 if (*event_name == NULL) {
1483 "the DNP3 enum event map table.",
1499 static AppLayerStateData *DNP3GetStateData(
void *vstate)
1512 switch (prefix_code) {
1530 const char *proto_name =
"dnp3";
1537 ALPROTO_DNP3, 0,
sizeof(DNP3LinkHeader), STREAM_TOSERVER,
1538 DNP3ProbingParser, DNP3ProbingParser);
1543 DNP3ProbingParser, DNP3ProbingParser)) {
1549 SCLogConfig(
"Protocol detection and parser disabled for DNP3.");
1563 DNP3StateAlloc, DNP3StateFree);
1571 DNP3GetAlstateProgress);
1575 DNP3StateGetEventInfo);
1577 DNP3StateGetEventInfoById);
1591 "Protocol detection still on.", proto_name);
1610 static void DNP3FixCrc(uint8_t *data, uint32_t
len)
1612 uint32_t block_size;
1620 uint16_t
crc = DNP3ComputeCRC(data, block_size);
1621 data[block_size + 1] = (
crc >> 8) & 0xff;
1622 data[block_size] =
crc & 0xff;
1631 static int DNP3ParserTestCheckCRC(
void)
1633 uint8_t request[] = {
1635 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1642 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1643 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1647 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1651 FAIL_IF(!DNP3CheckCRC(request,
sizeof(DNP3LinkHeader)));
1654 FAIL_IF(!DNP3CheckCRC(request +
sizeof(DNP3LinkHeader),
1657 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1660 FAIL_IF(DNP3CheckCRC(request,
sizeof(DNP3LinkHeader)));
1664 request[
sizeof(DNP3LinkHeader) + 3]++;
1665 FAIL_IF(DNP3CheckCRC(request +
sizeof(DNP3LinkHeader),
1675 static int DNP3CheckUserDataCRCsTest(
void)
1678 uint8_t data_valid[] = {
1679 0xff, 0xc9, 0x05, 0x0c,
1680 0x01, 0x28, 0x01, 0x00,
1681 0x00, 0x00, 0x01, 0x01,
1682 0x01, 0x00, 0x00, 0x00,
1685 0xff, 0xc9, 0x05, 0x0c,
1686 0x01, 0x28, 0x01, 0x00,
1687 0x00, 0x00, 0x01, 0x01,
1688 0x01, 0x00, 0x00, 0x00,
1691 0xff, 0xc9, 0x05, 0x0c,
1692 0x01, 0x28, 0x01, 0x00,
1693 0x00, 0x00, 0x01, 0x01,
1694 0x01, 0x00, 0x00, 0x00,
1697 0x00, 0x00, 0x00, 0x00,
1701 FAIL_IF(!DNP3CheckUserDataCRCs(data_valid,
sizeof(data_valid)));
1703 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1705 uint8_t data_invalid[] = {
1706 0xff, 0xc9, 0x05, 0x0c,
1707 0x01, 0x28, 0x01, 0x00,
1708 0x00, 0x00, 0x01, 0x01,
1709 0x01, 0x00, 0x00, 0x00,
1712 0xff, 0xc9, 0x05, 0x0c,
1713 0x01, 0x28, 0x01, 0x00,
1714 0x00, 0x00, 0x01, 0x01,
1715 0x01, 0x00, 0x00, 0x00,
1718 0xff, 0xc9, 0x05, 0x0c,
1719 0x01, 0x28, 0x01, 0x00,
1720 0x00, 0x00, 0x01, 0x01,
1721 0x01, 0x00, 0x00, 0x00,
1724 0x00, 0x00, 0x00, 0x00,
1728 FAIL_IF(DNP3CheckUserDataCRCs(data_invalid,
sizeof(data_invalid)));
1731 uint8_t one_byte_nocrc[] = { 0x01 };
1732 FAIL_IF(DNP3CheckUserDataCRCs(one_byte_nocrc,
sizeof(one_byte_nocrc)));
1735 uint8_t two_byte_nocrc[] = { 0x01, 0x02 };
1736 FAIL_IF(DNP3CheckUserDataCRCs(two_byte_nocrc,
sizeof(two_byte_nocrc)));
1740 uint8_t three_bytes_good_crc[] = { 0x00, 0x00, 0x00 };
1741 *(uint16_t *)(three_bytes_good_crc + 1) = DNP3ComputeCRC(
1742 three_bytes_good_crc, 1);
1743 FAIL_IF(!DNP3CheckUserDataCRCs(three_bytes_good_crc,
1744 sizeof(three_bytes_good_crc)));
1756 static int DNP3CalculateLinkLengthTest(
void)
1759 FAIL_IF(DNP3CalculateLinkLength(0) != 0);
1760 FAIL_IF(DNP3CalculateLinkLength(1) != 0);
1761 FAIL_IF(DNP3CalculateLinkLength(2) != 0);
1762 FAIL_IF(DNP3CalculateLinkLength(3) != 0);
1763 FAIL_IF(DNP3CalculateLinkLength(4) != 0);
1766 FAIL_IF(DNP3CalculateLinkLength(5) != 10);
1769 FAIL_IF(DNP3CalculateLinkLength(21) != 28);
1772 FAIL_IF(DNP3CalculateLinkLength(37) != 46);
1776 FAIL_IF(DNP3CalculateLinkLength(38) != 49);
1779 FAIL_IF(DNP3CalculateLinkLength(255) != 292);
1788 static int DNP3CalculateTransportLengthWithoutCRCsTest(
void)
1790 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(0) != -1);
1791 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(1) != -1);
1792 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(2) != 0);
1793 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(3) != 1);
1794 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(16) != 14);
1795 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(17) != 15);
1796 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(18) != 16);
1799 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(19) != -1);
1803 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(20) != 16);
1805 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(21) != 17);
1813 static int DNP3ParserCheckLinkHeaderCRC(
void)
1816 uint8_t request[] = {
1818 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1825 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1826 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1827 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1830 DNP3LinkHeader *header = (DNP3LinkHeader *)request;
1831 FAIL_IF(!DNP3CheckLinkHeaderCRC(header));
1833 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1836 FAIL_IF(DNP3CheckLinkHeaderCRC(header));
1845 static int DNP3ReassembleApplicationLayerTest01(
void)
1847 uint32_t reassembled_len = 0;
1848 uint8_t *output = NULL;
1850 uint8_t payload[] = {
1852 0xff, 0xc9, 0x05, 0x0c,
1853 0x01, 0x28, 0x01, 0x00,
1854 0x00, 0x00, 0x01, 0x01,
1855 0x01, 0x00, 0x00, 0x00,
1858 0xff, 0xc9, 0x05, 0x0c,
1859 0x01, 0x28, 0x01, 0x00,
1860 0x00, 0x00, 0x01, 0x01,
1861 0x01, 0x00, 0x00, 0x00,
1864 0xff, 0xc9, 0x05, 0x0c,
1865 0x01, 0x28, 0x01, 0x00,
1866 0x00, 0x00, 0x01, 0x01,
1867 0x01, 0x00, 0x00, 0x00,
1870 0x00, 0x00, 0x00, 0x00,
1875 uint8_t expected[] = {
1877 0x01, 0x28, 0x01, 0x00,
1878 0x00, 0x00, 0x01, 0x01,
1879 0x01, 0x00, 0x00, 0x00,
1881 0xff, 0xc9, 0x05, 0x0c,
1882 0x01, 0x28, 0x01, 0x00,
1883 0x00, 0x00, 0x01, 0x01,
1884 0x01, 0x00, 0x00, 0x00,
1886 0xff, 0xc9, 0x05, 0x0c,
1887 0x01, 0x28, 0x01, 0x00,
1888 0x00, 0x00, 0x01, 0x01,
1889 0x01, 0x00, 0x00, 0x00,
1891 0x00, 0x00, 0x00, 0x00,
1897 FAIL_IF(!DNP3ReassembleApplicationLayer(payload,
1898 sizeof(payload), &output, &reassembled_len));
1900 FAIL_IF(reassembled_len !=
sizeof(expected));
1901 FAIL_IF(memcmp(expected, output, reassembled_len));
1905 reassembled_len = 0;
1907 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 1, &output,
1910 FAIL_IF(reassembled_len != 0);
1913 reassembled_len = 0;
1915 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 2, &output,
1918 FAIL_IF(reassembled_len != 0);
1922 reassembled_len = 0;
1924 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 3, &output,
1927 FAIL_IF(reassembled_len != 0);
1930 reassembled_len = 0;
1932 FAIL_IF(!DNP3ReassembleApplicationLayer(payload, 4, &output,
1935 FAIL_IF(reassembled_len != 1);
1938 uint8_t short_payload1[] = {
1940 0xff, 0xc9, 0x05, 0x0c,
1941 0x01, 0x28, 0x01, 0x00,
1942 0x00, 0x00, 0x01, 0x01,
1943 0x01, 0x00, 0x00, 0x00,
1946 0xff, 0xc9, 0x05, 0x0c,
1947 0x01, 0x28, 0x01, 0x00,
1948 0x00, 0x00, 0x01, 0x01,
1949 0x01, 0x00, 0x00, 0x00,
1952 0xff, 0xc9, 0x05, 0x0c,
1953 0x01, 0x28, 0x01, 0x00,
1954 0x00, 0x00, 0x01, 0x01,
1955 0x01, 0x00, 0x00, 0x00,
1960 reassembled_len = 0;
1961 FAIL_IF(DNP3ReassembleApplicationLayer(short_payload1,
1962 sizeof(short_payload1), &output, &reassembled_len));
1965 uint8_t short_payload2[] = {
1967 0xff, 0xc9, 0x05, 0x0c,
1968 0x01, 0x28, 0x01, 0x00,
1969 0x00, 0x00, 0x01, 0x01,
1970 0x01, 0x00, 0x00, 0x00,
1973 0xff, 0xc9, 0x05, 0x0c,
1974 0x01, 0x28, 0x01, 0x00,
1975 0x00, 0x00, 0x01, 0x01,
1976 0x01, 0x00, 0x00, 0x00,
1979 0xff, 0xc9, 0x05, 0x0c,
1980 0x01, 0x28, 0x01, 0x00,
1981 0x00, 0x00, 0x01, 0x01,
1982 0x01, 0x00, 0x00, 0x00,
1987 reassembled_len = 0;
1988 FAIL_IF(DNP3ReassembleApplicationLayer(short_payload2,
1989 sizeof(short_payload2), &output, &reassembled_len));
1997 static int DNP3ProbingParserTest(
void)
2000 0x05, 0x64, 0x05, 0xc9, 0x03, 0x00, 0x04, 0x00,
2006 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt,
sizeof(pkt), &rdir) !=
ALPROTO_DNP3);
2009 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt,
sizeof(DNP3LinkHeader) - 1, &rdir) !=
ALPROTO_UNKNOWN);
2023 char mybanner[] =
"Welcome to DNP3 SCADA.";
2024 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, (uint8_t *)mybanner,
sizeof(mybanner) - 1,
2026 FAIL_IF(rdir != STREAM_TOCLIENT);
2034 static int DNP3ParserTestRequestResponse(
void)
2038 uint8_t request[] = {
2040 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2047 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2048 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2049 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2052 uint8_t response[] = {
2054 0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2061 0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2062 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2063 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2071 memset(&flow, 0,
sizeof(flow));
2072 memset(&ssn, 0,
sizeof(ssn));
2075 flow.
proto = IPPROTO_TCP;
2082 STREAM_TOSERVER, request,
sizeof(request)));
2098 STREAM_TOCLIENT, response,
sizeof(response)));
2117 static int DNP3ParserTestUnsolicitedResponseConfirm(
void)
2122 uint8_t response[] = {
2123 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2124 0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2125 0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2126 0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9
2130 uint8_t confirm[] = {
2131 0x05, 0x64, 0x08, 0xc4, 0x02, 0x00,
2132 0x01, 0x00, 0xd3, 0xb7, 0xc0, 0xda, 0x00, 0x6a,
2140 memset(&flow, 0,
sizeof(flow));
2141 memset(&ssn, 0,
sizeof(ssn));
2144 flow.
proto = IPPROTO_TCP;
2151 STREAM_TOCLIENT, response,
sizeof(response)));
2166 STREAM_TOSERVER, confirm,
sizeof(confirm)));
2187 static int DNP3ParserTestFlooded(
void)
2191 uint8_t request[] = {
2193 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2200 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2201 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2202 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2209 memset(&flow, 0,
sizeof(flow));
2210 memset(&ssn, 0,
sizeof(ssn));
2213 flow.
proto = IPPROTO_TCP;
2220 STREAM_TOSERVER, request,
sizeof(request)));
2234 FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2239 STREAM_TOSERVER, request,
sizeof(request)));
2243 FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2248 STREAM_TOSERVER, request,
sizeof(request)));
2253 FAIL_IF(!DNP3GetAlstateProgress(tx, 0));
2268 static int DNP3ParserTestPartialFrame(
void)
2274 uint8_t request_partial1[] = {
2276 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2283 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2286 uint8_t request_partial2[] = {
2288 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2289 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2292 uint8_t response_partial1[] = {
2294 0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2301 0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2304 uint8_t response_partial2[] = {
2305 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2306 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2314 memset(&flow, 0,
sizeof(flow));
2315 memset(&ssn, 0,
sizeof(ssn));
2317 flow.
proto = IPPROTO_TCP;
2325 STREAM_TOSERVER, request_partial1,
sizeof(request_partial1));
2335 sizeof(request_partial1)));
2339 FAIL_IF(DNP3GetTx(state, 0) != NULL);
2344 STREAM_TOSERVER, request_partial2,
sizeof(request_partial2));
2354 tx = DNP3GetTx(state, 0);
2365 STREAM_TOCLIENT, response_partial1,
sizeof(response_partial1));
2370 tx = DNP3GetTx(state, 1);
2376 STREAM_TOCLIENT, response_partial2,
sizeof(response_partial2));
2385 tx = DNP3GetTx(state, 1);
2399 static int DNP3ParserTestMultiFrame(
void)
2404 uint8_t unsol_response1[] = {
2405 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2406 0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2407 0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2408 0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9,
2412 uint8_t unsol_response2[] = {
2413 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2414 0x89, 0xe5, 0xc5, 0xfb, 0x82, 0x00, 0x00, 0x02,
2415 0x02, 0x17, 0x01, 0x0c, 0x01, 0xd8, 0x75, 0xd8,
2416 0x32, 0x4c, 0xc9, 0x3c, 0x01, 0xa1, 0xc9,
2419 uint8_t combined[
sizeof(unsol_response1) +
sizeof(unsol_response2)];
2420 memcpy(combined, unsol_response1,
sizeof(unsol_response1));
2421 memcpy(combined +
sizeof(unsol_response1), unsol_response2,
2422 sizeof(unsol_response2));
2429 memset(&flow, 0,
sizeof(flow));
2430 memset(&ssn, 0,
sizeof(ssn));
2432 flow.
proto = IPPROTO_TCP;
2438 STREAM_TOCLIENT, combined,
sizeof(combined));
2460 static int DNP3ParserTestParsePDU01(
void)
2464 const uint8_t pkt[] = {
2466 0x0b, 0xc4, 0x17, 0x00, 0xef, 0xff, 0xc4, 0x8f,
2467 0xe1, 0xc8, 0x01, 0x01, 0x00, 0x06, 0x77, 0x6e
2471 int pdus = DNP3HandleRequestLinkLayer(dnp3state, pkt,
sizeof(pkt));
2481 DNP3StateFree(dnp3state);
2488 static int DNP3ParserDecodeG70V3Test(
void)
2490 const uint8_t pkt[] = {
2492 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00, 0xc7, 0xee,
2493 0xc7, 0xc9, 0x1b, 0x46, 0x03, 0x5b, 0x01, 0x55,
2494 0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2495 0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2496 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2497 0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2498 0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2499 0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2500 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2501 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2502 0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2503 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2504 0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2505 0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2511 int bytes = DNP3HandleRequestLinkLayer(dnp3state, pkt,
sizeof(pkt));
2512 FAIL_IF(bytes !=
sizeof(pkt));
2531 "C:/temp/DNPDeviceConfiguration written to Remote Device.xml") == 0);
2532 DNP3StateFree(dnp3state);
2539 static int DNP3ParserUnknownEventAlertTest(
void)
2543 0x05, 0x64, 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00,
2553 0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2554 0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2555 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2556 0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2557 0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2558 0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2559 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2560 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2561 0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2562 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2563 0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2564 0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2568 DNP3FixCrc(pkt + 10,
sizeof(pkt) - 10);
2572 int bytes = DNP3HandleRequestLinkLayer(dnp3state, pkt,
sizeof(pkt));
2573 FAIL_IF(bytes !=
sizeof(pkt));
2575 DNP3StateFree(dnp3state);
2582 static int DNP3ParserIncorrectUserData(
void)
2584 uint8_t packet_bytes[] = {
2585 0x05, 0x64, 0x08, 0xc4, 0x03, 0x00, 0x04, 0x00,
2586 0xbf, 0xe9, 0xc1, 0xc1, 0x82, 0xc5, 0xee
2592 memset(&flow, 0,
sizeof(flow));
2593 memset(&ssn, 0,
sizeof(ssn));
2595 flow.
proto = IPPROTO_TCP;
2600 STREAM_TOCLIENT, packet_bytes,
sizeof(packet_bytes));
2615 UtRegisterTest(
"DNP3ParserTestCheckCRC", DNP3ParserTestCheckCRC);
2617 DNP3ParserCheckLinkHeaderCRC);
2618 UtRegisterTest(
"DNP3CheckUserDataCRCsTest", DNP3CheckUserDataCRCsTest);
2619 UtRegisterTest(
"DNP3CalculateLinkLengthTest", DNP3CalculateLinkLengthTest);
2621 DNP3CalculateTransportLengthWithoutCRCsTest);
2623 DNP3ReassembleApplicationLayerTest01);
2626 DNP3ParserTestRequestResponse);
2628 DNP3ParserTestUnsolicitedResponseConfirm);
2629 UtRegisterTest(
"DNP3ParserTestPartialFrame", DNP3ParserTestPartialFrame);
2630 UtRegisterTest(
"DNP3ParserTestMultiFrame", DNP3ParserTestMultiFrame);
2632 UtRegisterTest(
"DNP3ParserTestParsePDU01", DNP3ParserTestParsePDU01);
2633 UtRegisterTest(
"DNP3ParserDecodeG70V3Test", DNP3ParserDecodeG70V3Test);
2635 DNP3ParserUnknownEventAlertTest);
2636 UtRegisterTest(
"DNP3ParserIncorrectUserData", DNP3ParserIncorrectUserData);