123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459 |
- // Copyright 2020 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "device/fido/filter.h"
- #include "testing/gtest/include/gtest/gtest.h"
- namespace device {
- namespace fido_filter {
- namespace {
- TEST(FidoFilter, Basic) {
- static const uint8_t kCredIDBytes[] = {1, 2, 3, 4};
- const auto cred_id = std::pair<IDType, base::span<const uint8_t>>(
- IDType::CREDENTIAL_ID, kCredIDBytes);
- const auto empty_cred_id = std::pair<IDType, base::span<const uint8_t>>(
- IDType::CREDENTIAL_ID, base::span<const uint8_t>());
- static const struct {
- const char* filter;
- Operation op;
- base::StringPiece rp_id;
- absl::optional<base::StringPiece> device;
- absl::optional<std::pair<IDType, base::span<const uint8_t>>> id;
- Action expected;
- } kTests[] = {
- {
- "",
- Operation::MAKE_CREDENTIAL,
- "example.com",
- absl::nullopt,
- absl::nullopt,
- Action::ALLOW,
- },
- {
- R"({"filters": []})",
- Operation::MAKE_CREDENTIAL,
- "example.com",
- absl::nullopt,
- absl::nullopt,
- Action::ALLOW,
- },
- {
- R"({"filters": [{
- "operation": "mc",
- "rp_id": "*",
- "action": "block",
- }]})",
- Operation::MAKE_CREDENTIAL,
- "example.com",
- absl::nullopt,
- absl::nullopt,
- Action::BLOCK,
- },
- {
- R"({"filters": [{
- "operation": "m*",
- "rp_id": "*",
- "action": "block",
- }]})",
- Operation::MAKE_CREDENTIAL,
- "example.com",
- absl::nullopt,
- absl::nullopt,
- Action::BLOCK,
- },
- {
- R"({"filters": [{
- "operation": "*",
- "rp_id": "*",
- "action": "block",
- }]})",
- Operation::MAKE_CREDENTIAL,
- "example.com",
- absl::nullopt,
- absl::nullopt,
- Action::BLOCK,
- },
- {
- R"({"filters": [{
- "operation": "mc",
- "rp_id": "*",
- "action": "no-attestation",
- }]})",
- Operation::MAKE_CREDENTIAL,
- "example.com",
- absl::nullopt,
- absl::nullopt,
- Action::NO_ATTESTATION,
- },
- {
- R"({"filters": [{
- "rp_id": "example.com",
- "action": "block",
- }]})",
- Operation::MAKE_CREDENTIAL,
- "example.com",
- absl::nullopt,
- absl::nullopt,
- Action::BLOCK,
- },
- {
- R"({"filters": [{
- "rp_id": "foo.com",
- "action": "block",
- }]})",
- Operation::MAKE_CREDENTIAL,
- "example.com",
- absl::nullopt,
- absl::nullopt,
- Action::ALLOW,
- },
- {
- R"({"filters": [{
- "device": "usb-1234:4321",
- "action": "block",
- }]})",
- Operation::MAKE_CREDENTIAL,
- "example.com",
- "usb-1234:4321",
- absl::nullopt,
- Action::BLOCK,
- },
- {
- R"({"filters": [{
- "device": "usb-1234:4321",
- "action": "block",
- }]})",
- Operation::MAKE_CREDENTIAL,
- "example.com",
- "usb-0000:4321",
- absl::nullopt,
- Action::ALLOW,
- },
- {
- R"({"filters": [{
- "device": "usb-*",
- "action": "block",
- }]})",
- Operation::MAKE_CREDENTIAL,
- "example.com",
- "usb-0000:4321",
- absl::nullopt,
- Action::BLOCK,
- },
- {
- R"({"filters": [{
- "device": "usb-*",
- "action": "block",
- }]})",
- Operation::MAKE_CREDENTIAL,
- "example.com",
- "usb-0000:4321",
- absl::nullopt,
- Action::BLOCK,
- },
- {
- R"({"filters": [{
- "id_type": "cred",
- "rp_id": "*",
- "action": "block",
- }]})",
- Operation::MAKE_CREDENTIAL,
- "example.com",
- absl::nullopt,
- cred_id,
- Action::BLOCK,
- },
- {
- R"({"filters": [{
- "id_type": "user",
- "rp_id": "*",
- "action": "block",
- }]})",
- Operation::MAKE_CREDENTIAL,
- "example.com",
- absl::nullopt,
- cred_id,
- Action::ALLOW,
- },
- {
- R"({"filters": [{
- "id_type": "cred",
- "id": "01*",
- "rp_id": "*",
- "action": "block",
- }]})",
- Operation::MAKE_CREDENTIAL,
- "example.com",
- absl::nullopt,
- cred_id,
- Action::BLOCK,
- },
- {
- R"({"filters": [{
- "id_type": "cred",
- "id": "01020304",
- "rp_id": "*",
- "action": "block",
- }]})",
- Operation::MAKE_CREDENTIAL,
- "example.com",
- absl::nullopt,
- cred_id,
- Action::BLOCK,
- },
- {
- R"({"filters": [{
- "id_type": "cred",
- "id_min_size": 4,
- "rp_id": "*",
- "action": "block",
- }]})",
- Operation::MAKE_CREDENTIAL,
- "example.com",
- absl::nullopt,
- cred_id,
- Action::BLOCK,
- },
- {
- R"({"filters": [{
- "id_type": "cred",
- "id_min_size": 8,
- "rp_id": "*",
- "action": "block",
- }]})",
- Operation::MAKE_CREDENTIAL,
- "example.com",
- absl::nullopt,
- cred_id,
- Action::ALLOW,
- },
- {
- R"({"filters": [{
- "id_type": "cred",
- "id_min_size": 4,
- "id_max_size": 4,
- "rp_id": "*",
- "action": "block",
- }]})",
- Operation::MAKE_CREDENTIAL,
- "example.com",
- absl::nullopt,
- cred_id,
- Action::BLOCK,
- },
- // id fields can be empty, to match an empty ID.
- {
- R"({"filters": [{
- "operation": "mc",
- "rp_id": "*",
- "id_type": "cred",
- "id": "",
- "action": "block",
- }]})",
- Operation::MAKE_CREDENTIAL,
- "example.com",
- absl::nullopt,
- empty_cred_id,
- Action::BLOCK,
- },
- // rp_id can be a list of strings, any of which may match.
- {
- R"({"filters": [{
- "operation": "mc",
- "rp_id": ["a.com", "b.com"],
- "action": "block",
- }]})",
- Operation::MAKE_CREDENTIAL,
- "a.com",
- absl::nullopt,
- absl::nullopt,
- Action::BLOCK,
- },
- {
- R"({"filters": [{
- "operation": "mc",
- "rp_id": ["a.com", "b.com"],
- "action": "block",
- }]})",
- Operation::MAKE_CREDENTIAL,
- "b.com",
- absl::nullopt,
- absl::nullopt,
- Action::BLOCK,
- },
- {
- R"({"filters": [{
- "operation": "mc",
- "rp_id": ["a.com", "b.com"],
- "action": "block",
- }]})",
- Operation::MAKE_CREDENTIAL,
- "c.com",
- absl::nullopt,
- absl::nullopt,
- Action::ALLOW,
- },
- // id can be a list of strings, any of which may match.
- {
- R"({"filters": [{
- "operation": "mc",
- "rp_id": "*",
- "id_type": "cred",
- "id": ["01", "01020304", "05060708", ""],
- "action": "block",
- }]})",
- Operation::MAKE_CREDENTIAL,
- "a.com",
- absl::nullopt,
- cred_id,
- Action::BLOCK,
- },
- // The two following cases test that a more specific filter can permit
- // something blocked by a later, more general, filter.
- {
- R"({"filters": [{
- "rp_id": "*",
- "device": "usb-1234:1234",
- "action": "allow",
- },{
- "rp_id": "*",
- "device": "usb-1234:*",
- "action": "block",
- }]})",
- Operation::MAKE_CREDENTIAL,
- "example.com",
- "usb-1234:5678",
- absl::nullopt,
- Action::BLOCK,
- },
- {
- R"({"filters": [{
- "rp_id": "*",
- "device": "usb-1234:1234",
- "action": "allow",
- },{
- "rp_id": "*",
- "device": "usb-1234:*",
- "action": "block",
- }]})",
- Operation::MAKE_CREDENTIAL,
- "example.com",
- "usb-1234:1234",
- absl::nullopt,
- Action::ALLOW,
- },
- };
- int test_num = 0;
- for (const auto& test : kTests) {
- SCOPED_TRACE(test_num);
- SCOPED_TRACE(test.filter);
- test_num++;
- ScopedFilterForTesting filter(test.filter);
- const Action result = Evaluate(test.op, test.rp_id, test.device, test.id);
- EXPECT_EQ(result, test.expected);
- }
- }
- TEST(FidoFilter, InvalidFilters) {
- static const char* kTests[] = {
- // Value has the wrong type.
- R"({"filters": [{
- "operation": 8,
- "rp_id": "foo.com",
- "action": "block"
- }]})",
- // Missing action.
- R"({"filters": [{
- "id_type": "cred",
- "id_min_size": 8
- }]})",
- // Unknown action.
- R"({"filters": [{
- "id_type": "cred",
- "id_min_size": 8,
- "action": "foo"
- }]})",
- // Missing ID types
- R"({"filters": [{
- "id_min_size": 8,
- "action": "block"
- }]})",
- R"({"filters": [{
- "id_max_size": 8,
- "action": "block"
- }]})",
- R"({"filters": [{
- "id": "112233",
- "action": "block"
- }]})",
- // Can't match everything.
- R"({"filters": [{
- "operation": "mc",
- "action": "block"
- }]})",
- // Can't match everything.
- R"({"filters": [{
- "operation": "ga",
- "action": "block"
- }]})",
- // Unknown keys are an error
- R"({"filters": [{
- "operation": "ga",
- "rp_id": "foo.com",
- "action": "block",
- "unknown": "bar"
- }]})",
- // No string values except IDs can be empty.
- R"({"filters": [{
- "operation": "ga",
- "rp_id": "",
- "action": "block",
- }]})",
- R"({"filters": [{
- "operation": "ga",
- "rp_id": ["nonempty", ""],
- "action": "block",
- }]})",
- R"({"filters": [{
- "operation": "ga",
- "rp_id": [],
- "action": "block",
- }]})",
- R"({"filters": [{
- "operation": "ga",
- "rp_id": "*",
- "id": [],
- "action": "block",
- }]})",
- };
- int test_num = 0;
- for (const auto* test : kTests) {
- SCOPED_TRACE(test_num);
- SCOPED_TRACE(test);
- test_num++;
- EXPECT_FALSE(ParseForTesting(test));
- }
- }
- TEST(FidoFilter, InvalidJSON) {
- // Testing that nothing crashes, etc.
- ScopedFilterForTesting filter(
- "nonsense", ScopedFilterForTesting::PermitInvalidJSON::kYes);
- ASSERT_EQ(Evaluate(Operation::GET_ASSERTION, "example.com", absl::nullopt,
- absl::nullopt),
- Action::ALLOW);
- ASSERT_EQ(Evaluate(Operation::MAKE_CREDENTIAL, "example.com", absl::nullopt,
- absl::nullopt),
- Action::ALLOW);
- }
- } // namespace
- } // namespace fido_filter
- } // namespace device
|