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.");
530 static uint32_t DNP3CalculateLinkLength(uint8_t length)
532 uint32_t frame_len = 0;
550 return frame_len +
sizeof(DNP3LinkHeader);
560 static int DNP3IsUserData(
const DNP3LinkHeader *header)
579 static int DNP3HasUserData(
const DNP3LinkHeader *header, uint8_t direction)
581 if (direction == STREAM_TOSERVER) {
583 sizeof(DNP3ApplicationHeader);
587 sizeof(DNP3ApplicationHeader) +
sizeof(DNP3InternalInd);
594 static void DNP3BufferReset(
DNP3Buffer *buffer)
609 static int DNP3BufferAdd(
DNP3Buffer *buffer,
const uint8_t *data, uint32_t
len)
611 if (buffer->
size == 0) {
640 static void DNP3BufferTrim(
DNP3Buffer *buffer)
643 DNP3BufferReset(buffer);
645 else if (buffer->
offset > 0) {
656 static void DNP3ObjectFree(
DNP3Object *
object)
658 if (object->
points != NULL) {
675 if (object->
points == NULL) {
676 DNP3ObjectFree(
object);
697 static int DNP3DecodeApplicationObjects(
DNP3Transaction *tx,
const uint8_t *buf,
698 uint32_t
len, DNP3ObjectList *objects)
702 if (buf == NULL ||
len == 0) {
709 if (
len <
sizeof(DNP3ObjHeader)) {
712 DNP3ObjHeader *header = (DNP3ObjHeader *)buf;
713 offset +=
sizeof(DNP3ObjHeader);
721 object->group = header->group;
722 object->variation = header->variation;
723 object->qualifier = header->qualifier;
733 if (
offset + (
sizeof(uint8_t) * 2) >
len) {
736 goto not_enough_data;
738 object->start = buf[
offset++];
739 object->stop = buf[
offset++];
740 object->count =
object->stop -
object->start + 1;
747 if (
offset + (
sizeof(uint16_t) * 2) >
len) {
750 goto not_enough_data;
753 offset +=
sizeof(uint16_t);
755 offset +=
sizeof(uint16_t);
756 object->count =
object->stop -
object->start + 1;
763 if (
offset + (
sizeof(uint32_t) * 2) >
len) {
766 goto not_enough_data;
769 offset +=
sizeof(uint32_t);
771 offset +=
sizeof(uint32_t);
772 object->count =
object->stop -
object->start + 1;
783 goto not_enough_data;
785 object->count = buf[
offset];
786 offset +=
sizeof(uint8_t);
792 goto not_enough_data;
795 offset +=
sizeof(uint16_t);
802 goto not_enough_data;
805 offset +=
sizeof(uint32_t);
812 goto not_enough_data;
814 object->count = *(uint8_t *)(buf +
offset);
815 offset +=
sizeof(uint8_t);
858 static void DNP3HandleUserDataRequest(
DNP3State *dnp3,
const uint8_t *input,
863 DNP3ApplicationHeader *ah;
866 lh = (DNP3LinkHeader *)input;
868 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
869 input_len -
sizeof(DNP3LinkHeader))) {
873 th = input[
sizeof(DNP3LinkHeader)];
877 if (ttx->lh.src == lh->src && ttx->lh.dst == lh->dst && ttx->is_request && !ttx->done &&
893 ah = (DNP3ApplicationHeader *)(input +
sizeof(DNP3LinkHeader) +
902 tx = DNP3TxAlloc(dnp3,
true);
911 if (!DNP3ReassembleApplicationLayer(input +
sizeof(DNP3LinkHeader),
927 if (DNP3DecodeApplicationObjects(tx, tx->
buffer +
sizeof(DNP3ApplicationHeader),
933 static void DNP3HandleUserDataResponse(
DNP3State *dnp3,
const uint8_t *input,
938 DNP3ApplicationHeader *ah;
939 DNP3InternalInd *iin;
943 lh = (DNP3LinkHeader *)input;
944 offset +=
sizeof(DNP3LinkHeader);
946 if (!DNP3CheckUserDataCRCs(input +
offset, input_len -
offset)) {
954 if (ttx->lh.src == lh->src && ttx->lh.dst == lh->dst && !ttx->is_request &&
970 ah = (DNP3ApplicationHeader *)(input +
offset);
971 offset +=
sizeof(DNP3ApplicationHeader);
972 iin = (DNP3InternalInd *)(input +
offset);
974 tx = DNP3TxAlloc(dnp3,
false);
986 if (!DNP3ReassembleApplicationLayer(input +
sizeof(DNP3LinkHeader),
998 offset =
sizeof(DNP3ApplicationHeader) +
sizeof(DNP3InternalInd);
999 if (DNP3DecodeApplicationObjects(
1011 static int DNP3HandleRequestLinkLayer(
DNP3State *dnp3,
const uint8_t *input,
1015 uint32_t processed = 0;
1020 if (input_len <
sizeof(DNP3LinkHeader)) {
1024 DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1026 if (!DNP3CheckStartBytes(header)) {
1030 if (!DNP3CheckLinkHeaderCRC(header)) {
1035 uint32_t frame_len = DNP3CalculateLinkLength(header->len);
1036 if (frame_len == 0) {
1040 if (input_len < frame_len) {
1046 if (!DNP3IsUserData(header)) {
1052 if (!DNP3HasUserData(header, STREAM_TOSERVER)) {
1057 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
1058 frame_len -
sizeof(DNP3LinkHeader))) {
1063 DNP3HandleUserDataRequest(dnp3, input, frame_len);
1068 input_len -= frame_len;
1069 processed += frame_len;
1088 StreamSlice stream_slice,
void *local_data)
1095 const uint8_t *input = StreamSliceGetData(&stream_slice);
1096 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1098 if (input_len == 0) {
1103 if (!DNP3BufferAdd(buffer, input, input_len)) {
1106 processed = DNP3HandleRequestLinkLayer(dnp3,
1109 if (processed < 0) {
1112 buffer->
offset += processed;
1113 DNP3BufferTrim(buffer);
1116 processed = DNP3HandleRequestLinkLayer(dnp3, input, input_len);
1117 if (processed < 0) {
1118 SCLogDebug(
"Failed to process request link layer.");
1123 input_len -= processed;
1127 if (!DNP3BufferAdd(buffer, input, input_len)) {
1137 DNP3BufferReset(buffer);
1147 static int DNP3HandleResponseLinkLayer(
DNP3State *dnp3,
const uint8_t *input,
1151 uint32_t processed = 0;
1156 if (input_len <
sizeof(DNP3LinkHeader)) {
1160 DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1162 if (!DNP3CheckStartBytes(header)) {
1166 if (!DNP3CheckLinkHeaderCRC(header)) {
1172 uint32_t frame_len = DNP3CalculateLinkLength(header->len);
1173 if (frame_len == 0) {
1177 if (input_len < frame_len) {
1183 if (!DNP3IsUserData(header)) {
1189 if (!DNP3HasUserData(header, STREAM_TOCLIENT)) {
1194 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
1195 frame_len -
sizeof(DNP3LinkHeader))) {
1200 DNP3HandleUserDataResponse(dnp3, input, frame_len);
1205 input_len -= frame_len;
1206 processed += frame_len;
1226 StreamSlice stream_slice,
void *local_data)
1234 const uint8_t *input = StreamSliceGetData(&stream_slice);
1235 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1238 if (!DNP3BufferAdd(buffer, input, input_len)) {
1241 processed = DNP3HandleResponseLinkLayer(dnp3,
1244 if (processed < 0) {
1247 buffer->
offset += processed;
1248 DNP3BufferTrim(buffer);
1253 if (DNP3ContainsBanner(input, input_len)) {
1257 processed = DNP3HandleResponseLinkLayer(dnp3, input, input_len);
1258 if (processed < 0) {
1262 input_len -= processed;
1266 if (!DNP3BufferAdd(buffer, input, input_len)) {
1278 DNP3BufferReset(buffer);
1282 static void *DNP3GetTx(
void *alstate, uint64_t tx_id)
1287 uint64_t tx_num = tx_id + 1;
1294 if (tx_num != tx->
tx_num) {
1303 static uint64_t DNP3GetTxCnt(
void *state)
1306 uint64_t count = ((uint64_t)((
DNP3State *)state)->transaction_max);
1313 static void DNP3TxFreeObjectList(DNP3ObjectList *objects)
1319 DNP3ObjectFree(
object);
1330 if (tx->
buffer != NULL) {
1336 if (tx->
tx_data.de_state != NULL) {
1340 DNP3TxFreeObjectList(&tx->
objects);
1352 static void DNP3StateTxFree(
void *state, uint64_t tx_id)
1357 uint64_t tx_num = tx_id + 1;
1361 if (tx->
tx_num != tx_num) {
1365 if (tx == dnp3->
curr) {
1369 if (tx->
tx_data.events != NULL) {
1394 static void DNP3StateFree(
void *state)
1399 if (state != NULL) {
1400 while ((tx =
TAILQ_FIRST(&dnp3->tx_list)) != NULL) {
1418 static int DNP3GetAlstateProgress(
void *tx, uint8_t direction)
1427 SCLogDebug(
"flooded: returning tx as done.");
1440 static int DNP3StateGetEventInfo(
const char *event_name,
int *event_id,
1441 AppLayerEventType *event_type)
1444 if (*event_id == -1) {
1446 "the DNP3 enum event map table.",
1451 *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
1459 static int DNP3StateGetEventInfoById(
int event_id,
const char **event_name,
1460 AppLayerEventType *event_type)
1463 if (*event_name == NULL) {
1465 "the DNP3 enum event map table.",
1470 *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
1481 static AppLayerStateData *DNP3GetStateData(
void *vstate)
1494 switch (prefix_code) {
1505 static AppLayerGetTxIterTuple DNP3GetTxIterator(
const uint8_t ipproto,
const AppProto alproto,
1509 AppLayerGetTxIterTuple no_tuple = { NULL, 0,
false };
1512 if (state->
un.
ptr == NULL) {
1518 while (tx_ptr->
tx_num < min_tx_id + 1) {
1524 if (tx_ptr->
tx_num >= max_tx_id + 1) {
1528 AppLayerGetTxIterTuple tuple = {
1530 .tx_id = tx_ptr->
tx_num - 1,
1531 .has_next = (state->
un.
ptr != NULL),
1546 const char *proto_name =
"dnp3";
1553 ALPROTO_DNP3, 0,
sizeof(DNP3LinkHeader), STREAM_TOSERVER,
1554 DNP3ProbingParser, DNP3ProbingParser);
1559 DNP3ProbingParser, DNP3ProbingParser)) {
1565 SCLogConfig(
"Protocol detection and parser disabled for DNP3.");
1579 DNP3StateAlloc, DNP3StateFree);
1588 DNP3GetAlstateProgress);
1592 DNP3StateGetEventInfo);
1594 DNP3StateGetEventInfoById);
1602 "Protocol detection still on.", proto_name);
1621 static void DNP3FixCrc(uint8_t *data, uint32_t
len)
1623 uint32_t block_size;
1631 uint16_t
crc = DNP3ComputeCRC(data, block_size);
1632 data[block_size + 1] = (
crc >> 8) & 0xff;
1633 data[block_size] =
crc & 0xff;
1642 static int DNP3ParserTestCheckCRC(
void)
1644 uint8_t request[] = {
1646 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1653 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1654 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1658 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1662 FAIL_IF(!DNP3CheckCRC(request,
sizeof(DNP3LinkHeader)));
1665 FAIL_IF(!DNP3CheckCRC(request +
sizeof(DNP3LinkHeader),
1668 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1671 FAIL_IF(DNP3CheckCRC(request,
sizeof(DNP3LinkHeader)));
1675 request[
sizeof(DNP3LinkHeader) + 3]++;
1676 FAIL_IF(DNP3CheckCRC(request +
sizeof(DNP3LinkHeader),
1686 static int DNP3CheckUserDataCRCsTest(
void)
1689 uint8_t data_valid[] = {
1690 0xff, 0xc9, 0x05, 0x0c,
1691 0x01, 0x28, 0x01, 0x00,
1692 0x00, 0x00, 0x01, 0x01,
1693 0x01, 0x00, 0x00, 0x00,
1696 0xff, 0xc9, 0x05, 0x0c,
1697 0x01, 0x28, 0x01, 0x00,
1698 0x00, 0x00, 0x01, 0x01,
1699 0x01, 0x00, 0x00, 0x00,
1702 0xff, 0xc9, 0x05, 0x0c,
1703 0x01, 0x28, 0x01, 0x00,
1704 0x00, 0x00, 0x01, 0x01,
1705 0x01, 0x00, 0x00, 0x00,
1708 0x00, 0x00, 0x00, 0x00,
1712 FAIL_IF(!DNP3CheckUserDataCRCs(data_valid,
sizeof(data_valid)));
1714 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1716 uint8_t data_invalid[] = {
1717 0xff, 0xc9, 0x05, 0x0c,
1718 0x01, 0x28, 0x01, 0x00,
1719 0x00, 0x00, 0x01, 0x01,
1720 0x01, 0x00, 0x00, 0x00,
1723 0xff, 0xc9, 0x05, 0x0c,
1724 0x01, 0x28, 0x01, 0x00,
1725 0x00, 0x00, 0x01, 0x01,
1726 0x01, 0x00, 0x00, 0x00,
1729 0xff, 0xc9, 0x05, 0x0c,
1730 0x01, 0x28, 0x01, 0x00,
1731 0x00, 0x00, 0x01, 0x01,
1732 0x01, 0x00, 0x00, 0x00,
1735 0x00, 0x00, 0x00, 0x00,
1739 FAIL_IF(DNP3CheckUserDataCRCs(data_invalid,
sizeof(data_invalid)));
1742 uint8_t one_byte_nocrc[] = { 0x01 };
1743 FAIL_IF(DNP3CheckUserDataCRCs(one_byte_nocrc,
sizeof(one_byte_nocrc)));
1746 uint8_t two_byte_nocrc[] = { 0x01, 0x02 };
1747 FAIL_IF(DNP3CheckUserDataCRCs(two_byte_nocrc,
sizeof(two_byte_nocrc)));
1751 uint8_t three_bytes_good_crc[] = { 0x00, 0x00, 0x00 };
1752 *(uint16_t *)(three_bytes_good_crc + 1) = DNP3ComputeCRC(
1753 three_bytes_good_crc, 1);
1754 FAIL_IF(!DNP3CheckUserDataCRCs(three_bytes_good_crc,
1755 sizeof(three_bytes_good_crc)));
1767 static int DNP3CalculateLinkLengthTest(
void)
1770 FAIL_IF(DNP3CalculateLinkLength(0) != 0);
1771 FAIL_IF(DNP3CalculateLinkLength(1) != 0);
1772 FAIL_IF(DNP3CalculateLinkLength(2) != 0);
1773 FAIL_IF(DNP3CalculateLinkLength(3) != 0);
1774 FAIL_IF(DNP3CalculateLinkLength(4) != 0);
1777 FAIL_IF(DNP3CalculateLinkLength(5) != 10);
1780 FAIL_IF(DNP3CalculateLinkLength(21) != 28);
1783 FAIL_IF(DNP3CalculateLinkLength(37) != 46);
1787 FAIL_IF(DNP3CalculateLinkLength(38) != 49);
1790 FAIL_IF(DNP3CalculateLinkLength(255) != 292);
1799 static int DNP3CalculateTransportLengthWithoutCRCsTest(
void)
1801 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(0) != -1);
1802 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(1) != -1);
1803 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(2) != 0);
1804 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(3) != 1);
1805 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(16) != 14);
1806 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(17) != 15);
1807 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(18) != 16);
1810 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(19) != -1);
1814 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(20) != 16);
1816 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(21) != 17);
1824 static int DNP3ParserCheckLinkHeaderCRC(
void)
1827 uint8_t request[] = {
1829 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1836 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1837 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1838 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1841 DNP3LinkHeader *header = (DNP3LinkHeader *)request;
1842 FAIL_IF(!DNP3CheckLinkHeaderCRC(header));
1844 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1847 FAIL_IF(DNP3CheckLinkHeaderCRC(header));
1856 static int DNP3ReassembleApplicationLayerTest01(
void)
1858 uint32_t reassembled_len = 0;
1859 uint8_t *output = NULL;
1861 uint8_t payload[] = {
1863 0xff, 0xc9, 0x05, 0x0c,
1864 0x01, 0x28, 0x01, 0x00,
1865 0x00, 0x00, 0x01, 0x01,
1866 0x01, 0x00, 0x00, 0x00,
1869 0xff, 0xc9, 0x05, 0x0c,
1870 0x01, 0x28, 0x01, 0x00,
1871 0x00, 0x00, 0x01, 0x01,
1872 0x01, 0x00, 0x00, 0x00,
1875 0xff, 0xc9, 0x05, 0x0c,
1876 0x01, 0x28, 0x01, 0x00,
1877 0x00, 0x00, 0x01, 0x01,
1878 0x01, 0x00, 0x00, 0x00,
1881 0x00, 0x00, 0x00, 0x00,
1886 uint8_t expected[] = {
1888 0x01, 0x28, 0x01, 0x00,
1889 0x00, 0x00, 0x01, 0x01,
1890 0x01, 0x00, 0x00, 0x00,
1892 0xff, 0xc9, 0x05, 0x0c,
1893 0x01, 0x28, 0x01, 0x00,
1894 0x00, 0x00, 0x01, 0x01,
1895 0x01, 0x00, 0x00, 0x00,
1897 0xff, 0xc9, 0x05, 0x0c,
1898 0x01, 0x28, 0x01, 0x00,
1899 0x00, 0x00, 0x01, 0x01,
1900 0x01, 0x00, 0x00, 0x00,
1902 0x00, 0x00, 0x00, 0x00,
1908 FAIL_IF(!DNP3ReassembleApplicationLayer(payload,
1909 sizeof(payload), &output, &reassembled_len));
1911 FAIL_IF(reassembled_len !=
sizeof(expected));
1912 FAIL_IF(memcmp(expected, output, reassembled_len));
1916 reassembled_len = 0;
1918 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 1, &output,
1921 FAIL_IF(reassembled_len != 0);
1924 reassembled_len = 0;
1926 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 2, &output,
1929 FAIL_IF(reassembled_len != 0);
1933 reassembled_len = 0;
1935 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 3, &output,
1938 FAIL_IF(reassembled_len != 0);
1941 reassembled_len = 0;
1943 FAIL_IF(!DNP3ReassembleApplicationLayer(payload, 4, &output,
1946 FAIL_IF(reassembled_len != 1);
1949 uint8_t short_payload1[] = {
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 0xff, 0xc9, 0x05, 0x0c,
1964 0x01, 0x28, 0x01, 0x00,
1965 0x00, 0x00, 0x01, 0x01,
1966 0x01, 0x00, 0x00, 0x00,
1971 reassembled_len = 0;
1972 FAIL_IF(DNP3ReassembleApplicationLayer(short_payload1,
1973 sizeof(short_payload1), &output, &reassembled_len));
1976 uint8_t short_payload2[] = {
1978 0xff, 0xc9, 0x05, 0x0c,
1979 0x01, 0x28, 0x01, 0x00,
1980 0x00, 0x00, 0x01, 0x01,
1981 0x01, 0x00, 0x00, 0x00,
1984 0xff, 0xc9, 0x05, 0x0c,
1985 0x01, 0x28, 0x01, 0x00,
1986 0x00, 0x00, 0x01, 0x01,
1987 0x01, 0x00, 0x00, 0x00,
1990 0xff, 0xc9, 0x05, 0x0c,
1991 0x01, 0x28, 0x01, 0x00,
1992 0x00, 0x00, 0x01, 0x01,
1993 0x01, 0x00, 0x00, 0x00,
1998 reassembled_len = 0;
1999 FAIL_IF(DNP3ReassembleApplicationLayer(short_payload2,
2000 sizeof(short_payload2), &output, &reassembled_len));
2008 static int DNP3ProbingParserTest(
void)
2011 0x05, 0x64, 0x05, 0xc9, 0x03, 0x00, 0x04, 0x00,
2017 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt,
sizeof(pkt), &rdir) !=
ALPROTO_DNP3);
2020 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt,
sizeof(DNP3LinkHeader) - 1, &rdir) !=
ALPROTO_UNKNOWN);
2034 char mybanner[] =
"Welcome to DNP3 SCADA.";
2035 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, (uint8_t *)mybanner,
sizeof(mybanner) - 1,
2037 FAIL_IF(rdir != STREAM_TOCLIENT);
2045 static int DNP3ParserTestRequestResponse(
void)
2049 uint8_t request[] = {
2051 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2058 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2059 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2060 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2063 uint8_t response[] = {
2065 0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2072 0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2073 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2074 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2082 memset(&flow, 0,
sizeof(flow));
2083 memset(&ssn, 0,
sizeof(ssn));
2086 flow.
proto = IPPROTO_TCP;
2093 STREAM_TOSERVER, request,
sizeof(request)));
2109 STREAM_TOCLIENT, response,
sizeof(response)));
2128 static int DNP3ParserTestUnsolicitedResponseConfirm(
void)
2133 uint8_t response[] = {
2134 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2135 0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2136 0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2137 0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9
2141 uint8_t confirm[] = {
2142 0x05, 0x64, 0x08, 0xc4, 0x02, 0x00,
2143 0x01, 0x00, 0xd3, 0xb7, 0xc0, 0xda, 0x00, 0x6a,
2151 memset(&flow, 0,
sizeof(flow));
2152 memset(&ssn, 0,
sizeof(ssn));
2155 flow.
proto = IPPROTO_TCP;
2162 STREAM_TOCLIENT, response,
sizeof(response)));
2177 STREAM_TOSERVER, confirm,
sizeof(confirm)));
2198 static int DNP3ParserTestFlooded(
void)
2202 uint8_t request[] = {
2204 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2211 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2212 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2213 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2220 memset(&flow, 0,
sizeof(flow));
2221 memset(&ssn, 0,
sizeof(ssn));
2224 flow.
proto = IPPROTO_TCP;
2231 STREAM_TOSERVER, request,
sizeof(request)));
2245 FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2250 STREAM_TOSERVER, request,
sizeof(request)));
2254 FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2259 STREAM_TOSERVER, request,
sizeof(request)));
2264 FAIL_IF(!DNP3GetAlstateProgress(tx, 0));
2279 static int DNP3ParserTestPartialFrame(
void)
2285 uint8_t request_partial1[] = {
2287 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2294 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2297 uint8_t request_partial2[] = {
2299 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2300 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2303 uint8_t response_partial1[] = {
2305 0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2312 0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2315 uint8_t response_partial2[] = {
2316 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2317 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2325 memset(&flow, 0,
sizeof(flow));
2326 memset(&ssn, 0,
sizeof(ssn));
2328 flow.
proto = IPPROTO_TCP;
2336 STREAM_TOSERVER, request_partial1,
sizeof(request_partial1));
2346 sizeof(request_partial1)));
2350 FAIL_IF(DNP3GetTx(state, 0) != NULL);
2355 STREAM_TOSERVER, request_partial2,
sizeof(request_partial2));
2365 tx = DNP3GetTx(state, 0);
2376 STREAM_TOCLIENT, response_partial1,
sizeof(response_partial1));
2381 tx = DNP3GetTx(state, 1);
2387 STREAM_TOCLIENT, response_partial2,
sizeof(response_partial2));
2396 tx = DNP3GetTx(state, 1);
2410 static int DNP3ParserTestMultiFrame(
void)
2415 uint8_t unsol_response1[] = {
2416 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2417 0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2418 0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2419 0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9,
2423 uint8_t unsol_response2[] = {
2424 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2425 0x89, 0xe5, 0xc5, 0xfb, 0x82, 0x00, 0x00, 0x02,
2426 0x02, 0x17, 0x01, 0x0c, 0x01, 0xd8, 0x75, 0xd8,
2427 0x32, 0x4c, 0xc9, 0x3c, 0x01, 0xa1, 0xc9,
2430 uint8_t combined[
sizeof(unsol_response1) +
sizeof(unsol_response2)];
2431 memcpy(combined, unsol_response1,
sizeof(unsol_response1));
2432 memcpy(combined +
sizeof(unsol_response1), unsol_response2,
2433 sizeof(unsol_response2));
2440 memset(&flow, 0,
sizeof(flow));
2441 memset(&ssn, 0,
sizeof(ssn));
2443 flow.
proto = IPPROTO_TCP;
2449 STREAM_TOCLIENT, combined,
sizeof(combined));
2471 static int DNP3ParserTestParsePDU01(
void)
2475 const uint8_t pkt[] = {
2477 0x0b, 0xc4, 0x17, 0x00, 0xef, 0xff, 0xc4, 0x8f,
2478 0xe1, 0xc8, 0x01, 0x01, 0x00, 0x06, 0x77, 0x6e
2482 int pdus = DNP3HandleRequestLinkLayer(dnp3state, pkt,
sizeof(pkt));
2492 DNP3StateFree(dnp3state);
2499 static int DNP3ParserDecodeG70V3Test(
void)
2501 const uint8_t pkt[] = {
2503 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00, 0xc7, 0xee,
2504 0xc7, 0xc9, 0x1b, 0x46, 0x03, 0x5b, 0x01, 0x55,
2505 0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2506 0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2507 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2508 0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2509 0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2510 0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2511 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2512 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2513 0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2514 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2515 0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2516 0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2522 int bytes = DNP3HandleRequestLinkLayer(dnp3state, pkt,
sizeof(pkt));
2523 FAIL_IF(bytes !=
sizeof(pkt));
2542 "C:/temp/DNPDeviceConfiguration written to Remote Device.xml") == 0);
2543 DNP3StateFree(dnp3state);
2550 static int DNP3ParserUnknownEventAlertTest(
void)
2554 0x05, 0x64, 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00,
2564 0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2565 0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2567 0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2568 0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2569 0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2570 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2571 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2572 0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2573 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2574 0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2575 0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2579 DNP3FixCrc(pkt + 10,
sizeof(pkt) - 10);
2583 int bytes = DNP3HandleRequestLinkLayer(dnp3state, pkt,
sizeof(pkt));
2584 FAIL_IF(bytes !=
sizeof(pkt));
2586 DNP3StateFree(dnp3state);
2593 static int DNP3ParserIncorrectUserData(
void)
2595 uint8_t packet_bytes[] = {
2596 0x05, 0x64, 0x08, 0xc4, 0x03, 0x00, 0x04, 0x00,
2597 0xbf, 0xe9, 0xc1, 0xc1, 0x82, 0xc5, 0xee
2603 memset(&flow, 0,
sizeof(flow));
2604 memset(&ssn, 0,
sizeof(ssn));
2606 flow.
proto = IPPROTO_TCP;
2611 STREAM_TOCLIENT, packet_bytes,
sizeof(packet_bytes));
2626 UtRegisterTest(
"DNP3ParserTestCheckCRC", DNP3ParserTestCheckCRC);
2628 DNP3ParserCheckLinkHeaderCRC);
2629 UtRegisterTest(
"DNP3CheckUserDataCRCsTest", DNP3CheckUserDataCRCsTest);
2630 UtRegisterTest(
"DNP3CalculateLinkLengthTest", DNP3CalculateLinkLengthTest);
2632 DNP3CalculateTransportLengthWithoutCRCsTest);
2634 DNP3ReassembleApplicationLayerTest01);
2637 DNP3ParserTestRequestResponse);
2639 DNP3ParserTestUnsolicitedResponseConfirm);
2640 UtRegisterTest(
"DNP3ParserTestPartialFrame", DNP3ParserTestPartialFrame);
2641 UtRegisterTest(
"DNP3ParserTestMultiFrame", DNP3ParserTestMultiFrame);
2643 UtRegisterTest(
"DNP3ParserTestParsePDU01", DNP3ParserTestParsePDU01);
2644 UtRegisterTest(
"DNP3ParserDecodeG70V3Test", DNP3ParserDecodeG70V3Test);
2646 DNP3ParserUnknownEventAlertTest);
2647 UtRegisterTest(
"DNP3ParserIncorrectUserData", DNP3ParserIncorrectUserData);