Ver código fonte

remove webdav digest_auth

Guénaël Muller 6 anos atrás
pai
commit
c714f22ae6

+ 4 - 0
doc/apache.md Ver arquivo

@@ -109,6 +109,10 @@ Add `webdav` at `root_path` in the `[tracim_path]/tracim/wsgidav.conf`:
109 109
     
110 110
     root_path = ''
111 111
     
112
+    # Tracim doesn't support digest auth for webdav
113
+    acceptbasic = True
114
+    acceptdigest = False
115
+    defaultdigest = False
112 116
     #===============================================================================
113 117
     # Lock Manager
114 118
     #

+ 26 - 0
tracim/migration/versions/2b4043fa2502_remove_webdav_right_digest_response_.py Ver arquivo

@@ -0,0 +1,26 @@
1
+"""remove webdav_right_digest_response_hash from database
2
+
3
+Revision ID: 2b4043fa2502
4
+Revises: f3852e1349c4
5
+Create Date: 2018-03-13 14:41:38.590375
6
+
7
+"""
8
+
9
+# revision identifiers, used by Alembic.
10
+revision = '2b4043fa2502'
11
+down_revision = 'f3852e1349c4'
12
+
13
+from alembic import op
14
+from sqlalchemy import Column, Unicode
15
+
16
+
17
+def upgrade():
18
+    with op.batch_alter_table('users') as batch_op:
19
+        batch_op.drop_column('webdav_left_digest_response_hash')
20
+
21
+
22
+def downgrade():
23
+    with op.batch_alter_table('users') as batch_op:
24
+        batch_op.add_column(
25
+            Column('webdav_left_digest_response_hash', Unicode(128))
26
+        )

+ 2 - 2
tracim/tracim/lib/daemons.py Ver arquivo

@@ -390,14 +390,14 @@ class WsgiDavDaemon(Daemon):
390 390
             print(
391 391
                 "WARNING: Could not import lxml: using xml instead (slower). Consider installing lxml from http://codespeak.net/lxml/.")
392 392
         from wsgidav.dir_browser import WsgiDavDirBrowser
393
-        from tracim.lib.webdav.tracim_http_authenticator import TracimHTTPAuthenticator
393
+        from wsgidav.http_authenticator import HTTPAuthenticator
394 394
         from wsgidav.error_printer import ErrorPrinter
395 395
         from tracim.lib.webdav.utils import TracimWsgiDavDebugFilter
396 396
 
397 397
         config['middleware_stack'] = [
398 398
             TracimEnforceHTTPS,
399 399
             WsgiDavDirBrowser,
400
-            TracimHTTPAuthenticator,
400
+            HTTPAuthenticator,
401 401
             ErrorPrinter,
402 402
             TracimWsgiDavDebugFilter,
403 403
         ]

+ 7 - 17
tracim/tracim/lib/webdav/sql_domain_controller.py Ver arquivo

@@ -2,6 +2,9 @@
2 2
 
3 3
 from tracim.lib.user import UserApi
4 4
 
5
+class DigestAuthNotImplemented(Exception):
6
+    pass
7
+
5 8
 class TracimDomainController(object):
6 9
     """
7 10
     The domain controller is used by http_authenticator to authenticate the user every time a request is
@@ -15,13 +18,11 @@ class TracimDomainController(object):
15 18
 
16 19
     def getRealmUserPassword(self, realmname, username, environ):
17 20
         """
18
-        Warning ! This return hashed version of password !
21
+        This method is normally only use for digest auth. wsgidav need
22
+        plain password to deal with it. as we didn't
23
+        provide support for this kind of auth, this method raise an exception.
19 24
         """
20
-        try:
21
-            user = self._api.get_one_by_email(username)
22
-            return user.password
23
-        except:
24
-            return False
25
+        raise DigestAuthNotImplemented
25 26
 
26 27
     def requireAuthentication(self, realmname, environ):
27 28
         return True
@@ -37,17 +38,6 @@ class TracimDomainController(object):
37 38
         except:
38 39
             return False
39 40
 
40
-    def get_left_digest_response_hash(self, realmname, username, environ):
41
-        """
42
-        Called by our http_authenticator to get the hashed md5 digest for the current user that is also sent by
43
-        the webdav client
44
-        """
45
-        try:
46
-            user = self._api.get_one_by_email(username)
47
-            return user.webdav_left_digest_response_hash
48
-        except:
49
-            return None
50
-
51 41
     def authDomainUser(self, realmname, username, password, environ):
52 42
         """
53 43
         If you ever feel the need to send a request al-mano with a curl, this is the function that'll be called by

+ 0 - 76
tracim/tracim/lib/webdav/tracim_http_authenticator.py Ver arquivo

