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;
}
/**
* 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
*
+2
View File
@@ -118,6 +118,8 @@ const char *characterstring_value(const BACNET_CHARACTER_STRING *char_string);
BACNET_STACK_EXPORT
size_t characterstring_length(const BACNET_CHARACTER_STRING *char_string);
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);
BACNET_STACK_EXPORT
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
do not require a password, this parameter shall be ignored.*/
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_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
} else if (characterstring_ansi_same(
+7 -1
View File
@@ -24,7 +24,13 @@
#include "bacnet/basic/services.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.
* @param new_password [in] The new DCC password, of up to 31 characters.
+5 -2
View File
@@ -8,9 +8,11 @@
#include <stdint.h>
/* BACnet Stack defines - first */
#include "bacnet/bacdef.h"
#include "bacnet/bacstr.h"
/* BACnet Stack API */
#include "bacnet/bacdcode.h"
#include "bacnet/dcc.h"
/** @file dcc.c Enable/Disable Device Communication Control (DCC) */
/* note: the disable and time are not expected to survive
over a power cycle or reinitialization. */
@@ -267,7 +269,6 @@ int dcc_decode_service_request(
uint32_t len_value_type = 0;
BACNET_UNSIGNED_INTEGER decoded_unsigned = 0;
uint32_t decoded_enum = 0;
uint32_t password_length = 0;
if (apdu && apdu_len_max) {
/* Tag 0: timeDuration, in minutes --optional-- */
@@ -321,7 +322,9 @@ int dcc_decode_service_request(
&apdu[apdu_len], apdu_len_max - apdu_len,
len_value_type, password);
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)) {
apdu_len += len;
} else {
+2 -1
View File
@@ -51,7 +51,8 @@ int reinitialize_device_encode(
}
/* password [1] CharacterString (SIZE (1..20)) OPTIONAL */
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);
apdu_len += len;
}