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
66 #define DNP3_MAX_APP_SEQNO 16
70 #define DNP3_LINK_HDR_LEN 5
79 #define DNP3_RESERVED_ADDR_MIN 0xfff0
80 #define DNP3_RESERVED_ADDR_MAX 0xfffb
83 #define DNP3_SRC_ADDR_MAX 0xfff0
85 #define DNP3_OBJ_TIME_SIZE 6
86 #define DNP3_OBJ_G12_V1_SIZE 11
87 #define DNP3_OBJ_G12_V2_SIZE 11
88 #define DNP3_OBJ_G12_V3_SIZE 1
91 #define DNP3_OBJ_PREFIX(x) ((x >> 4) & 0x7)
94 #define DNP3_OBJ_RANGE(x) (x & 0xf)
108 #define NEXT_TH_SEQNO(current) ((current + 1) % DNP3_MAX_TRAN_SEQNO)
111 #define NEXT_APP_SEQNO(current) ((current + 1) % DNP3_MAX_APP_SEQNO)
115 static const uint16_t crc_table[256] = {
116 0x0000, 0x365e, 0x6cbc, 0x5ae2, 0xd978, 0xef26, 0xb5c4, 0x839a,
117 0xff89, 0xc9d7, 0x9335, 0xa56b, 0x26f1, 0x10af, 0x4a4d, 0x7c13,
118 0xb26b, 0x8435, 0xded7, 0xe889, 0x6b13, 0x5d4d, 0x07af, 0x31f1,
119 0x4de2, 0x7bbc, 0x215e, 0x1700, 0x949a, 0xa2c4, 0xf826, 0xce78,
120 0x29af, 0x1ff1, 0x4513, 0x734d, 0xf0d7, 0xc689, 0x9c6b, 0xaa35,
121 0xd626, 0xe078, 0xba9a, 0x8cc4, 0x0f5e, 0x3900, 0x63e2, 0x55bc,
122 0x9bc4, 0xad9a, 0xf778, 0xc126, 0x42bc, 0x74e2, 0x2e00, 0x185e,
123 0x644d, 0x5213, 0x08f1, 0x3eaf, 0xbd35, 0x8b6b, 0xd189, 0xe7d7,
124 0x535e, 0x6500, 0x3fe2, 0x09bc, 0x8a26, 0xbc78, 0xe69a, 0xd0c4,
125 0xacd7, 0x9a89, 0xc06b, 0xf635, 0x75af, 0x43f1, 0x1913, 0x2f4d,
126 0xe135, 0xd76b, 0x8d89, 0xbbd7, 0x384d, 0x0e13, 0x54f1, 0x62af,
127 0x1ebc, 0x28e2, 0x7200, 0x445e, 0xc7c4, 0xf19a, 0xab78, 0x9d26,
128 0x7af1, 0x4caf, 0x164d, 0x2013, 0xa389, 0x95d7, 0xcf35, 0xf96b,
129 0x8578, 0xb326, 0xe9c4, 0xdf9a, 0x5c00, 0x6a5e, 0x30bc, 0x06e2,
130 0xc89a, 0xfec4, 0xa426, 0x9278, 0x11e2, 0x27bc, 0x7d5e, 0x4b00,
131 0x3713, 0x014d, 0x5baf, 0x6df1, 0xee6b, 0xd835, 0x82d7, 0xb489,
132 0xa6bc, 0x90e2, 0xca00, 0xfc5e, 0x7fc4, 0x499a, 0x1378, 0x2526,
133 0x5935, 0x6f6b, 0x3589, 0x03d7, 0x804d, 0xb613, 0xecf1, 0xdaaf,
134 0x14d7, 0x2289, 0x786b, 0x4e35, 0xcdaf, 0xfbf1, 0xa113, 0x974d,
135 0xeb5e, 0xdd00, 0x87e2, 0xb1bc, 0x3226, 0x0478, 0x5e9a, 0x68c4,
136 0x8f13, 0xb94d, 0xe3af, 0xd5f1, 0x566b, 0x6035, 0x3ad7, 0x0c89,
137 0x709a, 0x46c4, 0x1c26, 0x2a78, 0xa9e2, 0x9fbc, 0xc55e, 0xf300,
138 0x3d78, 0x0b26, 0x51c4, 0x679a, 0xe400, 0xd25e, 0x88bc, 0xbee2,
139 0xc2f1, 0xf4af, 0xae4d, 0x9813, 0x1b89, 0x2dd7, 0x7735, 0x416b,
140 0xf5e2, 0xc3bc, 0x995e, 0xaf00, 0x2c9a, 0x1ac4, 0x4026, 0x7678,
141 0x0a6b, 0x3c35, 0x66d7, 0x5089, 0xd313, 0xe54d, 0xbfaf, 0x89f1,
142 0x4789, 0x71d7, 0x2b35, 0x1d6b, 0x9ef1, 0xa8af, 0xf24d, 0xc413,
143 0xb800, 0x8e5e, 0xd4bc, 0xe2e2, 0x6178, 0x5726, 0x0dc4, 0x3b9a,
144 0xdc4d, 0xea13, 0xb0f1, 0x86af, 0x0535, 0x336b, 0x6989, 0x5fd7,
145 0x23c4, 0x159a, 0x4f78, 0x7926, 0xfabc, 0xcce2, 0x9600, 0xa05e,
146 0x6e26, 0x5878, 0x029a, 0x34c4, 0xb75e, 0x8100, 0xdbe2, 0xedbc,
147 0x91af, 0xa7f1, 0xfd13, 0xcb4d, 0x48d7, 0x7e89, 0x246b, 0x1235
157 static uint16_t DNP3ComputeCRC(
const uint8_t *buf, uint32_t
len)
159 const uint8_t *
byte = buf;
164 idx = (
crc ^ *byte) & 0xff;
165 crc = (crc_table[idx] ^ (
crc >> 8)) & 0xffff;
169 return ~
crc & 0xffff;
180 static int DNP3CheckCRC(
const uint8_t *block, uint32_t
len)
182 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
195 if (((
crc & 0xff) == block[crc_offset]) &&
196 ((
crc >> 8) == block[crc_offset + 1])) {
210 static int DNP3CheckLinkHeaderCRC(
const DNP3LinkHeader *header)
212 return DNP3CheckCRC((uint8_t *)header,
sizeof(DNP3LinkHeader));
223 static int DNP3CheckUserDataCRCs(
const uint8_t *data, uint32_t
len)
236 if (!DNP3CheckCRC(data +
offset, block_size)) {
252 static int DNP3CheckStartBytes(
const DNP3LinkHeader *header)
259 #define DNP3_BANNER "DNP3"
269 static int DNP3ContainsBanner(
const uint8_t *input, uint32_t
len)
277 static uint16_t DNP3ProbingParser(
Flow *f, uint8_t direction,
278 const uint8_t *input, uint32_t
len,
281 const DNP3LinkHeader *
const hdr = (
const DNP3LinkHeader *)input;
282 const bool toserver = (direction & STREAM_TOSERVER) != 0;
285 if (DNP3ContainsBanner(input,
len)) {
287 bool is_banner =
true;
289 for (uint32_t i = 0; i <
len && i < 0x100; i++) {
290 if (!isprint(input[i])) {
297 *rdir = STREAM_TOCLIENT;
304 if (
len <
sizeof(DNP3LinkHeader)) {
305 SCLogDebug(
"Length too small to be a DNP3 header.");
310 if (!DNP3CheckStartBytes(hdr)) {
317 SCLogDebug(
"Packet too small to be a valid DNP3 fragment.");
323 *rdir = toserver ? STREAM_TOCLIENT : STREAM_TOSERVER;
336 static int DNP3CalculateTransportLengthWithoutCRCs(uint32_t input_len)
379 static int DNP3ReassembleApplicationLayer(
const uint8_t *input,
380 uint32_t input_len, uint8_t **output, uint32_t *output_len)
382 int len = DNP3CalculateTransportLengthWithoutCRCs(input_len);
394 if (*output == NULL) {
401 uint8_t *ptr =
SCRealloc(*output, (
size_t)(*output_len +
len));
408 int offset = 0, block_size;
409 while ((uint32_t)
offset < input_len) {
414 block_size = input_len -
offset;
439 memcpy(*output + *output_len, input +
offset,
454 static void *DNP3StateAlloc(
void *orig_state,
AppProto proto_orig)
473 static void DNP3SetEvent(
DNP3State *dnp3, uint8_t event)
475 if (dnp3 && dnp3->
curr) {
480 SCLogWarning(
"Failed to set event, state or tx pointer was NULL.");
536 static uint32_t DNP3CalculateLinkLength(uint8_t length)
538 uint32_t frame_len = 0;
556 return frame_len +
sizeof(DNP3LinkHeader);
566 static int DNP3IsUserData(
const DNP3LinkHeader *header)
585 static int DNP3HasUserData(
const DNP3LinkHeader *header, uint8_t direction)
587 if (direction == STREAM_TOSERVER) {
589 sizeof(DNP3ApplicationHeader);
593 sizeof(DNP3ApplicationHeader) +
sizeof(DNP3InternalInd);
600 static void DNP3BufferReset(
DNP3Buffer *buffer)
615 static int DNP3BufferAdd(
DNP3Buffer *buffer,
const uint8_t *data, uint32_t
len)
617 if (buffer->
size == 0) {
646 static void DNP3BufferTrim(
DNP3Buffer *buffer)
649 DNP3BufferReset(buffer);
651 else if (buffer->
offset > 0) {
662 static void DNP3ObjectFree(
DNP3Object *
object)
664 if (object->
points != NULL) {
681 if (object->
points == NULL) {
682 DNP3ObjectFree(
object);
703 static int DNP3DecodeApplicationObjects(
DNP3Transaction *tx,
const uint8_t *buf,
704 uint32_t
len, DNP3ObjectList *objects)
708 if (buf == NULL ||
len == 0) {
715 if (
len <
sizeof(DNP3ObjHeader)) {
718 DNP3ObjHeader *header = (DNP3ObjHeader *)buf;
719 offset +=
sizeof(DNP3ObjHeader);
727 object->group = header->group;
728 object->variation = header->variation;
729 object->qualifier = header->qualifier;
739 if (
offset + (
sizeof(uint8_t) * 2) >
len) {
742 goto not_enough_data;
744 object->start = buf[
offset++];
745 object->stop = buf[
offset++];
746 object->count =
object->stop -
object->start + 1;
753 if (
offset + (
sizeof(uint16_t) * 2) >
len) {
756 goto not_enough_data;
759 offset +=
sizeof(uint16_t);
761 offset +=
sizeof(uint16_t);
762 object->count =
object->stop -
object->start + 1;
769 if (
offset + (
sizeof(uint32_t) * 2) >
len) {
772 goto not_enough_data;
775 offset +=
sizeof(uint32_t);
777 offset +=
sizeof(uint32_t);
778 object->count =
object->stop -
object->start + 1;
789 goto not_enough_data;
791 object->count = buf[
offset];
792 offset +=
sizeof(uint8_t);
798 goto not_enough_data;
801 offset +=
sizeof(uint16_t);
808 goto not_enough_data;
811 offset +=
sizeof(uint32_t);
818 goto not_enough_data;
820 object->count = *(uint8_t *)(buf +
offset);
821 offset +=
sizeof(uint8_t);
864 static void DNP3HandleUserDataRequest(
DNP3State *dnp3,
const uint8_t *input,
869 DNP3ApplicationHeader *ah;
872 lh = (DNP3LinkHeader *)input;
874 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
875 input_len -
sizeof(DNP3LinkHeader))) {
879 th = input[
sizeof(DNP3LinkHeader)];
883 if (ttx->lh.src == lh->src && ttx->lh.dst == lh->dst && ttx->is_request && !ttx->done &&
899 ah = (DNP3ApplicationHeader *)(input +
sizeof(DNP3LinkHeader) +
908 tx = DNP3TxAlloc(dnp3,
true);
917 if (!DNP3ReassembleApplicationLayer(input +
sizeof(DNP3LinkHeader),
933 if (DNP3DecodeApplicationObjects(tx, tx->
buffer +
sizeof(DNP3ApplicationHeader),
939 static void DNP3HandleUserDataResponse(
DNP3State *dnp3,
const uint8_t *input,
944 DNP3ApplicationHeader *ah;
945 DNP3InternalInd *iin;
949 lh = (DNP3LinkHeader *)input;
950 offset +=
sizeof(DNP3LinkHeader);
952 if (!DNP3CheckUserDataCRCs(input +
offset, input_len -
offset)) {
960 if (ttx->lh.src == lh->src && ttx->lh.dst == lh->dst && !ttx->is_request &&
976 ah = (DNP3ApplicationHeader *)(input +
offset);
977 offset +=
sizeof(DNP3ApplicationHeader);
978 iin = (DNP3InternalInd *)(input +
offset);
980 tx = DNP3TxAlloc(dnp3,
false);
992 if (!DNP3ReassembleApplicationLayer(input +
sizeof(DNP3LinkHeader),
1004 offset =
sizeof(DNP3ApplicationHeader) +
sizeof(DNP3InternalInd);
1005 if (DNP3DecodeApplicationObjects(
1017 static int DNP3HandleRequestLinkLayer(
DNP3State *dnp3,
const uint8_t *input,
1021 uint32_t processed = 0;
1026 if (input_len <
sizeof(DNP3LinkHeader)) {
1030 DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1032 if (!DNP3CheckStartBytes(header)) {
1036 if (!DNP3CheckLinkHeaderCRC(header)) {
1041 uint32_t frame_len = DNP3CalculateLinkLength(header->len);
1042 if (frame_len == 0) {
1046 if (input_len < frame_len) {
1052 if (!DNP3IsUserData(header)) {
1058 if (!DNP3HasUserData(header, STREAM_TOSERVER)) {
1063 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
1064 frame_len -
sizeof(DNP3LinkHeader))) {
1069 DNP3HandleUserDataRequest(dnp3, input, frame_len);
1074 input_len -= frame_len;
1075 processed += frame_len;
1094 StreamSlice stream_slice,
void *local_data)
1101 const uint8_t *input = StreamSliceGetData(&stream_slice);
1102 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1104 if (input_len == 0) {
1109 if (!DNP3BufferAdd(buffer, input, input_len)) {
1112 processed = DNP3HandleRequestLinkLayer(dnp3,
1115 if (processed < 0) {
1118 buffer->
offset += processed;
1119 DNP3BufferTrim(buffer);
1122 processed = DNP3HandleRequestLinkLayer(dnp3, input, input_len);
1123 if (processed < 0) {
1124 SCLogDebug(
"Failed to process request link layer.");
1129 input_len -= processed;
1133 if (!DNP3BufferAdd(buffer, input, input_len)) {
1143 DNP3BufferReset(buffer);
1153 static int DNP3HandleResponseLinkLayer(
DNP3State *dnp3,
const uint8_t *input,
1157 uint32_t processed = 0;
1162 if (input_len <
sizeof(DNP3LinkHeader)) {
1166 DNP3LinkHeader *header = (DNP3LinkHeader *)input;
1168 if (!DNP3CheckStartBytes(header)) {
1172 if (!DNP3CheckLinkHeaderCRC(header)) {
1178 uint32_t frame_len = DNP3CalculateLinkLength(header->len);
1179 if (frame_len == 0) {
1183 if (input_len < frame_len) {
1189 if (!DNP3IsUserData(header)) {
1195 if (!DNP3HasUserData(header, STREAM_TOCLIENT)) {
1200 if (!DNP3CheckUserDataCRCs(input +
sizeof(DNP3LinkHeader),
1201 frame_len -
sizeof(DNP3LinkHeader))) {
1206 DNP3HandleUserDataResponse(dnp3, input, frame_len);
1211 input_len -= frame_len;
1212 processed += frame_len;
1232 StreamSlice stream_slice,
void *local_data)
1240 const uint8_t *input = StreamSliceGetData(&stream_slice);
1241 uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
1244 if (!DNP3BufferAdd(buffer, input, input_len)) {
1247 processed = DNP3HandleResponseLinkLayer(dnp3,
1250 if (processed < 0) {
1253 buffer->
offset += processed;
1254 DNP3BufferTrim(buffer);
1259 if (DNP3ContainsBanner(input, input_len)) {
1263 processed = DNP3HandleResponseLinkLayer(dnp3, input, input_len);
1264 if (processed < 0) {
1268 input_len -= processed;
1272 if (!DNP3BufferAdd(buffer, input, input_len)) {
1284 DNP3BufferReset(buffer);
1288 static void *DNP3GetTx(
void *alstate, uint64_t tx_id)
1293 uint64_t tx_num = tx_id + 1;
1300 if (tx_num != tx->
tx_num) {
1309 static uint64_t DNP3GetTxCnt(
void *state)
1312 uint64_t count = ((uint64_t)((
DNP3State *)state)->transaction_max);
1319 static void DNP3TxFreeObjectList(DNP3ObjectList *objects)
1325 DNP3ObjectFree(
object);
1336 if (tx->
buffer != NULL) {
1342 if (tx->
tx_data.de_state != NULL) {
1346 DNP3TxFreeObjectList(&tx->
objects);
1358 static void DNP3StateTxFree(
void *state, uint64_t tx_id)
1363 uint64_t tx_num = tx_id + 1;
1367 if (tx->
tx_num != tx_num) {
1371 if (tx == dnp3->
curr) {
1375 if (tx->
tx_data.events != NULL) {
1400 static void DNP3StateFree(
void *state)
1405 if (state != NULL) {
1406 while ((tx =
TAILQ_FIRST(&dnp3->tx_list)) != NULL) {
1424 static int DNP3GetAlstateProgress(
void *tx, uint8_t direction)
1433 SCLogDebug(
"flooded: returning tx as done.");
1446 static int DNP3StateGetEventInfo(
const char *event_name,
int *event_id,
1447 AppLayerEventType *event_type)
1450 if (*event_id == -1) {
1452 "the DNP3 enum event map table.",
1457 *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
1465 static int DNP3StateGetEventInfoById(
int event_id,
const char **event_name,
1466 AppLayerEventType *event_type)
1469 if (*event_name == NULL) {
1471 "the DNP3 enum event map table.",
1476 *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
1487 static AppLayerStateData *DNP3GetStateData(
void *vstate)
1500 switch (prefix_code) {
1511 static AppLayerGetTxIterTuple DNP3GetTxIterator(
const uint8_t ipproto,
const AppProto alproto,
1515 AppLayerGetTxIterTuple no_tuple = { NULL, 0,
false };
1518 if (state->
un.
ptr == NULL) {
1524 while (tx_ptr->
tx_num < min_tx_id + 1) {
1530 if (tx_ptr->
tx_num >= max_tx_id + 1) {
1534 AppLayerGetTxIterTuple tuple = {
1536 .tx_id = tx_ptr->
tx_num - 1,
1537 .has_next = (state->
un.
ptr != NULL),
1552 const char *proto_name =
"dnp3";
1559 ALPROTO_DNP3, 0,
sizeof(DNP3LinkHeader), STREAM_TOSERVER,
1560 DNP3ProbingParser, DNP3ProbingParser);
1565 DNP3ProbingParser, DNP3ProbingParser)) {
1571 SCLogConfig(
"Protocol detection and parser disabled for DNP3.");
1585 DNP3StateAlloc, DNP3StateFree);
1594 DNP3GetAlstateProgress);
1598 DNP3StateGetEventInfo);
1600 DNP3StateGetEventInfoById);
1608 "Protocol detection still on.", proto_name);
1627 static void DNP3FixCrc(uint8_t *data, uint32_t
len)
1629 uint32_t block_size;
1637 uint16_t
crc = DNP3ComputeCRC(data, block_size);
1638 data[block_size + 1] = (
crc >> 8) & 0xff;
1639 data[block_size] =
crc & 0xff;
1648 static int DNP3ParserTestCheckCRC(
void)
1650 uint8_t request[] = {
1652 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1659 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1660 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1664 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1668 FAIL_IF(!DNP3CheckCRC(request,
sizeof(DNP3LinkHeader)));
1671 FAIL_IF(!DNP3CheckCRC(request +
sizeof(DNP3LinkHeader),
1674 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1677 FAIL_IF(DNP3CheckCRC(request,
sizeof(DNP3LinkHeader)));
1681 request[
sizeof(DNP3LinkHeader) + 3]++;
1682 FAIL_IF(DNP3CheckCRC(request +
sizeof(DNP3LinkHeader),
1692 static int DNP3CheckUserDataCRCsTest(
void)
1695 uint8_t data_valid[] = {
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 0xff, 0xc9, 0x05, 0x0c,
1709 0x01, 0x28, 0x01, 0x00,
1710 0x00, 0x00, 0x01, 0x01,
1711 0x01, 0x00, 0x00, 0x00,
1714 0x00, 0x00, 0x00, 0x00,
1718 FAIL_IF(!DNP3CheckUserDataCRCs(data_valid,
sizeof(data_valid)));
1720 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1722 uint8_t data_invalid[] = {
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 0xff, 0xc9, 0x05, 0x0c,
1736 0x01, 0x28, 0x01, 0x00,
1737 0x00, 0x00, 0x01, 0x01,
1738 0x01, 0x00, 0x00, 0x00,
1741 0x00, 0x00, 0x00, 0x00,
1745 FAIL_IF(DNP3CheckUserDataCRCs(data_invalid,
sizeof(data_invalid)));
1748 uint8_t one_byte_nocrc[] = { 0x01 };
1749 FAIL_IF(DNP3CheckUserDataCRCs(one_byte_nocrc,
sizeof(one_byte_nocrc)));
1752 uint8_t two_byte_nocrc[] = { 0x01, 0x02 };
1753 FAIL_IF(DNP3CheckUserDataCRCs(two_byte_nocrc,
sizeof(two_byte_nocrc)));
1757 uint8_t three_bytes_good_crc[] = { 0x00, 0x00, 0x00 };
1758 *(uint16_t *)(three_bytes_good_crc + 1) = DNP3ComputeCRC(
1759 three_bytes_good_crc, 1);
1760 FAIL_IF(!DNP3CheckUserDataCRCs(three_bytes_good_crc,
1761 sizeof(three_bytes_good_crc)));
1773 static int DNP3CalculateLinkLengthTest(
void)
1776 FAIL_IF(DNP3CalculateLinkLength(0) != 0);
1777 FAIL_IF(DNP3CalculateLinkLength(1) != 0);
1778 FAIL_IF(DNP3CalculateLinkLength(2) != 0);
1779 FAIL_IF(DNP3CalculateLinkLength(3) != 0);
1780 FAIL_IF(DNP3CalculateLinkLength(4) != 0);
1783 FAIL_IF(DNP3CalculateLinkLength(5) != 10);
1786 FAIL_IF(DNP3CalculateLinkLength(21) != 28);
1789 FAIL_IF(DNP3CalculateLinkLength(37) != 46);
1793 FAIL_IF(DNP3CalculateLinkLength(38) != 49);
1796 FAIL_IF(DNP3CalculateLinkLength(255) != 292);
1805 static int DNP3CalculateTransportLengthWithoutCRCsTest(
void)
1807 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(0) != -1);
1808 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(1) != -1);
1809 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(2) != 0);
1810 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(3) != 1);
1811 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(16) != 14);
1812 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(17) != 15);
1813 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(18) != 16);
1816 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(19) != -1);
1820 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(20) != 16);
1822 FAIL_IF(DNP3CalculateTransportLengthWithoutCRCs(21) != 17);
1830 static int DNP3ParserCheckLinkHeaderCRC(
void)
1833 uint8_t request[] = {
1835 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
1842 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
1843 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
1844 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1847 DNP3LinkHeader *header = (DNP3LinkHeader *)request;
1848 FAIL_IF(!DNP3CheckLinkHeaderCRC(header));
1850 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1853 FAIL_IF(DNP3CheckLinkHeaderCRC(header));
1862 static int DNP3ReassembleApplicationLayerTest01(
void)
1864 uint32_t reassembled_len = 0;
1865 uint8_t *output = NULL;
1867 uint8_t payload[] = {
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 0xff, 0xc9, 0x05, 0x0c,
1882 0x01, 0x28, 0x01, 0x00,
1883 0x00, 0x00, 0x01, 0x01,
1884 0x01, 0x00, 0x00, 0x00,
1887 0x00, 0x00, 0x00, 0x00,
1892 uint8_t expected[] = {
1894 0x01, 0x28, 0x01, 0x00,
1895 0x00, 0x00, 0x01, 0x01,
1896 0x01, 0x00, 0x00, 0x00,
1898 0xff, 0xc9, 0x05, 0x0c,
1899 0x01, 0x28, 0x01, 0x00,
1900 0x00, 0x00, 0x01, 0x01,
1901 0x01, 0x00, 0x00, 0x00,
1903 0xff, 0xc9, 0x05, 0x0c,
1904 0x01, 0x28, 0x01, 0x00,
1905 0x00, 0x00, 0x01, 0x01,
1906 0x01, 0x00, 0x00, 0x00,
1908 0x00, 0x00, 0x00, 0x00,
1914 FAIL_IF(!DNP3ReassembleApplicationLayer(payload,
1915 sizeof(payload), &output, &reassembled_len));
1917 FAIL_IF(reassembled_len !=
sizeof(expected));
1918 FAIL_IF(memcmp(expected, output, reassembled_len));
1922 reassembled_len = 0;
1924 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 1, &output,
1927 FAIL_IF(reassembled_len != 0);
1930 reassembled_len = 0;
1932 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 2, &output,
1935 FAIL_IF(reassembled_len != 0);
1939 reassembled_len = 0;
1941 FAIL_IF(DNP3ReassembleApplicationLayer(payload, 3, &output,
1944 FAIL_IF(reassembled_len != 0);
1947 reassembled_len = 0;
1949 FAIL_IF(!DNP3ReassembleApplicationLayer(payload, 4, &output,
1952 FAIL_IF(reassembled_len != 1);
1955 uint8_t short_payload1[] = {
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,
1969 0xff, 0xc9, 0x05, 0x0c,
1970 0x01, 0x28, 0x01, 0x00,
1971 0x00, 0x00, 0x01, 0x01,
1972 0x01, 0x00, 0x00, 0x00,
1977 reassembled_len = 0;
1978 FAIL_IF(DNP3ReassembleApplicationLayer(short_payload1,
1979 sizeof(short_payload1), &output, &reassembled_len));
1982 uint8_t short_payload2[] = {
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,
1996 0xff, 0xc9, 0x05, 0x0c,
1997 0x01, 0x28, 0x01, 0x00,
1998 0x00, 0x00, 0x01, 0x01,
1999 0x01, 0x00, 0x00, 0x00,
2004 reassembled_len = 0;
2005 FAIL_IF(DNP3ReassembleApplicationLayer(short_payload2,
2006 sizeof(short_payload2), &output, &reassembled_len));
2014 static int DNP3ProbingParserTest(
void)
2017 0x05, 0x64, 0x05, 0xc9, 0x03, 0x00, 0x04, 0x00,
2023 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt,
sizeof(pkt), &rdir) !=
ALPROTO_DNP3);
2026 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, pkt,
sizeof(DNP3LinkHeader) - 1, &rdir) !=
ALPROTO_UNKNOWN);
2040 char mybanner[] =
"Welcome to DNP3 SCADA.";
2041 FAIL_IF(DNP3ProbingParser(NULL, STREAM_TOSERVER, (uint8_t *)mybanner,
sizeof(mybanner) - 1,
2043 FAIL_IF(rdir != STREAM_TOCLIENT);
2051 static int DNP3ParserTestRequestResponse(
void)
2055 uint8_t request[] = {
2057 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2064 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2065 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2066 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2069 uint8_t response[] = {
2071 0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2078 0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2079 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2080 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2088 memset(&flow, 0,
sizeof(flow));
2089 memset(&ssn, 0,
sizeof(ssn));
2092 flow.
proto = IPPROTO_TCP;
2099 STREAM_TOSERVER, request,
sizeof(request)));
2115 STREAM_TOCLIENT, response,
sizeof(response)));
2134 static int DNP3ParserTestUnsolicitedResponseConfirm(
void)
2139 uint8_t response[] = {
2140 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2141 0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2142 0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2143 0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9
2147 uint8_t confirm[] = {
2148 0x05, 0x64, 0x08, 0xc4, 0x02, 0x00,
2149 0x01, 0x00, 0xd3, 0xb7, 0xc0, 0xda, 0x00, 0x6a,
2157 memset(&flow, 0,
sizeof(flow));
2158 memset(&ssn, 0,
sizeof(ssn));
2161 flow.
proto = IPPROTO_TCP;
2168 STREAM_TOCLIENT, response,
sizeof(response)));
2183 STREAM_TOSERVER, confirm,
sizeof(confirm)));
2204 static int DNP3ParserTestFlooded(
void)
2208 uint8_t request[] = {
2210 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2217 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2218 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2219 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2226 memset(&flow, 0,
sizeof(flow));
2227 memset(&ssn, 0,
sizeof(ssn));
2230 flow.
proto = IPPROTO_TCP;
2237 STREAM_TOSERVER, request,
sizeof(request)));
2251 FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2256 STREAM_TOSERVER, request,
sizeof(request)));
2260 FAIL_IF_NOT(DNP3GetAlstateProgress(tx, STREAM_TOSERVER));
2265 STREAM_TOSERVER, request,
sizeof(request)));
2270 FAIL_IF(!DNP3GetAlstateProgress(tx, 0));
2285 static int DNP3ParserTestPartialFrame(
void)
2291 uint8_t request_partial1[] = {
2293 0x05, 0x64, 0x1a, 0xc4, 0x02, 0x00, 0x01, 0x00,
2300 0xc9, 0x05, 0x0c, 0x01, 0x28, 0x01, 0x00, 0x00,
2303 uint8_t request_partial2[] = {
2305 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x72,
2306 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
2309 uint8_t response_partial1[] = {
2311 0x05, 0x64, 0x1c, 0x44, 0x01, 0x00, 0x02, 0x00,
2318 0xc9, 0x81, 0x00, 0x00, 0x0c, 0x01, 0x28, 0x01,
2321 uint8_t response_partial2[] = {
2322 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7a,
2323 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2331 memset(&flow, 0,
sizeof(flow));
2332 memset(&ssn, 0,
sizeof(ssn));
2334 flow.
proto = IPPROTO_TCP;
2342 STREAM_TOSERVER, request_partial1,
sizeof(request_partial1));
2352 sizeof(request_partial1)));
2356 FAIL_IF(DNP3GetTx(state, 0) != NULL);
2361 STREAM_TOSERVER, request_partial2,
sizeof(request_partial2));
2371 tx = DNP3GetTx(state, 0);
2382 STREAM_TOCLIENT, response_partial1,
sizeof(response_partial1));
2387 tx = DNP3GetTx(state, 1);
2393 STREAM_TOCLIENT, response_partial2,
sizeof(response_partial2));
2402 tx = DNP3GetTx(state, 1);
2416 static int DNP3ParserTestMultiFrame(
void)
2421 uint8_t unsol_response1[] = {
2422 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2423 0x89, 0xe5, 0xc4, 0xfa, 0x82, 0x00, 0x00, 0x02,
2424 0x02, 0x17, 0x01, 0x01, 0x81, 0xa7, 0x75, 0xd8,
2425 0x32, 0x4c, 0x81, 0x3e, 0x01, 0xa1, 0xc9,
2429 uint8_t unsol_response2[] = {
2430 0x05, 0x64, 0x16, 0x44, 0x01, 0x00, 0x02, 0x00,
2431 0x89, 0xe5, 0xc5, 0xfb, 0x82, 0x00, 0x00, 0x02,
2432 0x02, 0x17, 0x01, 0x0c, 0x01, 0xd8, 0x75, 0xd8,
2433 0x32, 0x4c, 0xc9, 0x3c, 0x01, 0xa1, 0xc9,
2436 uint8_t combined[
sizeof(unsol_response1) +
sizeof(unsol_response2)];
2437 memcpy(combined, unsol_response1,
sizeof(unsol_response1));
2438 memcpy(combined +
sizeof(unsol_response1), unsol_response2,
2439 sizeof(unsol_response2));
2446 memset(&flow, 0,
sizeof(flow));
2447 memset(&ssn, 0,
sizeof(ssn));
2449 flow.
proto = IPPROTO_TCP;
2455 STREAM_TOCLIENT, combined,
sizeof(combined));
2477 static int DNP3ParserTestParsePDU01(
void)
2481 const uint8_t pkt[] = {
2483 0x0b, 0xc4, 0x17, 0x00, 0xef, 0xff, 0xc4, 0x8f,
2484 0xe1, 0xc8, 0x01, 0x01, 0x00, 0x06, 0x77, 0x6e
2488 int pdus = DNP3HandleRequestLinkLayer(dnp3state, pkt,
sizeof(pkt));
2498 DNP3StateFree(dnp3state);
2505 static int DNP3ParserDecodeG70V3Test(
void)
2507 const uint8_t pkt[] = {
2509 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00, 0xc7, 0xee,
2510 0xc7, 0xc9, 0x1b, 0x46, 0x03, 0x5b, 0x01, 0x55,
2511 0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2512 0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2513 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2514 0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2515 0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2516 0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2517 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2518 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2519 0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2520 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2521 0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2522 0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2528 int bytes = DNP3HandleRequestLinkLayer(dnp3state, pkt,
sizeof(pkt));
2529 FAIL_IF(bytes !=
sizeof(pkt));
2548 "C:/temp/DNPDeviceConfiguration written to Remote Device.xml") == 0);
2549 DNP3StateFree(dnp3state);
2556 static int DNP3ParserUnknownEventAlertTest(
void)
2560 0x05, 0x64, 0x63, 0xc4, 0x04, 0x00, 0x03, 0x00,
2570 0x00, 0x1a, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00,
2571 0x9e, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2573 0x00, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x00, 0x43,
2574 0x3a, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x2f, 0x44,
2575 0x4e, 0x50, 0x44, 0x65, 0x67, 0x7d, 0x76, 0x69,
2576 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
2577 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x93, 0x0c,
2578 0x6e, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
2579 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x52, 0x65, 0x6d,
2580 0x35, 0x20, 0x6f, 0x74, 0x65, 0x20, 0x44, 0x65,
2581 0x76, 0x69, 0x63, 0x65, 0x2e, 0x78, 0x6d, 0x6c,
2585 DNP3FixCrc(pkt + 10,
sizeof(pkt) - 10);
2589 int bytes = DNP3HandleRequestLinkLayer(dnp3state, pkt,
sizeof(pkt));
2590 FAIL_IF(bytes !=
sizeof(pkt));
2592 DNP3StateFree(dnp3state);
2599 static int DNP3ParserIncorrectUserData(
void)
2601 uint8_t packet_bytes[] = {
2602 0x05, 0x64, 0x08, 0xc4, 0x03, 0x00, 0x04, 0x00,
2603 0xbf, 0xe9, 0xc1, 0xc1, 0x82, 0xc5, 0xee
2609 memset(&flow, 0,
sizeof(flow));
2610 memset(&ssn, 0,
sizeof(ssn));
2612 flow.
proto = IPPROTO_TCP;
2617 STREAM_TOCLIENT, packet_bytes,
sizeof(packet_bytes));
2632 UtRegisterTest(
"DNP3ParserTestCheckCRC", DNP3ParserTestCheckCRC);
2634 DNP3ParserCheckLinkHeaderCRC);
2635 UtRegisterTest(
"DNP3CheckUserDataCRCsTest", DNP3CheckUserDataCRCsTest);
2636 UtRegisterTest(
"DNP3CalculateLinkLengthTest", DNP3CalculateLinkLengthTest);
2638 DNP3CalculateTransportLengthWithoutCRCsTest);
2640 DNP3ReassembleApplicationLayerTest01);
2643 DNP3ParserTestRequestResponse);
2645 DNP3ParserTestUnsolicitedResponseConfirm);
2646 UtRegisterTest(
"DNP3ParserTestPartialFrame", DNP3ParserTestPartialFrame);
2647 UtRegisterTest(
"DNP3ParserTestMultiFrame", DNP3ParserTestMultiFrame);
2649 UtRegisterTest(
"DNP3ParserTestParsePDU01", DNP3ParserTestParsePDU01);
2650 UtRegisterTest(
"DNP3ParserDecodeG70V3Test", DNP3ParserDecodeG70V3Test);
2652 DNP3ParserUnknownEventAlertTest);
2653 UtRegisterTest(
"DNP3ParserIncorrectUserData", DNP3ParserIncorrectUserData);