@@ -1,76 +0,0 @@
1
-from wsgidav.http_authenticator import HTTPAuthenticator
2
-from wsgidav import util
3
-
4
-_logger = util.getModuleLogger(__name__, True)
5
-
6
-
7
-class TracimHTTPAuthenticator(HTTPAuthenticator):
8
-    def computeDigestResponse(
9
-            self,
10
-            username,
11
-            realm,
12
-            password,
13
-            method,
14
-            uri,
15
-            nonce,
16
-            cnonce,
17
-            qop,
18
-            nc
19
-    ):
20
-        """
21
-        Override standard computeDigestResponse : as user password is already
22
-        hashed in database, we need to use left_digest_response_hash
23
-        to have correctly hashed digest_response.
24
-        """
25
-
26
-        # TODO - G.M - 13-03-2018 Check if environ is useful
27
-        # for get_left_digest_response. If true, find a solution
28
-        # to obtain it here without recopy-paste whole authDigestAuthRequest
29
-        # method.
30
-        left_digest_response_hash = self._domaincontroller.get_left_digest_response_hash(realm, username, None)  # nopep8
31
-        if left_digest_response_hash:
32
-            return self.tracim_compute_digest_response(
33
-                left_digest_response_hash=left_digest_response_hash,
34
-                method=method,
35
-                uri=uri,
36
-                nonce=nonce,
37
-                cnonce=cnonce,
38
-                qop=qop,
39
-                nc=nc,
40
-            )
41
-        else:
42
-            return None
43
-
44
-    def tracim_compute_digest_response(
45
-            self,
46
-            left_digest_response_hash,
47
-            method,
48
-            uri,
49
-            nonce,
50
-            cnonce,
51
-            qop,
52
-            nc
53
-    ):
54
-        # TODO : Rename A to something more correct
55
-        A = "{method}:{uri}".format(method=method, uri=uri)
56
-        if qop:
57
-            right_digest_response_hash = "{nonce}:{nc}:{cnonce}:{qop}:{A}".format(  # nopep8
58
-                nonce=nonce,
59
-                nc=nc,
60
-                cnonce=cnonce,
61
-                qop=qop,
62
-                method=method,
63
-                uri=uri,
64
-                A=self.md5h(A),
65
-            )
66
-        else:
67
-            right_digest_response_hash = "{nonce}:{A}".format(
68
-                nonce=nonce,
69
-                A=self.md5h(A),
70
-            )
71
-        digestresp = self.md5kd(
72
-            left_digest_response_hash,
73
-            right_digest_response_hash,
74
-        )
75
-
76
-        return digestresp

+ 0 - 25
tracim/tracim/model/auth.py Ver arquivo

@@ -128,7 +128,6 @@ class User(DeclarativeBase):
128 128
     is_active = Column(Boolean, default=True, nullable=False)
129 129
     imported_from = Column(Unicode(32), nullable=True)
130 130
     timezone = Column(Unicode(255), nullable=False, server_default='')
131
-    _webdav_left_digest_response_hash = Column('webdav_left_digest_response_hash', Unicode(128))
132 131
     auth_token = Column(Unicode(255))
133 132
     auth_token_created = Column(DateTime)
134 133
 
@@ -202,10 +201,8 @@ class User(DeclarativeBase):
202 201
 
203 202
         Hash cleartext password on the fly,
204 203
         Store its ciphertext version,
205
-        Update the WebDAV hash as well.
206 204
         """
207 205
         self._password = self._hash_password(cleartext_password)
208
-        self.update_webdav_digest_auth(cleartext_password)
209 206
 
210 207
     def _get_password(self) -> str:
211 208
         """Return the hashed version of the password."""
@@ -214,26 +211,6 @@ class User(DeclarativeBase):
214 211
     password = synonym('_password', descriptor=property(_get_password,
215 212
                                                         _set_password))
216 213
 
217
-    @classmethod
218
-    def _hash_digest(cls, digest):
219
-        return md5(bytes(digest, 'utf-8')).hexdigest()
220
-
221
-    def _set_hash_digest(self, digest):
222
-        self._webdav_left_digest_response_hash = self._hash_digest(digest)
223
-
224
-    def _get_hash_digest(self):
225
-        return self._webdav_left_digest_response_hash
226
-
227
-    webdav_left_digest_response_hash = synonym('_webdav_left_digest_response_hash',
228
-                                               descriptor=property(_get_hash_digest,
229
-                                                                   _set_hash_digest))
230
-
231
-    def update_webdav_digest_auth(self, cleartext_password: str) -> None:
232
-        self.webdav_left_digest_response_hash \
233
-            = '{username}:/:{cleartext_password}'.format(
234
-                username=self.email,
235
-                cleartext_password=cleartext_password,
236
-            )
237 214
 
238 215
     def validate_password(self, cleartext_password: str) -> bool:
239 216
         """
