Просмотр исходного кода

Move authentication delay into __init__.py and add config

Use the delay for all backends (not only htpasswd).
Add configuration option to configure the delay.
Unrud 8 лет назад
Родитель
Сommit
f2fb07fa84
5 измененных файлов с 18 добавлено и 5 удалено
  1. 3 0
      config
  2. 9 0
      radicale/__init__.py
  3. 0 4
      radicale/auth.py
  4. 4 1
      radicale/config.py
  5. 2 0
      radicale/tests/test_auth.py

+ 3 - 0
config

@@ -78,6 +78,9 @@
 # bcrypt and md5 require the passlib library to be installed.
 #htpasswd_encryption = bcrypt
 
+# Incorrect authentication delay (seconds)
+#delay = 1
+
 
 [rights]
 

+ 9 - 0
radicale/__init__.py

@@ -34,11 +34,13 @@ import itertools
 import os
 import posixpath
 import pprint
+import random
 import socket
 import socketserver
 import ssl
 import sys
 import threading
+import time
 import traceback
 import wsgiref.simple_server
 import zlib
@@ -383,6 +385,13 @@ class Application:
             is_authenticated = False
         else:
             is_authenticated = self.Auth.is_authenticated(user, password)
+            if not is_authenticated:
+                # Random delay to avoid timing oracles and bruteforce attacks
+                delay = self.configuration.getfloat("auth", "delay")
+                if delay > 0:
+                    random_delay = delay * (0.5 + random.random())
+                    self.logger.debug("Sleeping %.3f seconds", random_delay)
+                    time.sleep(random_delay)
 
         # Create principal collection
         if user and is_authenticated:

+ 0 - 4
radicale/auth.py

@@ -58,8 +58,6 @@ import functools
 import hashlib
 import hmac
 import os
-import random
-import time
 from importlib import import_module
 
 
@@ -198,6 +196,4 @@ class Auth(BaseAuth):
                     login, hash_value = line.split(":")
                     if login == user and self.verify(hash_value, password):
                         return True
-        # Random timer to avoid timing oracles and simple bruteforce attacks
-        time.sleep(1 + random.random())
         return False

+ 4 - 1
radicale/config.py

@@ -93,7 +93,10 @@ INITIAL_CONFIG = OrderedDict([
             "help": "htpasswd filename"}),
         ("htpasswd_encryption", {
             "value": "bcrypt",
-            "help": "htpasswd encryption method"})])),
+            "help": "htpasswd encryption method"}),
+        ("delay", {
+            "value": "1",
+            "help": "incorrect authentication delay"})])),
     ("rights", OrderedDict([
         ("type", {
             "value": "owner_only",

+ 2 - 0
radicale/tests/test_auth.py

@@ -47,6 +47,8 @@ class TestBaseAuthRequests(BaseTest):
         self.configuration.set("storage", "filesystem_fsync", "False")
         # Required on Windows, doesn't matter on Unix
         self.configuration.set("storage", "close_lock_file", "True")
+        # Set incorrect authentication delay to a very low value
+        self.configuration.set("auth", "delay", "0.002")
 
     def teardown(self):
         shutil.rmtree(self.colpath)