filter.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // Copyright 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef DEVICE_FIDO_FILTER_H_
  5. #define DEVICE_FIDO_FILTER_H_
  6. #include <string>
  7. #include <utility>
  8. #include "base/component_export.h"
  9. #include "base/containers/span.h"
  10. #include "base/strings/string_piece.h"
  11. #include "third_party/abseil-cpp/absl/types/optional.h"
  12. namespace device {
  13. namespace fido_filter {
  14. // This code is intended to allow Finch control of several cases that have
  15. // cropped up over time:
  16. // * Disabling a device on the USB bus that immediately answers all requests,
  17. // thus stopping anything else from working.
  18. // * Filtering attestation from devices that are found to be sending
  19. // excessively identifying information.
  20. // * Filtering attestation from websites that are performing tight
  21. // allowlisting in a public context.
  22. // * Filtering IDs from devices that are using them to tunnel other protocols.
  23. //
  24. // Thus Finch can set the "json" parameter of "WebAuthenticationFilter" to a
  25. // JSON string with the following structure:
  26. //
  27. // {
  28. // "filters": [{
  29. // "operation": matched against "ga" (getAssertion) or "mc" (makeCredential)
  30. // "rp_id": matched against the RP ID (or AppID via the U2F API). Can be a
  31. // list of such strings which matches if any element matches.
  32. // "device": matched against the GetDisplayName value of the authenticator
  33. // "id_type": matched against "cred" (credential IDs) or "user" (user IDs).
  34. // "cred" matches against the allowCredentials of
  35. // PublicKeyCredentialRequestOptions and the excludeCredentials
  36. // of PublicKeyCredentialCreationOptions. "user" matches against
  37. // the user.id of PublicKeyCredentialCreationOptions.
  38. // "id": matched against the uppercase hex of the given ID. Can be
  39. // a list of such strings which matches if any element matches.
  40. // "id_min_size": matches if <= to the ID length, in bytes.
  41. // "id_max_size": matches if >= to the ID length, in bytes.
  42. // "action": "allow", "block", or "no-attestation".
  43. // }, { ... }
  44. // ]}
  45. //
  46. // The JSON is allowed to have trailing commas, unlike standard JSON.
  47. //
  48. // When strings are matched, it is using base/strings/pattern.h. Note the
  49. // comment in that file well because it's more like a file glob than a regexp.
  50. //
  51. // The only required field is "action", but:
  52. // * "id_type" must be given if "id_min_size", "id_max_size", or "id" are.
  53. // * At least one of "device" or "rp_id" must be given.
  54. //
  55. // Any structural errors, or unknown keys, in the JSON cause a parse error and
  56. // the filter fails open.
  57. //
  58. // A result of "block" rejects the action. If an action is blocked for all
  59. // devices and doesn't specify an ID then it'll result in an immediate rejection
  60. // of the WebAuthn Promise. Otherwise, a block causes an authenticator to be
  61. // ignored, potentially hanging the request if all authenticators are ignored. A
  62. // result of "allow" permits the action. (This can be useful to permit a narrow
  63. // range of cases before blocking a wider range.) Lastly, a result of
  64. // "no-attestation" causes attestation to be suppressed for makeCredential
  65. // operations, unless the RP ID is listed in enterprise policy.
  66. //
  67. // At various points in the code, |Evaluate| can be called in order to process
  68. // any configured filter. Before |Evaluate| can be called, |MaybeInitialize|
  69. // must be called to check whether the filter has been updated.
  70. //
  71. // Processing stops at the first matching filter. If none match, |ALLOW| is
  72. // returned.
  73. // MaybeInitialize parses any update to the Finch-controlled filter.
  74. COMPONENT_EXPORT(DEVICE_FIDO)
  75. void MaybeInitialize();
  76. // Operation enumerates the possible operations for calling |Evaluate|.
  77. enum class Operation {
  78. MAKE_CREDENTIAL,
  79. GET_ASSERTION,
  80. };
  81. // Operation enumerates the possible types of IDs for calling |Evaluate|.
  82. enum class IDType {
  83. CREDENTIAL_ID,
  84. USER_ID,
  85. };
  86. // Action enumerates the result of evaluating a set of filterse.
  87. enum class Action {
  88. ALLOW = 1,
  89. NO_ATTESTATION = 2,
  90. BLOCK = 3,
  91. };
  92. // Evaluate consults any configured filters and returns the result of evaluating
  93. // them. See above about the format of filters.
  94. COMPONENT_EXPORT(DEVICE_FIDO)
  95. Action Evaluate(
  96. Operation op,
  97. base::StringPiece rp_id,
  98. absl::optional<base::StringPiece> device,
  99. absl::optional<std::pair<IDType, base::span<const uint8_t>>> id);
  100. // ScopedFilterForTesting sets the current filter JSON for the duration of its
  101. // lifetime. It is a fatal error if |json| is ill-formed.
  102. class COMPONENT_EXPORT(DEVICE_FIDO) ScopedFilterForTesting {
  103. public:
  104. enum class PermitInvalidJSON {
  105. kYes,
  106. };
  107. explicit ScopedFilterForTesting(base::StringPiece json);
  108. ScopedFilterForTesting(base::StringPiece json, PermitInvalidJSON);
  109. ~ScopedFilterForTesting();
  110. private:
  111. const absl::optional<std::string> previous_json_;
  112. };
  113. // ParseForTesting returns true iff |json| is a well-formed filter.
  114. COMPONENT_EXPORT(DEVICE_FIDO)
  115. bool ParseForTesting(base::StringPiece json);
  116. } // namespace fido_filter
  117. } // namespace device
  118. #endif // DEVICE_FIDO_FILTER_H_