Skip to content

Commit 61fbaef

Browse files
committed
GH-43: Enforce Credential and User Capabilities
Bug-SiliconLabs: UIC-3222 Bug-GitHub: #43 Signed-off-by: Philippe Coval <[email protected]>
1 parent a16243a commit 61fbaef

File tree

3 files changed

+1158
-116
lines changed

3 files changed

+1158
-116
lines changed

applications/zpc/components/zcl_cluster_servers/test/user_credential_cluster_server_test.cpp

+185-13
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ void mock_deletion_user_mqtt_topic(user_credential_user_unique_id_t user_id);
5151
void mock_deletion_cred_mqtt_topic(user_credential_user_unique_id_t user_id,
5252
user_credential_type_t credential_type,
5353
user_credential_slot_t credential_slot);
54+
void mock_deletion_cred_rule_mqtt_topic(user_credential_type_t credential_type);
55+
void setup_user_capabilities();
56+
void setup_cred_capabilities();
57+
5458

5559
// Keep a reference to the mqtt topics we want to test
5660
// Stored as <topic, payload>
@@ -60,6 +64,8 @@ static std::vector<std::tuple<user_credential_user_unique_id_t,
6064
user_credential_type_t,
6165
user_credential_slot_t>>
6266
created_credential_ids;
67+
static std::vector<user_credential_type_t>
68+
created_supported_credential_types;
6369

6470
// Callback functions
6571
// clang-format off
@@ -132,6 +138,11 @@ int suiteTearDown(int num_failures)
132138
/// Called before each and every test
133139
void setUp()
134140
{
141+
// WARNING : Order matters here
142+
// Check if credential rules need to be removed
143+
for(auto cred_type: created_supported_credential_types) {
144+
mock_deletion_cred_rule_mqtt_topic(cred_type);
145+
}
135146
// Check if any users that need to be removed
136147
for (auto user_id: created_user_id) {
137148
// Check if MQTT topics for deletion are correctly published
@@ -143,6 +154,8 @@ void setUp()
143154
std::get<2>(cred_id));
144155
}
145156

157+
158+
146159
zpc_attribute_store_test_helper_create_network();
147160

148161
// Intercept the dotdot MQTT callbacks
@@ -154,7 +167,7 @@ void setUp()
154167
mqtt_topics.clear();
155168
created_user_id.clear();
156169
created_credential_ids.clear();
157-
170+
created_supported_credential_types.clear();
158171
// clang-format off
159172
// User
160173
uic_mqtt_dotdot_user_credential_add_user_callback_set_Stub(&uic_mqtt_dotdot_user_credential_add_user_callback_set_stub);
@@ -168,20 +181,29 @@ void setUp()
168181

169182
// Run the component init
170183
TEST_ASSERT_EQUAL(SL_STATUS_OK, user_credential_cluster_server_init());
184+
185+
// We are not here to test user capabilities, so we need to set them up to
186+
// accept our test data
187+
setup_user_capabilities();
188+
// Need to call this after init() to have the mqtt callback initialized
189+
setup_cred_capabilities();
171190
}
172191

173192
/////////////////////////////////////////////////////////////////////////
174193
// Mqtt topics helpers
175194
/////////////////////////////////////////////////////////////////////////
176-
std::string get_base_topic()
195+
std::string get_base_topic(bool include_user=true)
177196
{
197+
const std::string user_str = include_user ? "/User" : "";
178198
const std::string base
179-
= "ucl/by-unid/%1%/ep%2%/UserCredential/Attributes/User";
199+
= "ucl/by-unid/%1%/ep%2%/UserCredential/Attributes%3%";
180200
return (boost::format(base) % supporting_node_unid
181-
% (unsigned int)endpoint_id)
201+
% (unsigned int)endpoint_id % user_str)
182202
.str();
183203
}
184204

205+
206+
185207
std::string
186208
get_user_attribute_mqtt_topic(user_credential_user_unique_id_t user_unique_id,
187209
const std::string &attribute_name)
@@ -205,6 +227,17 @@ std::string
205227
.str();
206228
}
207229

230+
std::string
231+
get_cred_rule_mqtt_topic(user_credential_type_t credential_type,
232+
const std::string &attribute_name)
233+
{
234+
const std::string base = "%1%/Credentials/%2%/%3%/Reported";
235+
return (boost::format(base) % get_base_topic(false)
236+
% cred_type_get_enum_value_name(credential_type)
237+
% attribute_name)
238+
.str();
239+
}
240+
208241
} // extern "C"
209242

