macOS keychain sanity test (#5885)

When requesting kSecClassIdentity items from the keychain sometimes
invalid items are returned. These cause errSecInvalidItemRef to
be returned from SecKeychainItemCopyAttributesAndData and result
in an empty row in the table. Catch the error and avoid returning
empty rows.
This commit is contained in:
Will Newton 2019-10-17 13:50:17 +01:00 committed by Teddy Reed
parent 3957d8e948
commit 599e9d6f3a
2 changed files with 27 additions and 22 deletions

View File

@ -55,9 +55,17 @@ void genKeychainItem(const SecKeychainItemRef& item, QueryData& results) {
// Any tag that does not exist for the item will prevent the entire result.
for (const auto& attr_tag : kKeychainItemAttrs) {
tags[0] = attr_tag.first;
SecKeychainItemCopyAttributesAndData(
auto os_status = SecKeychainItemCopyAttributesAndData(
item, &info, &item_class, &attr_list, 0, nullptr);
if (os_status == errSecNoSuchAttr) {
// This attr does not exist, skip it.
continue;
} else if (os_status != errSecSuccess) {
// If this keychain item is not valid then don't add it to results.
return;
}
if (attr_list != nullptr) {
// Expect each specific tag to return string data.
for (size_t i = 0; i < attr_list->count; ++i) {

View File

@ -14,34 +14,31 @@
namespace osquery {
namespace table_tests {
class keychainItems : public testing::Test {
class KeychainItemsTest : public testing::Test {
protected:
void SetUp() override {
setUpEnvironment();
}
};
TEST_F(keychainItems, test_sanity) {
// 1. Query data
TEST_F(KeychainItemsTest, test_sanity) {
auto const data = execute_query("select * from keychain_items");
// 2. Check size before validation
// ASSERT_GE(data.size(), 0ul);
// ASSERT_EQ(data.size(), 1ul);
// ASSERT_EQ(data.size(), 0ul);
// 3. Build validation map
// See helper.h for avaialbe flags
// Or use custom DataCheck object
// ValidationMap row_map = {
// {"label", NormalType}
// {"description", NormalType}
// {"comment", NormalType}
// {"created", NormalType}
// {"modified", NormalType}
// {"type", NormalType}
// {"path", NormalType}
//}
// 4. Perform validation
// validate_rows(data, row_map);
ASSERT_GT(data.size(), 0ul);
ValidationMap row_map = {
{"label", NormalType},
{"description", NormalType},
{"comment", NormalType},
{"created", NormalType},
{"modified", NormalType},
{"type",
SpecificValuesCheck{"password",
"certificate",
"symmetric key",
"public key",
"private key"}},
{"path", NonEmptyString},
};
validate_rows(data, row_map);
}
} // namespace table_tests