Files
bacnet_stack/test/bacnet/ptransfer/src/main.c
T
Steve Karg a70ce07507 Secure BACnet decoders and service requests (#1244)
* Secured BACnetAssignedAccessRights decoder.

* Secured BACnetPropertyState decoder.

* Secured BACnetCredentialAuthenticationFactor decoder.

* Secured BACnetEventState change-of-state [1] SEQUENCE decoder.

* Secured I-Have-Request service decoder.

* Secured Add/Remove ListElement service request decoder.

* Secured ConfirmedPrivateTransfer-Request and UnconfirmedPrivateTransfer-Request decoders.

* Secured ReadPropertyMultiple-Request and -Ack decoders.

* Secured TimeSynchronization-Request decoder.

* Secured WritePropertyMultiple service decoders

* Secured Trend Log object TL_fetch_property() function.

* Secured ReadProperty-Ack decider,

* Refactor BACnet time sync recipient handling by moving timesync linked list structure into bacdest where the recipient encoder and decoder already existed.

* Secured decoding of BACnetPropertyState.

* Secured decoding in the LifeSafetyOperation-Request service.

* Secured BACnetAuthenticationFactor decoding in the Credential Data Input object.

* Fixed WriteProperty decoder to avoid read buffer overrun.  Improved WriteProperty error reporting by adding specific reject codes during decoding similar to WritePropertyMultiple. Deduplicated the WriteProperty handling of abort, reject and error codes.

* Added BACNET_STACK_DEPRECATED_DISABLE guards around all of the deprecated decoding functions to ensure they are not used except intentionally for legacy code bases.

* Changed version to 1.5.0.rc5 for security fix tracking in branch.
2026-02-26 10:48:25 -06:00

378 lines
12 KiB
C

/**
* @file
* @brief test BACnet PrivateTransfer services encoding and decoding API
* @author Steve Karg <skarg@users.sourceforge.net>
* @date 2004
* @copyright SPDX-License-Identifier: MIT
*/
#include <zephyr/ztest.h>
#include <bacnet/bacapp.h>
#include <bacnet/bacenum.h>
#include <bacnet/ptransfer.h>
/**
* @addtogroup bacnet_tests
* @{
*/
/**
* @brief Test
*/
static int ptransfer_decode_apdu(
uint8_t *apdu,
unsigned apdu_size,
uint8_t *invoke_id,
BACNET_PRIVATE_TRANSFER_DATA *private_data)
{
int len = 0, apdu_len = 0;
if (!apdu) {
return -1;
}
/* optional checking - most likely was already done prior to this call */
if (apdu[0] != PDU_TYPE_CONFIRMED_SERVICE_REQUEST) {
return -1;
}
/* apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU); */
/* invoke id - filled in by net layer */
*invoke_id = apdu[2];
if (apdu[3] != SERVICE_CONFIRMED_PRIVATE_TRANSFER) {
return -1;
}
apdu_len = 4;
if (apdu_size > apdu_len) {
len = ptransfer_decode_service_request(
&apdu[apdu_len], apdu_size - apdu_len, private_data);
if (len < 0) {
return -1;
}
apdu_len += len;
}
return apdu_len;
}
static int uptransfer_decode_apdu(
uint8_t *apdu,
unsigned apdu_size,
BACNET_PRIVATE_TRANSFER_DATA *private_data)
{
int len = 0;
unsigned apdu_len = 0;
if (!apdu) {
return -1;
}
/* optional checking - most likely was already done prior to this call */
if (apdu[0] != PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST) {
return -1;
}
if (apdu[1] != SERVICE_UNCONFIRMED_PRIVATE_TRANSFER) {
return -1;
}
apdu_len = 2;
if (apdu_size > apdu_len) {
len = ptransfer_decode_service_request(
&apdu[apdu_len], apdu_size - apdu_len, private_data);
if (len < 0) {
return -1;
}
apdu_len += len;
}
return apdu_len;
}
static int ptransfer_ack_decode_apdu(
uint8_t *apdu,
int apdu_len, /* total length of the apdu */
uint8_t *invoke_id,
BACNET_PRIVATE_TRANSFER_DATA *private_data)
{
int len = 0;
int offset = 0;
if (!apdu) {
return -1;
}
/* optional checking - most likely was already done prior to this call */
if (apdu[0] != PDU_TYPE_COMPLEX_ACK) {
return -1;
}
*invoke_id = apdu[1];
if (apdu[2] != SERVICE_CONFIRMED_PRIVATE_TRANSFER) {
return -1;
}
offset = 3;
if (apdu_len > offset) {
len = ptransfer_decode_service_request(
&apdu[offset], apdu_len - offset, private_data);
}
return len;
}
static int ptransfer_error_decode_apdu(
uint8_t *apdu,
int apdu_len, /* total length of the apdu */
uint8_t *invoke_id,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code,
BACNET_PRIVATE_TRANSFER_DATA *private_data)
{
int len = 0;
int offset = 0;
if (!apdu) {
return -1;
}
/* optional checking - most likely was already done prior to this call */
if (apdu[0] != PDU_TYPE_ERROR) {
return -1;
}
*invoke_id = apdu[1];
if (apdu[2] != SERVICE_CONFIRMED_PRIVATE_TRANSFER) {
return -1;
}
offset = 3;
if (apdu_len > offset) {
len = ptransfer_error_decode_service_request(
&apdu[offset], apdu_len - offset, error_class, error_code,
private_data);
}
return len;
}
#if defined(CONFIG_ZTEST_NEW_API)
ZTEST(ptransfer_tests, test_Private_Transfer_Ack)
#else
static void test_Private_Transfer_Ack(void)
#endif
{
uint8_t apdu[480] = { 0 };
int len = 0;
int apdu_len = 0;
uint8_t invoke_id = 128;
uint8_t test_invoke_id = 0;
BACNET_PRIVATE_TRANSFER_DATA private_data;
BACNET_PRIVATE_TRANSFER_DATA test_data;
uint8_t test_value[480] = { 0 };
int private_data_len = 0;
char private_data_chunk[33] = { "00112233445566778899AABBCCDDEEFF" };
BACNET_APPLICATION_DATA_VALUE data_value = { 0 };
BACNET_APPLICATION_DATA_VALUE test_data_value = { 0 };
bool status = false;
private_data.vendorID = BACNET_VENDOR_ID;
private_data.serviceNumber = 1;
status = bacapp_parse_application_data(
BACNET_APPLICATION_TAG_OCTET_STRING, &private_data_chunk[0],
&data_value);
zassert_true(status, NULL);
private_data_len =
bacapp_encode_application_data(&test_value[0], &data_value);
private_data.serviceParameters = &test_value[0];
private_data.serviceParametersLen = private_data_len;
len = ptransfer_ack_encode_apdu(&apdu[0], invoke_id, &private_data);
zassert_not_equal(len, 0, NULL);
zassert_not_equal(len, -1, NULL);
apdu_len = len;
len = ptransfer_ack_decode_apdu(
&apdu[0], apdu_len, &test_invoke_id, &test_data);
zassert_not_equal(len, -1, NULL);
zassert_equal(test_invoke_id, invoke_id, NULL);
zassert_equal(test_data.vendorID, private_data.vendorID, NULL);
zassert_equal(test_data.serviceNumber, private_data.serviceNumber, NULL);
zassert_equal(
test_data.serviceParametersLen, private_data.serviceParametersLen,
NULL);
len = bacapp_decode_application_data(
test_data.serviceParameters, test_data.serviceParametersLen,
&test_data_value);
zassert_true(bacapp_same_value(&data_value, &test_data_value), NULL);
}
#if defined(CONFIG_ZTEST_NEW_API)
ZTEST(ptransfer_tests, test_Private_Transfer_Error)
#else
static void test_Private_Transfer_Error(void)
#endif
{
uint8_t apdu[480] = { 0 };
int len = 0;
int apdu_len = 0;
uint8_t invoke_id = 128;
uint8_t test_invoke_id = 0;
BACNET_ERROR_CLASS error_class = ERROR_CLASS_RESOURCES;
BACNET_ERROR_CODE error_code = ERROR_CODE_OPERATIONAL_PROBLEM;
BACNET_ERROR_CLASS test_error_class = 0;
BACNET_ERROR_CODE test_error_code = 0;
BACNET_PRIVATE_TRANSFER_DATA private_data;
BACNET_PRIVATE_TRANSFER_DATA test_data;
uint8_t test_value[480] = { 0 };
int private_data_len = 0;
char private_data_chunk[33] = { "00112233445566778899AABBCCDDEEFF" };
BACNET_APPLICATION_DATA_VALUE data_value = { 0 };
BACNET_APPLICATION_DATA_VALUE test_data_value = { 0 };
bool status = false;
private_data.vendorID = BACNET_VENDOR_ID;
private_data.serviceNumber = 1;
status = bacapp_parse_application_data(
BACNET_APPLICATION_TAG_OCTET_STRING, &private_data_chunk[0],
&data_value);
zassert_true(status, NULL);
private_data_len =
bacapp_encode_application_data(&test_value[0], &data_value);
private_data.serviceParameters = &test_value[0];
private_data.serviceParametersLen = private_data_len;
len = ptransfer_error_encode_apdu(
&apdu[0], invoke_id, error_class, error_code, &private_data);
zassert_not_equal(len, 0, NULL);
zassert_not_equal(len, -1, NULL);
apdu_len = len;
len = ptransfer_error_decode_apdu(
&apdu[0], apdu_len, &test_invoke_id, &test_error_class,
&test_error_code, &test_data);
zassert_not_equal(len, -1, NULL);
zassert_equal(test_invoke_id, invoke_id, NULL);
zassert_equal(test_data.vendorID, private_data.vendorID, NULL);
zassert_equal(test_data.serviceNumber, private_data.serviceNumber, NULL);
zassert_equal(test_error_class, error_class, NULL);
zassert_equal(test_error_code, error_code, NULL);
zassert_equal(
test_data.serviceParametersLen, private_data.serviceParametersLen,
NULL);
len = bacapp_decode_application_data(
test_data.serviceParameters, test_data.serviceParametersLen,
&test_data_value);
zassert_true(bacapp_same_value(&data_value, &test_data_value), NULL);
}
#if defined(CONFIG_ZTEST_NEW_API)
ZTEST(ptransfer_tests, test_Private_Transfer_Request)
#else
static void test_Private_Transfer_Request(void)
#endif
{
uint8_t apdu[480] = { 0 };
uint8_t test_value[480] = { 0 };
int len = 0, test_len = 0;
int apdu_len = 0;
uint8_t invoke_id = 128;
uint8_t test_invoke_id = 0;
int private_data_len = 0;
char private_data_chunk[33] = { "00112233445566778899AABBCCDDEEFF" };
BACNET_APPLICATION_DATA_VALUE data_value = { 0 };
BACNET_APPLICATION_DATA_VALUE test_data_value = { 0 };
BACNET_PRIVATE_TRANSFER_DATA private_data = { 0 };
BACNET_PRIVATE_TRANSFER_DATA test_data = { 0 };
bool status = false;
private_data.vendorID = BACNET_VENDOR_ID;
private_data.serviceNumber = 1;
status = bacapp_parse_application_data(
BACNET_APPLICATION_TAG_OCTET_STRING, &private_data_chunk[0],
&data_value);
zassert_true(status, NULL);
private_data_len =
bacapp_encode_application_data(&test_value[0], &data_value);
private_data.serviceParameters = &test_value[0];
private_data.serviceParametersLen = private_data_len;
apdu_len = ptransfer_encode_apdu(&apdu[0], invoke_id, &private_data);
zassert_not_equal(apdu_len, 0, NULL);
test_len =
ptransfer_decode_apdu(&apdu[0], apdu_len, &test_invoke_id, &test_data);
zassert_not_equal(test_len, -1, NULL);
zassert_equal(apdu_len, test_len, NULL);
zassert_equal(test_data.vendorID, private_data.vendorID, NULL);
zassert_equal(test_data.serviceNumber, private_data.serviceNumber, NULL);
zassert_equal(
test_data.serviceParametersLen, private_data.serviceParametersLen,
NULL);
len = bacapp_decode_application_data(
test_data.serviceParameters, test_data.serviceParametersLen,
&test_data_value);
zassert_not_equal(len, -1, NULL);
zassert_true(bacapp_same_value(&data_value, &test_data_value), NULL);
return;
}
#if defined(CONFIG_ZTEST_NEW_API)
ZTEST(ptransfer_tests, test_Unconfirmed_Private_Transfer_Request)
#else
static void test_Unconfirmed_Private_Transfer_Request(void)
#endif
{
uint8_t apdu[480] = { 0 };
uint8_t test_value[480] = { 0 };
int len = 0;
int apdu_len = 0, test_len = 0;
int private_data_len = 0;
char private_data_chunk[32] = { "I Love You, Patricia!" };
BACNET_APPLICATION_DATA_VALUE data_value = { 0 };
BACNET_APPLICATION_DATA_VALUE test_data_value = { 0 };
BACNET_PRIVATE_TRANSFER_DATA private_data;
BACNET_PRIVATE_TRANSFER_DATA test_data;
bool status = false;
private_data.vendorID = BACNET_VENDOR_ID;
private_data.serviceNumber = 1;
status = bacapp_parse_application_data(
BACNET_APPLICATION_TAG_CHARACTER_STRING, &private_data_chunk[0],
&data_value);
zassert_true(status, NULL);
private_data_len =
bacapp_encode_application_data(&test_value[0], &data_value);
private_data.serviceParameters = &test_value[0];
private_data.serviceParametersLen = private_data_len;
apdu_len = uptransfer_encode_apdu(&apdu[0], &private_data);
zassert_not_equal(apdu_len, 0, NULL);
test_len = uptransfer_decode_apdu(&apdu[0], apdu_len, &test_data);
zassert_not_equal(test_len, -1, NULL);
zassert_equal(
apdu_len, test_len, "apdu_len=%d test_len=%d", apdu_len, test_len);
zassert_equal(test_data.vendorID, private_data.vendorID, NULL);
zassert_equal(test_data.serviceNumber, private_data.serviceNumber, NULL);
zassert_equal(
test_data.serviceParametersLen, private_data.serviceParametersLen,
NULL);
len = bacapp_decode_application_data(
test_data.serviceParameters, test_data.serviceParametersLen,
&test_data_value);
zassert_not_equal(len, -1, NULL);
zassert_true(bacapp_same_value(&data_value, &test_data_value), NULL);
return;
}
/**
* @}
*/
#if defined(CONFIG_ZTEST_NEW_API)
ZTEST_SUITE(ptransfer_tests, NULL, NULL, NULL, NULL, NULL);
#else
void test_main(void)
{
ztest_test_suite(
ptransfer_tests, ztest_unit_test(test_Private_Transfer_Request),
ztest_unit_test(test_Private_Transfer_Ack),
ztest_unit_test(test_Private_Transfer_Error),
ztest_unit_test(test_Unconfirmed_Private_Transfer_Request));
ztest_run_test_suite(ptransfer_tests);
}
#endif