210243
template<typename T> std::string get_payload(T value)
@@ -250,7 +283,21 @@ void mock_expected_cred_mqtt_topic(user_credential_user_unique_id_t user_id,
250283
mqtt_topics.back().second.size(),
251284
true);
252285
}
286+
template<typename T>
287+
void mock_expected_cred_rule_mqtt_topic(user_credential_type_t credential_type,
288+
const std::string &attribute_name,
289+
T payload_value)
290+
{
291+
// This way we make sure that we have valid reference to our strings
292+
mqtt_topics.push_back(
293+
{get_cred_rule_mqtt_topic(credential_type, attribute_name),
294+
get_payload<T>(payload_value)});
253295

296+
uic_mqtt_publish_Expect(mqtt_topics.back().first.c_str(),
297+
mqtt_topics.back().second.c_str(),
298+
mqtt_topics.back().second.size(),
299+
true);
300+
}
254301
void mock_deletion_user_mqtt_topic(user_credential_user_unique_id_t user_id)
255302
{
256303
// WARNING : Order here matters based on their initialization order in the add_complete_user function
@@ -292,6 +339,129 @@ void mock_deletion_cred_mqtt_topic(user_credential_user_unique_id_t user_id,
292339
true);
293340
}
294341
}
342+
343+
void mock_deletion_cred_rule_mqtt_topic(user_credential_type_t credential_type)
344+
{
345+
// WARNING : Order here matters based on their initialization order in the add_complete_credential function
346+
std::vector<std::string> attribute_names = {"ReadBackSupport",
347+
"SupportedSlotCount",
348+
"CredentialMinLength",
349+
"CredentialMaxLength"};
350+
for (auto &attribute_name: attribute_names) {
351+
mqtt_topics.push_back(
352+
{get_cred_rule_mqtt_topic(credential_type, attribute_name), ""});
353+
uic_mqtt_publish_Expect(mqtt_topics.back().first.c_str(),
354+
mqtt_topics.back().second.c_str(),
355+
mqtt_topics.back().second.size(),
356+
true);
357+
}
358+
}
359+
/////////////////////////////////////////////////////////////////////////
360+
// Capabilities Helper
361+
/////////////////////////////////////////////////////////////////////////
362+
void setup_user_capabilities() {
363+
uint16_t number_of_users = 12;
364+
user_credential_supported_credential_rules_t cred_rule_bitmask = 0x0F;
365+
uint8_t username_max_length = 112;
366+
uint8_t support_user_schedule = 0;
367+
uint8_t support_all_users_checksum = 0;
368+
uint8_t support_user_checksum = 0;
369+
user_credential_supported_user_type_bitmask_t supported_user_types_bitmask
370+
= 0xFF;
371+
372+
attribute_store_emplace(endpoint_id_node,
373+
ATTRIBUTE(NUMBER_OF_USERS),
374+
&number_of_users,
375+
sizeof(number_of_users));
376+
377+
attribute_store_emplace(endpoint_id_node,
378+
ATTRIBUTE(SUPPORTED_CREDENTIAL_RULES),
379+
&cred_rule_bitmask,
380+
sizeof(cred_rule_bitmask));
381+
382+
attribute_store_emplace(endpoint_id_node,
383+
ATTRIBUTE(MAX_USERNAME_LENGTH),
384+
&username_max_length,
385+
sizeof(username_max_length));
386+
387+
attribute_store_emplace(endpoint_id_node,
388+
ATTRIBUTE(SUPPORT_USER_SCHEDULE),
389+
&support_user_schedule,
390+
sizeof(support_user_schedule));
391+
392+
attribute_store_emplace(endpoint_id_node,
393+
ATTRIBUTE(SUPPORT_ALL_USERS_CHECKSUM),
394+
&support_all_users_checksum,
395+
sizeof(support_all_users_checksum));
396+
397+
attribute_store_emplace(endpoint_id_node,
398+
ATTRIBUTE(SUPPORT_USER_CHECKSUM),
399+
&support_user_checksum,
400+
sizeof(support_user_checksum));
401+
402+
attribute_store_emplace(endpoint_id_node,
403+
ATTRIBUTE(SUPPORTED_USER_TYPES),
404+
&supported_user_types_bitmask,
405+
sizeof(supported_user_types_bitmask));
406+
}
407+
408+
void setup_cred_capabilities() {
409+
410+
// Supports ZCL_CRED_TYPE_PIN_CODE..ZCL_CRED_TYPE_BLE
411+
// Adjust if needed, we don't need to test all types and this outputs a lot of noise on the logs
412+
uint8_t max_cred_type = ZCL_CRED_TYPE_BLE;
413+
for (uint8_t i=ZCL_CRED_TYPE_PIN_CODE;i<=max_cred_type;i++) {
414+
user_credential_type_t cred_type
415+
= static_cast<user_credential_type_t>(i);
416+
417+
auto supported_cred_type_node
418+
= attribute_store_emplace(endpoint_id_node,
419+
ATTRIBUTE(SUPPORTED_CREDENTIAL_TYPE),
420+
&cred_type,
421+
sizeof(cred_type));
422+
uint8_t crb_support = 1;
423+
uint16_t slot_supported = 0xFFFF;
424+
uint16_t cred_min_length = 0;
425+
uint16_t cred_max_length = 0xFF;
426+
427+
mock_expected_cred_rule_mqtt_topic(cred_type,
428+
"ReadBackSupport",
429+
(bool)crb_support);
430+
attribute_store_emplace(supported_cred_type_node,
431+
ATTRIBUTE(CREDENTIAL_LEARN_READ_BACK_SUPPORT),
432+
&crb_support,
433+
sizeof(crb_support));
434+
435+
mock_expected_cred_rule_mqtt_topic(cred_type,
436+
"SupportedSlotCount",
437+
slot_supported);
438+
439+
attribute_store_emplace(supported_cred_type_node,
440+
ATTRIBUTE(CREDENTIAL_SUPPORTED_SLOT_COUNT),
441+
&slot_supported,
442+
sizeof(slot_supported));
443+
mock_expected_cred_rule_mqtt_topic(cred_type,
444+
"CredentialMinLength",
445+
cred_min_length);
446+
447+
attribute_store_emplace(supported_cred_type_node,
448+
ATTRIBUTE(CREDENTIAL_MIN_LENGTH),
449+
&cred_min_length,
450+
sizeof(cred_min_length));
451+
452+
mock_expected_cred_rule_mqtt_topic(cred_type,
453+
"CredentialMaxLength",
454+
cred_max_length);
455+
attribute_store_emplace(supported_cred_type_node,
456+
ATTRIBUTE(CREDENTIAL_MAX_LENGTH),
457+
&cred_max_length,
458+
sizeof(cred_max_length));
459+
460+
// Will allow to test deletion of attributes
461+
created_supported_credential_types.push_back(cred_type);
462+
}
463+
}
464+
295465
/////////////////////////////////////////////////////////////////////////
296466
// HELPERS
297467
/////////////////////////////////////////////////////////////////////////
@@ -1100,7 +1270,7 @@ void test_user_credential_cluster_add_credential_others_happy_case()
11001270
{
11011271
// Simulate user
11021272
user_credential_user_unique_id_t user_unique_id = 12;
1103-
CredType credential_type = CredType::ZCL_CRED_TYPE_NFC;
1273+
CredType credential_type = CredType::ZCL_CRED_TYPE_RFID_CODE;
11041274
user_credential_slot_t credential_slot = 1;
11051275
const char *credential_data = "hunter2";
11061276

@@ -1402,13 +1572,6 @@ void test_user_credential_cluster_delete_credential_happy_case()
14021572

14031573
void test_user_credential_cluster_test_user_command_support_happy_case()
14041574
{
1405-
// Emplace checked attributes
1406-
uint16_t user_count = 2;
1407-
attribute_store_emplace(endpoint_id_node,
1408-
ATTRIBUTE(NUMBER_OF_USERS),
1409-
&user_count,
1410-
sizeof(user_count));
1411-
14121575
// We don't care about those value it should not matter here
14131576
user_credential_user_unique_id_t user_unique_id = 12;
14141577
UserTypeEnum user_type = ZCL_USER_TYPE_ENUM_DISPOSABLE_USER;
@@ -1466,6 +1629,15 @@ void test_user_credential_cluster_test_user_command_not_supported_happy_case()
14661629
UserNameEncodingType user_name_encoding = ZCL_USER_NAME_ENCODING_TYPE_ASCII;
14671630
const char *user_name = "Test User";
14681631

1632+
// We don't want anything in the tree for this test
1633+
// This way we can make support check fails
1634+
// We need to inform the MQTT of the deleted credential type rules
1635+
for(auto cred_type: created_supported_credential_types) {
1636+
mock_deletion_cred_rule_mqtt_topic(cred_type);
1637+
}
1638+
// Delete all the nodes
1639+
attribute_store_delete_all_children(endpoint_id_node);
1640+
14691641
TEST_ASSERT_EQUAL_MESSAGE(
14701642
SL_STATUS_FAIL,
14711643
add_user_command(supporting_node_unid,
@@ -1478,7 +1650,7 @@ void test_user_credential_cluster_test_user_command_not_supported_happy_case()
14781650
user_name,
14791651
expiring_timeout,
14801652
user_name_encoding),
1481-
"Add user should not be supported");
1653+
"Check value : Add user should not be supported");
14821654

14831655
TEST_ASSERT_EQUAL_MESSAGE(
14841656
SL_STATUS_FAIL,

0 commit comments

Comments
 (0)