44 #define DNP3_DEFAULT_REQ_FLOOD_COUNT 500
46 #define DNP3_DEFAULT_PORT "20000"
49 #define DNP3_START_BYTE0 0x05
50 #define DNP3_START_BYTE1 0x64
53 #define DNP3_MIN_LEN 5
56 #define DNP3_CRC_LEN 2
60 #define DNP3_BLOCK_SIZE 16
63 #define DNP3_MAX_TRAN_SEQNO 64
70 #define DNP3_LINK_HDR_LEN 5
86 #define DNP3_OBJ_PREFIX(x) ((x >> 4) & 0x7)
89 #define DNP3_OBJ_RANGE(x) (x & 0xf)
103 #define NEXT_TH_SEQNO(current) ((current + 1) % DNP3_MAX_TRAN_SEQNO)
107 static const uint16_t crc_table[256] = {
108 0x0000, 0x365e, 0x6cbc, 0x5ae2, 0xd978, 0xef26, 0xb5c4, 0x839a,
109 0xff89, 0xc9d7, 0x9335, 0xa56b, 0x26f1, 0x10af, 0x4a4d, 0x7c13,
110 0xb26b, 0x8435, 0xded7, 0xe889, 0x6b13, 0x5d4d, 0x07af, 0x31f1,
111 0x4de2, 0x7bbc, 0x215e, 0x1700, 0x949a, 0xa2c4, 0xf826, 0xce78,
112 0x29af, 0x1ff1, 0x4513, 0x734d, 0xf0d7, 0xc689, 0x9c6b, 0xaa35,
113 0xd626, 0xe078, 0xba9a, 0x8cc4, 0x0f5e, 0x3900, 0x63e2, 0x55bc,
114 0x9bc4, 0xad9a, 0xf778, 0xc126, 0x42bc, 0x74e2, 0x2e00, 0x185e,
115 0x644d, 0x5213, 0x08f1, 0x3eaf, 0xbd35, 0x8b6b, 0xd189, 0xe7d7,
116 0x535e, 0x6500, 0x3fe2, 0x09bc, 0x8a26, 0xbc78, 0xe69a, 0xd0c4,
117 0xacd7, 0x9a89, 0xc06b, 0xf635, 0x75af, 0x43f1, 0x1913, 0x2f4d,
118 0xe135, 0xd76b, 0x8d89, 0xbbd7, 0x384d, 0x0e13, 0x54f1, 0x62af,
119 0x1ebc, 0x28e2, 0x7200, 0x445e, 0xc7c4, 0xf19a, 0xab78, 0x9d26,
120 0x7af1, 0x4caf, 0x164d, 0x2013, 0xa389, 0x95d7, 0xcf35, 0xf96b,
121 0x8578, 0xb326, 0xe9c4, 0xdf9a, 0x5c00, 0x6a5e, 0x30bc, 0x06e2,
122 0xc89a, 0xfec4, 0xa426, 0x9278, 0x11e2, 0x27bc, 0x7d5e, 0x4b00,
123 0x3713, 0x014d, 0x5baf, 0x6df1, 0xee6b, 0xd835, 0x82d7, 0xb489,
124 0xa6bc, 0x90e2, 0xca00, 0xfc5e, 0x7fc4, 0x499a, 0x1378, 0x2526,
125 0x5935, 0x6f6b, 0x3589, 0x03d7, 0x804d, 0xb613, 0xecf1, 0xdaaf,
126 0x14d7, 0x2289, 0x786b, 0x4e35, 0xcdaf, 0xfbf1, 0xa113, 0x974d,
127 0xeb5e, 0xdd00, 0x87e2, 0xb1bc, 0x3226, 0x0478, 0x5e9a, 0x68c4,
128 0x8f13, 0xb94d, 0xe3af, 0xd5f1, 0x566b, 0x6035, 0x3ad7, 0x0c89,
129 0x709a, 0x46c4, 0x1c26, 0x2a78, 0xa9e2, 0x9fbc, 0xc55e, 0xf300,
130 0x3d78, 0x0b26, 0x51c4, 0x679a, 0xe400, 0xd25e, 0x88bc, 0xbee2,
131 0xc2f1, 0xf4af, 0xae4d, 0x9813, 0x1b89, 0x2dd7, 0x7735, 0x416b,
132 0xf5e2, 0xc3bc, 0x995e, 0xaf00, 0x2c9a, 0x1ac4, 0x4026, 0x7678,
133 0x0a6b, 0x3c35, 0x66d7, 0x5089, 0xd313, 0xe54d, 0xbfaf, 0x89f1,
134 0x4789, 0x71d7, 0x2b35, 0x1d6b, 0x9ef1, 0xa8af, 0xf24d, 0xc413,
135 0xb800, 0x8e5e, 0xd4bc, 0xe2e2, 0x6178, 0x5726, 0x0dc4, 0x3b9a,
136 0xdc4d, 0xea13, 0xb0f1, 0x86af, 0x0535, 0x336b, 0x6989, 0x5fd7,
137 0x23c4, 0x159a, 0x4f78, 0x7926, 0xfabc, 0xcce2, 0x9600, 0xa05e,
138 0x6e26, 0x5878, 0x029a, 0x34c4, 0xb75e, 0x8100, 0xdbe2, 0xedbc,
139 0x91af, 0xa7f1, 0xfd13, 0xcb4d, 0x48d7, 0x7e89, 0x246b, 0x1235
149 static uint16_t DNP3ComputeCRC(
const uint8_t *buf, uint32_t
len)
151 const uint8_t *
byte = buf;
156 idx = (
crc ^ *byte) & 0xff;
157 crc = (crc_table[idx] ^ (
crc >> 8)) & 0xffff;
161 return ~
crc & 0xffff;
172 static int DNP3CheckCRC(
const uint8_t *block, uint32_t
len)
174 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
187 if (((
crc & 0xff) == block[crc_offset]) &&
188 ((
crc >> 8) == block[crc_offset + 1])) {
202 static int DNP3CheckLinkHeaderCRC(
const DNP3LinkHeader *header)
204 return DNP3CheckCRC((uint8_t *)header,
sizeof(DNP3LinkHeader));
215 static int DNP3CheckUserDataCRCs(
const uint8_t *data, uint32_t
len)
228 if (!DNP3CheckCRC(data +
offset, block_size)) {
244 static int DNP3CheckStartBytes(
const DNP3LinkHeader *header)
251 #define DNP3_BANNER "DNP3"
261 static int DNP3ContainsBanner(
const uint8_t *input, uint32_t
len)
269 static uint16_t DNP3ProbingParser(
Flow *f, uint8_t direction,
270 const uint8_t *input, uint32_t
len,
273 const DNP3LinkHeader *
const hdr = (
const DNP3LinkHeader *)input;
274 const bool toserver = (direction & STREAM_TOSERVER) != 0;
277 if (DNP3ContainsBanner(input,
len)) {
279 bool is_banner =
true;
281 for (uint32_t i = 0; i <
len && i < 0x100; i++) {
282 if (!isprint(input[i])) {
289 *rdir = STREAM_TOCLIENT;
296 if (
len <
sizeof(DNP3LinkHeader)) {
297 SCLogDebug(
"Length too small to be a DNP3 header.");
302 if (!DNP3CheckStartBytes(hdr)) {
309 SCLogDebug(
"Packet too small to be a valid DNP3 fragment.");
315 *rdir = toserver ? STREAM_TOCLIENT : STREAM_TOSERVER;
328 static int DNP3CalculateTransportLengthWithoutCRCs(uint32_t input_len)
371 static int DNP3ReassembleApplicationLayer(
const uint8_t *input,
372 uint32_t input_len, uint8_t **output, uint32_t *output_len)
374 int len = DNP3CalculateTransportLengthWithoutCRCs(input_len);
386 if (*output == NULL) {
393 uint8_t *ptr =
SCRealloc(*output, (
size_t)(*output_len +
len));
400 int offset = 0, block_size;
401 while ((uint32_t)
offset < input_len) {
406 block_size = input_len -
offset;
431 memcpy(*output + *output_len, input +
offset,
446 static void *DNP3StateAlloc(
void *orig_state,
AppProto proto_orig)
465 static void DNP3SetEvent(
DNP3State *dnp3, uint8_t event)
467 if (dnp3 && dnp3->
curr) {
472 SCLogWarning(
"Failed to set event, state or tx pointer was NULL.");
528 static uint32_t DNP3CalculateLinkLength(uint8_t length)
530 uint32_t frame_len = 0;
548 return frame_len +
sizeof(DNP3LinkHeader);
558 static int DNP3IsUserData(
const DNP3LinkHeader *header)
577 static int DNP3HasUserData(
const DNP3LinkHeader *header, uint8_t direction)
579 if (direction == STREAM_TOSERVER) {
581 sizeof(DNP3ApplicationHeader);
585 sizeof(DNP3ApplicationHeader) +
sizeof(DNP3InternalInd);
592 static void DNP3BufferReset(
DNP3Buffer *buffer)
607 static int DNP3BufferAdd(
DNP3Buffer *buffer,
const uint8_t *data, uint32_t
len)
609 if (buffer->
size == 0) {
638 static void DNP3BufferTrim(
DNP3Buffer *buffer)
641 DNP3BufferReset(buffer);
643 else if (buffer->
offset > 0) {
654 static void DNP3ObjectFree(
DNP3Object *
object)
656 if (object->
points != NULL) {
673 if (object->
points == NULL) {
674 DNP3ObjectFree(
object);
695 static int DNP3DecodeApplicationObjects(
DNP3Transaction *tx,
const uint8_t *buf,
696 uint32_t
len, DNP3ObjectList *objects)
700 if (buf == NULL ||
len == 0) {
707 if (
len <
sizeof(DNP3ObjHeader)) {
710 DNP3ObjHeader *header = (DNP3ObjHeader *)buf;
711 offset +=
sizeof(DNP3ObjHeader);
719 object->group = header->group;
720 object->variation = header->variation;
721 object->qualifier = header->qualifier;
731 if (
offset + (
sizeof(uint8_t) * 2) >
len) {
734 goto not_enough_data;
736 object->start = buf[
offset++];
737 object->stop = buf[
offset++];
738 object->count =
object->stop -
object->start + 1;
745 if (
offset + (
sizeof(uint16_t) * 2) >
len) {
748 goto not_enough_data;
751 offset +=
sizeof(uint16_t);
753 offset +=
sizeof(uint16_t);
754 object->count =
object->stop -
object->start + 1;
761 if (
offset + (
sizeof(uint32_t) * 2) >
len) {
764 goto not_enough_data;
767 offset +=
sizeof(uint32_t);
769 offset +=
sizeof(uint32_t);
770 object->count =
object->stop -
object->start + 1;
781 goto not_enough_data;
783 object->count = buf[
offset];
784 offset +=
sizeof(uint8_t);
790 goto not_enough_data;
793 offset +=
sizeof(uint16_t);
800 goto not_enough_data;
803 offset +=
sizeof(uint32_t);
810 goto not_enough_data;
812 object->count = *(uint8_t *)(buf +
offset);
813 offset +=
sizeof(uint8_t);
856 static void DNP3HandleUserDataRequest(
DNP3State *dnp3,
const uint8_t *input,
861 DNP3ApplicationHeader *ah;
864 lh = (DNP3LinkHeader *)input;
866 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
867 input_len -
sizeof(DNP3LinkHeader))) {
871 th = input[
sizeof(DNP3LinkHeader)];
875 if (ttx->lh.src == lh->src && ttx->lh.dst == lh->dst && ttx->is_request && !ttx->done &&
891 ah = (DNP3ApplicationHeader *)(input +
sizeof(DNP3LinkHeader) +
900 tx = DNP3TxAlloc(dnp3,
true);
909 if (!DNP3ReassembleApplicationLayer(input +
sizeof(DNP3LinkHeader),
925 if (DNP3DecodeApplicationObjects(tx, tx->
buffer +
sizeof(DNP3ApplicationHeader),
931 static void DNP3HandleUserDataResponse(
DNP3State *dnp3,
const uint8_t *input,
936 DNP3ApplicationHeader *ah;
937 DNP3InternalInd *iin;
941 lh = (DNP3LinkHeader *)input;
942 offset +=
sizeof(DNP3LinkHeader);
944 if (!DNP3CheckUserDataCRCs(input +
offset, input_len -
offset)) {
952 if (ttx->lh.src == lh->src && ttx->lh.dst == lh->dst && !ttx->is_request &&
968 ah = (DNP3ApplicationHeader *)(input +
offset);
969 offset +=
sizeof(DNP3ApplicationHeader);
970 iin = (DNP3InternalInd *)(input +
offset);
972 tx = DNP3TxAlloc(dnp3,
false);
984 if (!DNP3ReassembleApplicationLayer(input +
sizeof(DNP3LinkHeader),
996 offset =
sizeof(DNP3ApplicationHeader) +
sizeof(DNP3InternalInd);
997 if (DNP3DecodeApplicationObjects(
1009 static int DNP3HandleRequestLinkLayer(
DNP3State *dnp3,
const uint8_t *input,
1013 uint32_t processed = 0;
1018 if (input_len <
sizeof(DNP3LinkHeader)) {
1022 DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1024 if (!DNP3CheckStartBytes(header)) {
1028 if (!DNP3CheckLinkHeaderCRC(header)) {
1033 uint32_t frame_len = DNP3CalculateLinkLength(header->len);
1034 if (frame_len == 0) {
1038 if (input_len < frame_len) {
1044 if (!DNP3IsUserData(header)) {
1050 if (!DNP3HasUserData(header, STREAM_TOSERVER)) {
1055 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
1056 frame_len -
sizeof(DNP3LinkHeader))) {
1061 DNP3HandleUserDataRequest(dnp3, input, frame_len);
1066 input_len -= frame_len;
1067 processed += frame_len;
1086 StreamSlice stream_slice,
void *local_data)
1093 const uint8_t *input = StreamSliceGetData(&stream_slice);
1094 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1096 if (input_len == 0) {
1101 if (!DNP3BufferAdd(buffer, input, input_len)) {
1104 processed = DNP3HandleRequestLinkLayer(dnp3,
1107 if (processed < 0) {
1110 buffer->
offset += processed;
1111 DNP3BufferTrim(buffer);
1114 processed = DNP3HandleRequestLinkLayer(dnp3, input, input_len);
1115 if (processed < 0) {
1116 SCLogDebug(
"Failed to process request link layer.");
1121 input_len -= processed;
1125 if (!DNP3BufferAdd(buffer, input, input_len)) {
1135 DNP3BufferReset(buffer);
1145 static int DNP3HandleResponseLinkLayer(
DNP3State *dnp3,
const uint8_t *input,
1149 uint32_t processed = 0;
1154 if (input_len <
sizeof(DNP3LinkHeader)) {
1158 DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1160 if (!DNP3CheckStartBytes(header)) {
1164 if (!DNP3CheckLinkHeaderCRC(header)) {
1170 uint32_t frame_len = DNP3CalculateLinkLength(header->len);
1171 if (frame_len == 0) {
1175 if (input_len < frame_len) {
1181 if (!DNP3IsUserData(header)) {
1187 if (!DNP3HasUserData(header, STREAM_TOCLIENT)) {
1192 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
1193 frame_len -
sizeof(DNP3LinkHeader))) {
1198 DNP3HandleUserDataResponse(dnp3, input, frame_len);
1203 input_len -= frame_len;
1204 processed += frame_len;
1224 StreamSlice stream_slice,
void *local_data)
1232 const uint8_t *input = StreamSliceGetData(&stream_slice);
1233 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1236 if (!DNP3BufferAdd(buffer, input, input_len)) {
1239 processed = DNP3HandleResponseLinkLayer(dnp3,
1242 if (processed < 0) {
1245 buffer->
offset += processed;
1246 DNP3BufferTrim(buffer);
1251 if (DNP3ContainsBanner(input, input_len)) {
1255 processed = DNP3HandleResponseLinkLayer(dnp3, input, input_len);
1256 if (processed < 0) {
1260 input_len -= processed;
1264 if (!DNP3BufferAdd(buffer, input, input_len)) {
1276 DNP3BufferReset(buffer);
1280 static void *DNP3GetTx(
void *alstate, uint64_t tx_id)
1285 uint64_t tx_num = tx_id + 1;
1292 if (tx_num != tx->
tx_num) {
1301 static uint64_t DNP3GetTxCnt(
void *state)
1304 uint64_t count = ((uint64_t)((
DNP3State *)state)->transaction_max);
1311 static void DNP3TxFreeObjectList(DNP3ObjectList *objects)
1317 DNP3ObjectFree(
object);
1328 if (tx->
buffer != NULL) {
1334 if (tx->
tx_data.de_state != NULL) {
1338 DNP3TxFreeObjectList(&tx->
objects);
1350 static void DNP3StateTxFree(
void *state, uint64_t tx_id)
1355 uint64_t tx_num = tx_id + 1;
1359 if (tx->
tx_num != tx_num) {
1363 if (tx == dnp3->
curr) {
1367 if (tx->
tx_data.events != NULL) {
1392 static void DNP3StateFree(
void *state)
1397 if (state != NULL) {
1398 while ((tx =
TAILQ_FIRST(&dnp3->tx_list)) != NULL) {
1416 static int DNP3GetAlstateProgress(
void *tx, uint8_t direction)
1425 SCLogDebug(
"flooded: returning tx as done.");
1438 static int DNP3StateGetEventInfo(
const char *event_name,
int *event_id,
1439 AppLayerEventType *event_type)
1442 if (*event_id == -1) {
1444 "the DNP3 enum event map table.",
1449 *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
1457 static int DNP3StateGetEventInfoById(
int event_id,
const char **event_name,
1458 AppLayerEventType *event_type)
1461 if (*event_name == NULL) {
1463 "the DNP3 enum event map table.",
1468 *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
1479 static AppLayerStateData *DNP3GetStateData(
void *vstate)
1492 switch (prefix_code) {
1503 static AppLayerGetTxIterTuple DNP3GetTxIterator(
const uint8_t ipproto,
const AppProto alproto,
1507 AppLayerGetTxIterTuple no_tuple = { NULL, 0,
false };
1510 if (state->
un.
ptr == NULL) {
1516 while (tx_ptr->
tx_num < min_tx_id + 1) {
1522 if (tx_ptr->
tx_num >= max_tx_id + 1) {
1526 AppLayerGetTxIterTuple tuple = {
1528 .tx_id = tx_ptr->
tx_num - 1,
1529 .has_next = (state->
un.
ptr != NULL),
1544 const char *proto_name =
"dnp3";
1551 ALPROTO_DNP3, 0,
sizeof(DNP3LinkHeader), STREAM_TOSERVER,
1552 DNP3ProbingParser, DNP3ProbingParser);
1557 DNP3ProbingParser, DNP3ProbingParser)) {
1563 SCLogConfig(
"Protocol detection and parser disabled for DNP3.");
1577 DNP3StateAlloc, DNP3StateFree);
1586 DNP3GetAlstateProgress);
1590 DNP3StateGetEventInfo);
1592 DNP3StateGetEventInfoById);
1600 "Protocol detection still on.", proto_name);
1619 static void DNP3FixCrc(uint8_t *data, uint32_t
len)
1621 uint32_t block_size;
1629 uint16_t
crc = DNP3ComputeCRC(data, block_size);
1630 data[block_size + 1] = (
crc >> 8) & 0xff;
1631 data[block_size] =
crc & 0xff;
1640 static int DNP3ParserTestCheckCRC(
void)
1642 uint8_t request[] = {
1644 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1651 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1652 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1656 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1660 FAIL_IF(!DNP3CheckCRC(request,
sizeof(DNP3LinkHeader)));
1663 FAIL_IF(!DNP3CheckCRC(request +
sizeof(DNP3LinkHeader),
1666 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1669 FAIL_IF(DNP3CheckCRC(request,
sizeof(DNP3LinkHeader)));
1673 request[
sizeof(DNP3LinkHeader) + 3]++;
1674 FAIL_IF(DNP3CheckCRC(request +
sizeof(DNP3LinkHeader),
1684 static int DNP3CheckUserDataCRCsTest(
void)
1687 uint8_t data_valid[] = {
1688 0xff, 0xc9, 0x05, 0x0c,
1689 0x01, 0x28, 0x01, 0x00,
1690 0x00, 0x00, 0x01, 0x01,
1691 0x01, 0x00, 0x00, 0x00,
1694 0xff, 0xc9, 0x05, 0x0c,
1695 0x01, 0x28, 0x01, 0x00,
1696 0x00, 0x00, 0x01, 0x01,
1697 0x01, 0x00, 0x00, 0x00,
1700 0xff, 0xc9, 0x05, 0x0c,
1701 0x01, 0x28, 0x01, 0x00,
1702 0x00, 0x00, 0x01, 0x01,
1703 0x01, 0x00, 0x00, 0x00,
1706 0x00, 0x00, 0x00, 0x00,
1710 FAIL_IF(!DNP3CheckUserDataCRCs(data_valid,
sizeof(data_valid)));
1712 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1714 uint8_t data_invalid[] = {
1715 0xff, 0xc9, 0x05, 0x0c,
1716 0x01, 0x28, 0x01, 0x00,
1717 0x00, 0x00, 0x01, 0x01,
1718 0x01, 0x00, 0x00, 0x00,
1721 0xff, 0xc9, 0x05, 0x0c,
1722 0x01, 0x28, 0x01, 0x00,
1723 0x00, 0x00, 0x01, 0x01,
1724 0x01, 0x00, 0x00, 0x00,
1727 0xff, 0xc9, 0x05, 0x0c,
1728 0x01, 0x28, 0x01, 0x00,
1729 0x00, 0x00, 0x01, 0x01,
1730 0x01, 0x00, 0x00, 0x00,
1733 0x00, 0x00, 0x00, 0x00,
1737 FAIL_IF(DNP3CheckUserDataCRCs(data_invalid,
sizeof(data_invalid)));
1740 uint8_t one_byte_nocrc[] = { 0x01 };
1741 FAIL_IF(DNP3CheckUserDataCRCs(one_byte_nocrc,
sizeof(one_byte_nocrc)));
1744 uint8_t two_byte_nocrc[] = { 0x01, 0x02 };
1745 FAIL_IF(DNP3CheckUserDataCRCs(two_byte_nocrc,
sizeof(two_byte_nocrc)));
1749 uint8_t three_bytes_good_crc[] = { 0x00, 0x00, 0x00 };
1750 *(uint16_t *)(three_bytes_good_crc + 1) = DNP3ComputeCRC(
1751 three_bytes_good_crc, 1);
1752 FAIL_IF(!DNP3CheckUserDataCRCs(three_bytes_good_crc,
1753 sizeof(three_bytes_good_crc)));
1765 static int DNP3CalculateLinkLengthTest(
void)
1768 FAIL_IF(DNP3CalculateLinkLength(0) != 0);
1769 FAIL_IF(DNP3CalculateLinkLength(1) != 0);
1770 FAIL_IF(DNP3CalculateLinkLength(2) != 0);
1771 FAIL_IF(DNP3CalculateLinkLength(3) != 0);
1772 FAIL_IF(DNP3CalculateLinkLength(4) != 0);
1775 FAIL_IF(DNP3CalculateLinkLength(5) != 10);
1778 FAIL_IF(DNP3CalculateLinkLength(21) != 28);
1781 FAIL_IF(DNP3CalculateLinkLength(37) != 46);
1785 FAIL_IF(DNP3CalculateLinkLength(38) != 49);
1788 FAIL_IF(DNP3CalculateLinkLength(255) != 292);
1797 static int DNP3CalculateTransportLengthWithoutCRCsTest(
void)
1799 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(0) != -1);
1800 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(1) != -1);
1801 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(2) != 0);
1802 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(3) != 1);
1803 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(16) != 14);
1804 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(17) != 15);
1805 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(18) != 16);
1808 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(19) != -1);
1812 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(20) != 16);
1814 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(21) != 17);
1822 static int DNP3ParserCheckLinkHeaderCRC(
void)
1825 uint8_t request[] = {
1827 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1834 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1835 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1836 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1839 DNP3LinkHeader *header = (DNP3LinkHeader *)request;
1840 FAIL_IF(!DNP3CheckLinkHeaderCRC(header));
1842 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1845 FAIL_IF(DNP3CheckLinkHeaderCRC(header));
1854 static int DNP3ReassembleApplicationLayerTest01(
void)
1856 uint32_t reassembled_len = 0;
1857 uint8_t *output = NULL;
1859 uint8_t payload[] = {
1861 0xff, 0xc9, 0x05, 0x0c,
1862 0x01, 0x28, 0x01, 0x00,
1863 0x00, 0x00, 0x01, 0x01,
1864 0x01, 0x00, 0x00, 0x00,
1867 0xff, 0xc9, 0x05, 0x0c,
1868 0x01, 0x28, 0x01, 0x00,
1869 0x00, 0x00, 0x01, 0x01,
1870 0x01, 0x00, 0x00, 0x00,
1873 0xff, 0xc9, 0x05, 0x0c,
1874 0x01, 0x28, 0x01, 0x00,
1875 0x00, 0x00, 0x01, 0x01,
1876 0x01, 0x00, 0x00, 0x00,
1879 0x00, 0x00, 0x00, 0x00,
1884 uint8_t expected[] = {
1886 0x01, 0x28, 0x01, 0x00,
1887 0x00, 0x00, 0x01, 0x01,
1888 0x01, 0x00, 0x00, 0x00,
1890 0xff, 0xc9, 0x05, 0x0c,
1891 0x01, 0x28, 0x01, 0x00,
1892 0x00, 0x00, 0x01, 0x01,
1893 0x01, 0x00, 0x00, 0x00,
1895 0xff, 0xc9, 0x05, 0x0c,
1896 0x01, 0x28, 0x01, 0x00,
1897 0x00, 0x00, 0x01, 0x01,
1898 0x01, 0x00, 0x00, 0x00,
1900 0x00, 0x00, 0x00, 0x00,
1906 FAIL_IF(!DNP3ReassembleApplicationLayer(payload,
1907 sizeof(payload), &output, &reassembled_len));
1909 FAIL_IF(reassembled_len !=
sizeof(expected));
1910 FAIL_IF(memcmp(expected, output, reassembled_len));
1914 reassembled_len = 0;
1916 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 1, &output,
1919 FAIL_IF(reassembled_len != 0);
1922 reassembled_len = 0;
1924 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 2, &output,
1927 FAIL_IF(reassembled_len != 0);
1931 reassembled_len = 0;
1933 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 3, &output,
1936 FAIL_IF(reassembled_len != 0);
1939 reassembled_len = 0;
1941 FAIL_IF(!DNP3ReassembleApplicationLayer(payload, 4, &output,
1944 FAIL_IF(reassembled_len != 1);
1947 uint8_t short_payload1[] = {
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 0xff, 0xc9, 0x05, 0x0c,
1962 0x01, 0x28, 0x01, 0x00,
1963 0x00, 0x00, 0x01, 0x01,
1964 0x01, 0x00, 0x00, 0x00,
1969 reassembled_len = 0;
1970 FAIL_IF(DNP3ReassembleApplicationLayer(short_payload1,
1971 sizeof(short_payload1), &output, &reassembled_len));
1974 uint8_t short_payload2[] = {
1976 0xff, 0xc9, 0x05, 0x0c,
1977 0x01, 0x28, 0x01, 0x00,
1978 0x00, 0x00, 0x01, 0x01,
1979 0x01, 0x00, 0x00, 0x00,
1982 0xff, 0xc9, 0x05, 0x0c,
1983 0x01, 0x28, 0x01, 0x00,
1984 0x00, 0x00, 0x01, 0x01,
1985 0x01, 0x00, 0x00, 0x00,
1988 0xff, 0xc9, 0x05, 0x0c,
1989 0x01, 0x28, 0x01, 0x00,
1990 0x00, 0x00, 0x01, 0x01,
1991 0x01, 0x00, 0x00, 0x00,
1996 reassembled_len = 0;
1997 FAIL_IF(DNP3ReassembleApplicationLayer(short_payload2,
1998 sizeof(short_payload2), &output, &reassembled_len));
2006 static int DNP3ProbingParserTest(
void)
2009 0x05, 0x64, 0x05, 0xc9, 0x03, 0x00, 0x04, 0x00,
2015 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt,
sizeof(pkt), &rdir) !=
ALPROTO_DNP3);
2018 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt,
sizeof(DNP3LinkHeader) - 1, &rdir) !=
ALPROTO_UNKNOWN);
2032 char mybanner[] =
"Welcome to DNP3 SCADA.";
2033 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, (uint8_t *)mybanner,
sizeof(mybanner) - 1,
2035 FAIL_IF(rdir != STREAM_TOCLIENT);
2043 static int DNP3ParserTestRequestResponse(
void)
2047 uint8_t request[] = {
2049 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2056 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2057 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2058 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2061 uint8_t response[] = {
2063 0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2070 0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2071 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2072 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2080 memset(&flow, 0,
sizeof(flow));
2081 memset(&ssn, 0,
sizeof(ssn));
2084 flow.
proto = IPPROTO_TCP;
2091 STREAM_TOSERVER, request,
sizeof(request)));
2107 STREAM_TOCLIENT, response,
sizeof(response)));
2126 static int DNP3ParserTestUnsolicitedResponseConfirm(
void)
2131 uint8_t response[] = {
2132 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2133 0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2134 0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2135 0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9
2139 uint8_t confirm[] = {
2140 0x05, 0x64, 0x08, 0xc4, 0x02, 0x00,
2141 0x01, 0x00, 0xd3, 0xb7, 0xc0, 0xda, 0x00, 0x6a,
2149 memset(&flow, 0,
sizeof(flow));
2150 memset(&ssn, 0,
sizeof(ssn));
2153 flow.
proto = IPPROTO_TCP;
2160 STREAM_TOCLIENT, response,
sizeof(response)));
2175 STREAM_TOSERVER, confirm,
sizeof(confirm)));
2196 static int DNP3ParserTestFlooded(
void)
2200 uint8_t request[] = {
2202 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2209 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2210 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2211 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2218 memset(&flow, 0,
sizeof(flow));
2219 memset(&ssn, 0,
sizeof(ssn));
2222 flow.
proto = IPPROTO_TCP;
2229 STREAM_TOSERVER, request,
sizeof(request)));
2243 FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2248 STREAM_TOSERVER, request,
sizeof(request)));
2252 FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2257 STREAM_TOSERVER, request,
sizeof(request)));
2262 FAIL_IF(!DNP3GetAlstateProgress(tx, 0));
2277 static int DNP3ParserTestPartialFrame(
void)
2283 uint8_t request_partial1[] = {
2285 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2292 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2295 uint8_t request_partial2[] = {
2297 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2298 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2301 uint8_t response_partial1[] = {
2303 0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2310 0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2313 uint8_t response_partial2[] = {
2314 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2315 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2323 memset(&flow, 0,
sizeof(flow));
2324 memset(&ssn, 0,
sizeof(ssn));
2326 flow.
proto = IPPROTO_TCP;
2334 STREAM_TOSERVER, request_partial1,
sizeof(request_partial1));
2344 sizeof(request_partial1)));
2348 FAIL_IF(DNP3GetTx(state, 0) != NULL);
2353 STREAM_TOSERVER, request_partial2,
sizeof(request_partial2));
2363 tx = DNP3GetTx(state, 0);
2374 STREAM_TOCLIENT, response_partial1,
sizeof(response_partial1));
2379 tx = DNP3GetTx(state, 1);
2385 STREAM_TOCLIENT, response_partial2,
sizeof(response_partial2));
2394 tx = DNP3GetTx(state, 1);
2408 static int DNP3ParserTestMultiFrame(
void)
2413 uint8_t unsol_response1[] = {
2414 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2415 0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2416 0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2417 0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9,
2421 uint8_t unsol_response2[] = {
2422 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2423 0x89, 0xe5, 0xc5, 0xfb, 0x82, 0x00, 0x00, 0x02,
2424 0x02, 0x17, 0x01, 0x0c, 0x01, 0xd8, 0x75, 0xd8,
2425 0x32, 0x4c, 0xc9, 0x3c, 0x01, 0xa1, 0xc9,
2428 uint8_t combined[
sizeof(unsol_response1) +
sizeof(unsol_response2)];
2429 memcpy(combined, unsol_response1,
sizeof(unsol_response1));
2430 memcpy(combined +
sizeof(unsol_response1), unsol_response2,
2431 sizeof(unsol_response2));
2438 memset(&flow, 0,
sizeof(flow));
2439 memset(&ssn, 0,
sizeof(ssn));
2441 flow.
proto = IPPROTO_TCP;
2447 STREAM_TOCLIENT, combined,
sizeof(combined));
2469 static int DNP3ParserTestParsePDU01(
void)
2473 const uint8_t pkt[] = {
2475 0x0b, 0xc4, 0x17, 0x00, 0xef, 0xff, 0xc4, 0x8f,
2476 0xe1, 0xc8, 0x01, 0x01, 0x00, 0x06, 0x77, 0x6e
2480 int pdus = DNP3HandleRequestLinkLayer(dnp3state, pkt,
sizeof(pkt));
2490 DNP3StateFree(dnp3state);
2497 static int DNP3ParserDecodeG70V3Test(
void)
2499 const uint8_t pkt[] = {
2501 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00, 0xc7, 0xee,
2502 0xc7, 0xc9, 0x1b, 0x46, 0x03, 0x5b, 0x01, 0x55,
2503 0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2504 0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2505 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2506 0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2507 0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2508 0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2509 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2510 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2511 0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2512 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2513 0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2514 0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2520 int bytes = DNP3HandleRequestLinkLayer(dnp3state, pkt,
sizeof(pkt));
2521 FAIL_IF(bytes !=
sizeof(pkt));
2540 "C:/temp/DNPDeviceConfiguration written to Remote Device.xml") == 0);
2541 DNP3StateFree(dnp3state);
2548 static int DNP3ParserUnknownEventAlertTest(
void)
2552 0x05, 0x64, 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00,
2562 0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2563 0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2565 0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2566 0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2567 0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2568 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2569 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2570 0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2571 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2572 0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2573 0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2577 DNP3FixCrc(pkt + 10,
sizeof(pkt) - 10);
2581 int bytes = DNP3HandleRequestLinkLayer(dnp3state, pkt,
sizeof(pkt));
2582 FAIL_IF(bytes !=
sizeof(pkt));
2584 DNP3StateFree(dnp3state);
2591 static int DNP3ParserIncorrectUserData(
void)
2593 uint8_t packet_bytes[] = {
2594 0x05, 0x64, 0x08, 0xc4, 0x03, 0x00, 0x04, 0x00,
2595 0xbf, 0xe9, 0xc1, 0xc1, 0x82, 0xc5, 0xee
2601 memset(&flow, 0,
sizeof(flow));
2602 memset(&ssn, 0,
sizeof(ssn));
2604 flow.
proto = IPPROTO_TCP;
2609 STREAM_TOCLIENT, packet_bytes,
sizeof(packet_bytes));
2624 UtRegisterTest(
"DNP3ParserTestCheckCRC", DNP3ParserTestCheckCRC);
2626 DNP3ParserCheckLinkHeaderCRC);
2627 UtRegisterTest(
"DNP3CheckUserDataCRCsTest", DNP3CheckUserDataCRCsTest);
2628 UtRegisterTest(
"DNP3CalculateLinkLengthTest", DNP3CalculateLinkLengthTest);
2630 DNP3CalculateTransportLengthWithoutCRCsTest);
2632 DNP3ReassembleApplicationLayerTest01);
2635 DNP3ParserTestRequestResponse);
2637 DNP3ParserTestUnsolicitedResponseConfirm);
2638 UtRegisterTest(
"DNP3ParserTestPartialFrame", DNP3ParserTestPartialFrame);
2639 UtRegisterTest(
"DNP3ParserTestMultiFrame", DNP3ParserTestMultiFrame);
2641 UtRegisterTest(
"DNP3ParserTestParsePDU01", DNP3ParserTestParsePDU01);
2642 UtRegisterTest(
"DNP3ParserDecodeG70V3Test", DNP3ParserDecodeG70V3Test);
2644 DNP3ParserUnknownEventAlertTest);
2645 UtRegisterTest(
"DNP3ParserIncorrectUserData", DNP3ParserIncorrectUserData);