@@ -252,8 +229,6 @@ class User(DeclarativeBase):
252 229
             hash = sha256()
253 230
             hash.update((cleartext_password + self.password[:64]).encode('utf-8'))
254 231
             result = self.password[64:] == hash.hexdigest()
255
-            if result and not self.webdav_left_digest_response_hash:
256
-                self.update_webdav_digest_auth(cleartext_password)
257 232
         return result
258 233
 
259 234
     def get_display_name(self, remove_email_part: bool=False) -> str:

+ 0 - 6
tracim/tracim/tests/command/user.py Ver arquivo

@@ -14,7 +14,6 @@ class TestUserCommand(TestCommand):
14 14
         # Check webdav digest exist for this user
15 15
         user = DBSession.query(User)\
16 16
             .filter(User.email == 'new-user@algoo.fr').one()
17
-        ok_(user.webdav_left_digest_response_hash)
18 17
 
19 18
     def test_update_password(self):
20 19
         self._create_user('new-user@algoo.fr', 'toor')
@@ -22,7 +21,6 @@ class TestUserCommand(TestCommand):
22 21
         # Grab webdav digest
23 22
         user = DBSession.query(User) \
24 23
             .filter(User.email == 'new-user@algoo.fr').one()
25
-        webdav_digest = user.webdav_left_digest_response_hash
26 24
 
27 25
         self._execute_command(
28 26
             UpdateUserCommand,
@@ -35,10 +33,6 @@ class TestUserCommand(TestCommand):
35 33
         # Grab new webdav digest to compare it
36 34
         user = DBSession.query(User) \
37 35
             .filter(User.email == 'new-user@algoo.fr').one()
38
-        ok_(
39
-            webdav_digest != user.webdav_left_digest_response_hash,
40
-            msg='Webdav digest should be different',
41
-        )
42 36
 
43 37
     def test_create_with_group(self):
44 38
         more_args = ['--add-to-group', 'managers', '--add-to-group', 'administrators']

+ 0 - 8
tracim/tracim/tests/functional/test_admin.py Ver arquivo

@@ -43,9 +43,6 @@ class TestAuthentication(TracimTestController):
43 43
         ok_(user, msg="User should exist now")
44 44
         ok_(user.validate_password('password'))
45 45
 
46
-        # User must have webdav digest
47
-        ok_(user.webdav_left_digest_response_hash)
48
-
49 46
     def test_update_user_password(self):
50 47
         self._connect_user(
51 48
             'admin@admin.admin',
@@ -67,7 +64,6 @@ class TestAuthentication(TracimTestController):
67 64
 
68 65
         user = DBSession.query(User) \
69 66
             .filter(User.email == 'an-other-email@test.local').one()
70
-        webdav_digest = user.webdav_left_digest_response_hash
71 67
 
72 68
         self.app.post(
73 69
             '/admin/users/{user_id}/password?_method=PUT'.format(
@@ -82,7 +78,3 @@ class TestAuthentication(TracimTestController):
82 78
         user = DBSession.query(User) \
83 79
             .filter(User.email == 'an-other-email@test.local').one()
84 80
         ok_(user.validate_password('new-password'))
85
-        ok_(
86
-            webdav_digest != user.webdav_left_digest_response_hash,
87
-            msg='Webdav digest should be updated',
88
-        )

+ 0 - 5
tracim/tracim/tests/functional/test_user.py Ver arquivo

@@ -22,7 +22,6 @@ class TestAuthentication(TracimTestController):
22 22
 
23 23
         user = DBSession.query(User) \
24 24
             .filter(User.email == 'lawrence-not-real-email@fsf.local').one()
25
-        webdav_digest = user.webdav_left_digest_response_hash
26 25
 
27 26
         try_post_user = self.app.post(
28 27
             '/user/{user_id}/password?_method=PUT'.format(
@@ -40,7 +39,3 @@ class TestAuthentication(TracimTestController):
40 39
         user = DBSession.query(User) \
41 40
             .filter(User.email == 'lawrence-not-real-email@fsf.local').one()
42 41
         ok_(user.validate_password('new-password'))
43
-        ok_(
44
-            webdav_digest != user.webdav_left_digest_response_hash,
45
-            msg='Webdav digest should be updated',
46
-        )

+ 4 - 0
tracim/wsgidav.conf.sample Ver arquivo

@@ -25,6 +25,10 @@ manager_locks = True
25 25
 
26 26
 root_path = ''
27 27
 
28
+# Tracim doesn't support digest auth for webdav
29
+acceptbasic = True
30
+acceptdigest = False
31
+defaultdigest = False
28 32
 #===============================================================================
29 33
 # Lock Manager
30 34
 #