Fixed UTF-8 passwords for DeviceCommunicationControl to hold up to 20 UTF-8 characters (#767)

This commit is contained in:
Tomasz Kazimierz Motyl
2024-09-19 14:37:36 +01:00
committed by GitHub
parent b9adcc8097
commit f4325f00b5
6 changed files with 40 additions and 5 deletions
+23
View File
@@ -587,6 +587,29 @@ bool characterstring_ansi_same(
return same_status; return same_status;
} }
/**
* Returns number of UTF8 code points in a character string.
*
* @param dest Pointer to the string to count the UTF8 code points.
*
* @return Length of the character string in utf8 codepoints
*/
size_t characterstring_utf8_length(const BACNET_CHARACTER_STRING *str)
{
size_t count = 0;
int i = 0;
while ((i < MAX_CHARACTER_STRING_BYTES) && (str->value[i] != '\0')) {
if ((str->value[i] & 0xc0) != 0x80) {
count++;
}
i++;
}
return count;
}
/** /**
* Append some characters to the end of the characterstring * Append some characters to the end of the characterstring
* *
+2
View File
@@ -118,6 +118,8 @@ const char *characterstring_value(const BACNET_CHARACTER_STRING *char_string);
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
size_t characterstring_length(const BACNET_CHARACTER_STRING *char_string); size_t characterstring_length(const BACNET_CHARACTER_STRING *char_string);
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
size_t characterstring_utf8_length(const BACNET_CHARACTER_STRING *str);
BACNET_STACK_EXPORT
uint8_t characterstring_encoding(const BACNET_CHARACTER_STRING *char_string); uint8_t characterstring_encoding(const BACNET_CHARACTER_STRING *char_string);
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
size_t characterstring_capacity(const BACNET_CHARACTER_STRING *char_string); size_t characterstring_capacity(const BACNET_CHARACTER_STRING *char_string);
+1 -1
View File
@@ -667,7 +667,7 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
is absent or if the password is incorrect. For those devices that is absent or if the password is incorrect. For those devices that
do not require a password, this parameter shall be ignored.*/ do not require a password, this parameter shall be ignored.*/
if (Reinit_Password && strlen(Reinit_Password) > 0) { if (Reinit_Password && strlen(Reinit_Password) > 0) {
if (characterstring_length(&rd_data->password) > 20) { if (characterstring_utf8_length(&rd_data->password) > 20) {
rd_data->error_class = ERROR_CLASS_SERVICES; rd_data->error_class = ERROR_CLASS_SERVICES;
rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
} else if (characterstring_ansi_same( } else if (characterstring_ansi_same(
+7 -1
View File
@@ -24,7 +24,13 @@
#include "bacnet/basic/services.h" #include "bacnet/basic/services.h"
#include "bacnet/datalink/datalink.h" #include "bacnet/datalink/datalink.h"
static char My_Password[32] = "filister"; /* The byte length of a UTF-8 character can vary.
* In UTF-8, the number of bytes used to represent a character can range from 1
* to 4 bytes. Commonly used characters in the ASCII set are represented by 1
* byte,xi while other Unicode characters may require 2, 3, or 4 bytes. Let's
* add space for the null '\0' termination byte.
* */
static char My_Password[20 * 4 + 1] = "filister";
/** Sets (non-volatile hold) the password to be used for DCC requests. /** Sets (non-volatile hold) the password to be used for DCC requests.
* @param new_password [in] The new DCC password, of up to 31 characters. * @param new_password [in] The new DCC password, of up to 31 characters.
+5 -2
View File
@@ -8,9 +8,11 @@
#include <stdint.h> #include <stdint.h>
/* BACnet Stack defines - first */ /* BACnet Stack defines - first */
#include "bacnet/bacdef.h" #include "bacnet/bacdef.h"
#include "bacnet/bacstr.h"
/* BACnet Stack API */ /* BACnet Stack API */
#include "bacnet/bacdcode.h" #include "bacnet/bacdcode.h"
#include "bacnet/dcc.h" #include "bacnet/dcc.h"
/** @file dcc.c Enable/Disable Device Communication Control (DCC) */
/* note: the disable and time are not expected to survive /* note: the disable and time are not expected to survive
over a power cycle or reinitialization. */ over a power cycle or reinitialization. */
@@ -267,7 +269,6 @@ int dcc_decode_service_request(
uint32_t len_value_type = 0; uint32_t len_value_type = 0;
BACNET_UNSIGNED_INTEGER decoded_unsigned = 0; BACNET_UNSIGNED_INTEGER decoded_unsigned = 0;
uint32_t decoded_enum = 0; uint32_t decoded_enum = 0;
uint32_t password_length = 0;
if (apdu && apdu_len_max) { if (apdu && apdu_len_max) {
/* Tag 0: timeDuration, in minutes --optional-- */ /* Tag 0: timeDuration, in minutes --optional-- */
@@ -321,7 +322,9 @@ int dcc_decode_service_request(
&apdu[apdu_len], apdu_len_max - apdu_len, &apdu[apdu_len], apdu_len_max - apdu_len,
len_value_type, password); len_value_type, password);
if (len > 0) { if (len > 0) {
password_length = len_value_type - 1; size_t password_length =
characterstring_utf8_length(password);
/* UTF-8 code points can be up to 4 bytes long */
if ((password_length >= 1) && (password_length <= 20)) { if ((password_length >= 1) && (password_length <= 20)) {
apdu_len += len; apdu_len += len;
} else { } else {
+2 -1
View File
@@ -51,7 +51,8 @@ int reinitialize_device_encode(
} }
/* password [1] CharacterString (SIZE (1..20)) OPTIONAL */ /* password [1] CharacterString (SIZE (1..20)) OPTIONAL */
if (password) { if (password) {
if ((password->length >= 1) && (password->length <= 20)) { if ((password->length >= 1) &&
(characterstring_utf8_length(password) <= 20)) {
len = encode_context_character_string(apdu, 1, password); len = encode_context_character_string(apdu, 1, password);
apdu_len += len; apdu_len += len;
} }