IThrottler.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  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. */
  41. public const MAX_DELAY = 25;
  42. /**
  43. * @since 25.0.0
  44. */
  45. public const MAX_DELAY_MS = 25000; // in milliseconds
  46. /**
  47. * @since 25.0.0
  48. */
  49. public const MAX_ATTEMPTS = 10;
  50. /**
  51. * Register a failed attempt to bruteforce a security control
  52. *
  53. * @param string $action
  54. * @param string $ip
  55. * @param array $metadata Optional metadata logged to the database
  56. * @since 25.0.0
  57. */
  58. public function registerAttempt(string $action, string $ip, array $metadata = []): void;
  59. /**
  60. * Get the throttling delay (in milliseconds)
  61. *
  62. * @param string $ip
  63. * @param string $action optionally filter by action
  64. * @param float $maxAgeHours
  65. * @return int
  66. * @since 25.0.0
  67. */
  68. public function getAttempts(string $ip, string $action = '', float $maxAgeHours = 12): int;
  69. /**
  70. * Get the throttling delay (in milliseconds)
  71. *
  72. * @param string $ip
  73. * @param string $action optionally filter by action
  74. * @return int
  75. * @since 25.0.0
  76. */
  77. public function getDelay(string $ip, string $action = ''): int;
  78. /**
  79. * Reset the throttling delay for an IP address, action and metadata
  80. *
  81. * @param string $ip
  82. * @param string $action
  83. * @param array $metadata
  84. * @since 25.0.0
  85. */
  86. public function resetDelay(string $ip, string $action, array $metadata): void;
  87. /**
  88. * Reset the throttling delay for an IP address
  89. *
  90. * @param string $ip
  91. * @since 25.0.0
  92. */
  93. public function resetDelayForIP(string $ip): void;
  94. /**
  95. * Will sleep for the defined amount of time
  96. *
  97. * @param string $ip
  98. * @param string $action optionally filter by action
  99. * @return int the time spent sleeping
  100. * @since 25.0.0
  101. */
  102. public function sleepDelay(string $ip, string $action = ''): int;
  103. /**
  104. * Will sleep for the defined amount of time unless maximum was reached in the last 30 minutes
  105. * In this case a "429 Too Many Request" exception is thrown
  106. *
  107. * @param string $ip
  108. * @param string $action optionally filter by action
  109. * @return int the time spent sleeping
  110. * @throws MaxDelayReached when reached the maximum
  111. * @since 25.0.0
  112. */
  113. public function sleepDelayOrThrowOnMax(string $ip, string $action = ''): int;
  114. }