IThrottler.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * @copyright Copyright (c) 2022 Joas Schilling <coding@schilljs.com>
  5. *
  6. * @license GNU AGPL version 3 or any later version
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU Affero General Public License as
  10. * published by the Free Software Foundation, either version 3 of the
  11. * License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU Affero General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Affero General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. namespace OCP\Security\Bruteforce;
  23. /**
  24. * Class Throttler implements the bruteforce protection for security actions in
  25. * Nextcloud.
  26. *
  27. * It is working by logging invalid login attempts to the database and slowing
  28. * down all login attempts from the same subnet. The max delay is 30 seconds and
  29. * the starting delay are 200 milliseconds. (after the first failed login)
  30. *
  31. * This is based on Paragonie's AirBrake for Airship CMS. You can find the original
  32. * code at https://github.com/paragonie/airship/blob/7e5bad7e3c0fbbf324c11f963fd1f80e59762606/src/Engine/Security/AirBrake.php
  33. *
  34. * @package OC\Security\Bruteforce
  35. * @since 25.0.0
  36. */
  37. interface IThrottler {
  38. /**
  39. * @since 25.0.0
  40. * @deprecated 28.0.0
  41. */
  42. public const MAX_DELAY = 25;
  43. /**
  44. * @since 25.0.0
  45. * @deprecated 28.0.0
  46. */
  47. public const MAX_DELAY_MS = 25000; // in milliseconds
  48. /**
  49. * @since 25.0.0
  50. * @deprecated 28.0.0
  51. */
  52. public const MAX_ATTEMPTS = 10;
  53. /**
  54. * Register a failed attempt to bruteforce a security control
  55. *
  56. * @param string $action
  57. * @param string $ip
  58. * @param array $metadata Optional metadata logged with the attempt
  59. * @since 25.0.0
  60. */
  61. public function registerAttempt(string $action, string $ip, array $metadata = []): void;
  62. /**
  63. * Check if the IP is allowed to bypass the brute force protection
  64. *
  65. * @param string $ip
  66. * @return bool
  67. * @since 28.0.0
  68. */
  69. public function isBypassListed(string $ip): bool;
  70. /**
  71. * Get the throttling delay (in milliseconds)
  72. *
  73. * @param string $ip
  74. * @param string $action optionally filter by action
  75. * @param float $maxAgeHours
  76. * @return int
  77. * @since 25.0.0
  78. * @deprecated 28.0.0 This method is considered internal as of Nextcloud 28. Use {@see showBruteforceWarning()} to decide whether a warning should be shown.
  79. */
  80. public function getAttempts(string $ip, string $action = '', float $maxAgeHours = 12): int;
  81. /**
  82. * Whether a warning should be shown about the throttle
  83. *
  84. * @param string $ip
  85. * @param string $action optionally filter by action
  86. * @return bool
  87. * @since 28.0.0
  88. */
  89. public function showBruteforceWarning(string $ip, string $action = ''): bool;
  90. /**
  91. * Get the throttling delay (in milliseconds)
  92. *
  93. * @param string $ip
  94. * @param string $action optionally filter by action
  95. * @return int
  96. * @since 25.0.0
  97. * @deprecated 28.0.0 This method is considered internal as of Nextcloud 28. Use {@see showBruteforceWarning()} to decide whether a warning should be shown.
  98. */
  99. public function getDelay(string $ip, string $action = ''): int;
  100. /**
  101. * Reset the throttling delay for an IP address, action and metadata
  102. *
  103. * @param string $ip
  104. * @param string $action
  105. * @param array $metadata
  106. * @since 25.0.0
  107. */
  108. public function resetDelay(string $ip, string $action, array $metadata): void;
  109. /**
  110. * Reset the throttling delay for an IP address
  111. *
  112. * @param string $ip
  113. * @since 25.0.0
  114. * @deprecated 28.0.0 This method is considered internal as of Nextcloud 28. Use {@see resetDelay()} and only reset the entries of your action and metadata
  115. */
  116. public function resetDelayForIP(string $ip): void;
  117. /**
  118. * Will sleep for the defined amount of time
  119. *
  120. * @param string $ip
  121. * @param string $action optionally filter by action
  122. * @return int the time spent sleeping
  123. * @since 25.0.0
  124. * @deprecated 28.0.0 Use {@see sleepDelayOrThrowOnMax()} instead and abort handling the request when it throws
  125. */
  126. public function sleepDelay(string $ip, string $action = ''): int;
  127. /**
  128. * Will sleep for the defined amount of time unless maximum was reached in the last 30 minutes
  129. * In this case a "429 Too Many Request" exception is thrown
  130. *
  131. * @param string $ip
  132. * @param string $action optionally filter by action
  133. * @return int the time spent sleeping
  134. * @throws MaxDelayReached when reached the maximum
  135. * @since 25.0.0
  136. */
  137. public function sleepDelayOrThrowOnMax(string $ip, string $action = ''): int;
  138. }