Bugfix/deprecate decode tag number and value (#481)

* added or updated secure the BACnet primitive value decoders - the core codecs - named bacnet_x_decode(), bacnet_x_application_decode() and bacnet_x_context_decode where x is one of the 13 BACnet primitive value names.  The updated API includes an APDU size to prevent over-reading of an APDU buffer while decoding.  Improved or added unit test code coverage for the BACnet primitive value decoders.

* marked the insecure decoding API as 'deprecated' which is defined in src/bacnet/basic/sys/platform.h and can be disabled during a build. 

* added secure decoders for BACnetTimeValue, BACnetHostNPort, BACnetTimeStamp, BACnetAddress, and Weekly_Schedule and improved unit test code coverage.

* improved test code coverage for BACnet objects and properties.

* secured AtomicReadFile and AtomicWriteFile service decoders and improved unit test code coverage.

* secured BACnet Error service decoder and improved unit test code coverage.

---------

Co-authored-by: Steve Karg <skarg@users.sourceforge.net>
This commit is contained in:
Steve Karg
2023-09-08 11:39:27 -05:00
committed by GitHub
parent bc8c261153
commit f641aacddb
67 changed files with 6103 additions and 3145 deletions
+72 -58
View File
@@ -151,10 +151,61 @@ bool Access_Credential_Object_Name(
return status;
}
/**
* @brief Encode a BACnetARRAY property element
* @param object_instance [in] BACnet network port object instance number
* @param index [in] array index requested:
* 0 to N for individual array members
* @param apdu [out] Buffer in which the APDU contents are built, or NULL to
* return the length of buffer if it had been built
* @return The length of the apdu encoded or
* BACNET_STATUS_ERROR for ERROR_CODE_INVALID_ARRAY_INDEX
*/
static int Access_Credential_Authentication_Factor_Array_Encode(
uint32_t object_instance, BACNET_ARRAY_INDEX index, uint8_t *apdu)
{
int apdu_len = BACNET_STATUS_ERROR;
if (object_instance < MAX_ACCESS_CREDENTIALS) {
if (index < ac_descr[object_instance].auth_factors_count) {
apdu_len = bacapp_encode_credential_authentication_factor(
apdu, &ac_descr[object_instance].auth_factors[index]);
}
}
return apdu_len;
}
/**
* @brief Encode a BACnetARRAY property element
* @param object_instance [in] BACnet network port object instance number
* @param index [in] array index requested:
* 0 to N for individual array members
* @param apdu [out] Buffer in which the APDU contents are built, or NULL to
* return the length of buffer if it had been built
* @return The length of the apdu encoded or
* BACNET_STATUS_ERROR for ERROR_CODE_INVALID_ARRAY_INDEX
*/
static int Access_Credential_Assigned_Access_Rights_Array_Encode(
uint32_t object_instance, BACNET_ARRAY_INDEX index, uint8_t *apdu)
{
int apdu_len = BACNET_STATUS_ERROR;
if (object_instance < MAX_ACCESS_CREDENTIALS) {
if (index < ac_descr[object_instance].assigned_access_rights_count) {
apdu_len = bacapp_encode_assigned_access_rights(
apdu, &ac_descr[object_instance].assigned_access_rights[index]);
}
}
return apdu_len;
}
/* return apdu len, or BACNET_STATUS_ERROR on error */
int Access_Credential_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
int len = 0;
int apdu_size;
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
@@ -167,6 +218,7 @@ int Access_Credential_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
return 0;
}
apdu = rpdata->application_data;
apdu_size = rpdata->application_data_len;
object_index = Access_Credential_Instance_To_Index(rpdata->object_instance);
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
@@ -218,35 +270,16 @@ int Access_Credential_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
}
break;
case PROP_AUTHENTICATION_FACTORS:
if (rpdata->array_index == 0) {
apdu_len = encode_application_unsigned(
&apdu[0], ac_descr[object_index].auth_factors_count);
} else if (rpdata->array_index == BACNET_ARRAY_ALL) {
for (i = 0; i < ac_descr[object_index].auth_factors_count;
i++) {
len = bacapp_encode_credential_authentication_factor(
&apdu[0], &ac_descr[object_index].auth_factors[i]);
if (apdu_len + len < MAX_APDU) {
apdu_len += len;
} else {
rpdata->error_code =
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
apdu_len = BACNET_STATUS_ABORT;
break;
}
}
} else {
if (rpdata->array_index <=
ac_descr[object_index].auth_factors_count) {
apdu_len =
bacapp_encode_credential_authentication_factor(&apdu[0],
&ac_descr[object_index]
.auth_factors[rpdata->array_index - 1]);
} else {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = BACNET_STATUS_ERROR;
}
apdu_len = bacnet_array_encode(rpdata->object_instance,
rpdata->array_index,
Access_Credential_Authentication_Factor_Array_Encode,
ac_descr[object_index].auth_factors_count, apdu, apdu_size);
if (apdu_len == BACNET_STATUS_ABORT) {
rpdata->error_code =
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
} else if (apdu_len == BACNET_STATUS_ERROR) {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
}
break;
case PROP_ACTIVATION_TIME:
@@ -262,35 +295,16 @@ int Access_Credential_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
&apdu[0], ac_descr[object_index].credential_disable);
break;
case PROP_ASSIGNED_ACCESS_RIGHTS:
if (rpdata->array_index == 0) {
apdu_len = encode_application_unsigned(&apdu[0],
ac_descr[object_index].assigned_access_rights_count);
} else if (rpdata->array_index == BACNET_ARRAY_ALL) {
for (i = 0;
i < ac_descr[object_index].assigned_access_rights_count;
i++) {
len = bacapp_encode_assigned_access_rights(&apdu[0],
&ac_descr[object_index].assigned_access_rights[i]);
if (apdu_len + len < MAX_APDU) {
apdu_len += len;
} else {
rpdata->error_code =
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
apdu_len = BACNET_STATUS_ABORT;
break;
}
}
} else {
if (rpdata->array_index <=
ac_descr[object_index].assigned_access_rights_count) {
apdu_len = bacapp_encode_assigned_access_rights(&apdu[0],
&ac_descr[object_index]
.assigned_access_rights[rpdata->array_index - 1]);
} else {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = BACNET_STATUS_ERROR;
}
apdu_len = bacnet_array_encode(rpdata->object_instance,
rpdata->array_index,
Access_Credential_Assigned_Access_Rights_Array_Encode,
ac_descr[object_index].assigned_access_rights_count, apdu, apdu_size);
if (apdu_len == BACNET_STATUS_ABORT) {
rpdata->error_code =
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
} else if (apdu_len == BACNET_STATUS_ERROR) {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
}
break;
default:
+4
View File
@@ -291,6 +291,10 @@ int Access_Point_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
}
}
break;
case PROP_PRIORITY_FOR_WRITING:
apdu_len = encode_application_unsigned(
&apdu[0], ap_descr[object_index].priority_for_writing);
break;
default:
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
+1
View File
@@ -31,6 +31,7 @@
#include "bacnet/bacdef.h"
#include "bacnet/cov.h"
#include "bacnet/datetime.h"
#include "bacnet/readrange.h"
#include "bacnet/rp.h"
#include "bacnet/wp.h"
+3 -1
View File
@@ -30,7 +30,9 @@
#endif
/* marking some code as 'deprecated' */
# if defined(_MSC_VER)
#if defined(BACNET_STACK_DEPRECATED_DISABLE)
# define BACNET_STACK_DEPRECATED(message)
#elif defined(_MSC_VER)
# define BACNET_STACK_DEPRECATED(message) __declspec(deprecated(message))
#elif defined(__GNUC__)
# define BACNET_STACK_DEPRECATED(message) __attribute__((deprecated(message)))