فهرست منبع

Fix Medusa auth handler when password has a colon. Closes #309

Mike Naberezny 11 سال پیش
والد
کامیت
c4c2f8bf68
4فایلهای تغییر یافته به همراه53 افزوده شده و 7 حذف شده
  1. 4 0
      CHANGES.txt
  2. 1 1
      supervisor/medusa/auth_handler.py
  3. 3 0
      supervisor/tests/base.py
  4. 45 6
      supervisor/tests/test_http.py

+ 4 - 0
CHANGES.txt

@@ -21,6 +21,10 @@
 - Changed ``supervisorctl`` to reuse the server proxy object between commands
   to reduce the number of open connections.  Patch by Zev Benjamin.
 
+- Fixed a bug in Medusa where the HTTP Basic authorizer would cause an
+  exception if the password contained a colon.  Thanks to Thomas Guttler
+  for reporting this issue.
+
 3.0 (2013-07-30)
 ----------------
 

+ 1 - 1
supervisor/medusa/auth_handler.py

@@ -57,7 +57,7 @@ class auth_handler:
                     print 'malformed authorization info <%s>' % cookie
                     request.error (400)
                     return
-                auth_info = decoded.split(':')
+                auth_info = decoded.split(':', 1)
                 if self.authorizer.authorize (auth_info):
                     self.pass_count.increment()
                     request.auth_info = auth_info

+ 3 - 0
supervisor/tests/base.py

@@ -597,6 +597,9 @@ class DummyMedusaChannel:
     def close_when_done(self):
         pass
 
+    def set_terminator(self, terminator):
+        pass
+
 class DummyRequest:
     command = 'GET'
     _error = None

+ 45 - 6
supervisor/tests/test_http.py

@@ -1,6 +1,7 @@
-import sys
+import base64
 import os
 import socket
+import sys
 import tempfile
 import unittest
 
@@ -265,25 +266,29 @@ class EncryptedDictionaryAuthorizedTests(unittest.TestCase):
 
     def test_authorize_baduser(self):
         authorizer = self._makeOne({})
-        self.assertEqual(authorizer.authorize(('foo', 'bar')), False)
+        self.assertFalse(authorizer.authorize(('foo', 'bar')))
 
     def test_authorize_gooduser_badpassword(self):
         authorizer = self._makeOne({'foo':'password'})
-        self.assertEqual(authorizer.authorize(('foo', 'bar')), False)
+        self.assertFalse(authorizer.authorize(('foo', 'bar')))
 
     def test_authorize_gooduser_goodpassword(self):
         authorizer = self._makeOne({'foo':'password'})
-        self.assertEqual(authorizer.authorize(('foo', 'password')), True)
+        self.assertTrue(authorizer.authorize(('foo', 'password')))
+
+    def test_authorize_gooduser_goodpassword_with_colon(self):
+        authorizer = self._makeOne({'foo':'pass:word'})
+        self.assertTrue(authorizer.authorize(('foo', 'pass:word')))
 
     def test_authorize_gooduser_badpassword_sha(self):
         password = '{SHA}' + sha1('password').hexdigest()
         authorizer = self._makeOne({'foo':password})
-        self.assertEqual(authorizer.authorize(('foo', 'bar')), False)
+        self.assertFalse(authorizer.authorize(('foo', 'bar')))
 
     def test_authorize_gooduser_goodpassword_sha(self):
         password = '{SHA}' + sha1('password').hexdigest()
         authorizer = self._makeOne({'foo':password})
-        self.assertEqual(authorizer.authorize(('foo', 'password')), True)
+        self.assertTrue(authorizer.authorize(('foo', 'password')))
 
 class SupervisorAuthHandlerTests(unittest.TestCase):
     def _getTargetClass(self):
@@ -299,6 +304,33 @@ class SupervisorAuthHandlerTests(unittest.TestCase):
         self.assertEqual(handler.authorizer.__class__,
                          encrypted_dictionary_authorizer)
 
+    def test_handle_request_authorizes_good_credentials(self):
+        request = DummyRequest('/logtail/process1', None, None, None)
+        encoded = base64.b64encode("user:password")
+        request.header = ["Authorization: Basic %s" % encoded]
+        handler = DummyHandler()
+        auth_handler = self._makeOne({'user':'password'}, handler)
+        auth_handler.handle_request(request)
+        self.assertTrue(handler.handled_request)
+
+    def test_handle_request_authorizes_good_password_with_colon(self):
+        request = DummyRequest('/logtail/process1', None, None, None)
+        encoded = base64.b64encode("user:pass:word") # password contains colon
+        request.header = ["Authorization: Basic %s" % encoded]
+        handler = DummyHandler()
+        auth_handler = self._makeOne({'user':'pass:word'}, handler)
+        auth_handler.handle_request(request)
+        self.assertTrue(handler.handled_request)
+
+    def test_handle_request_does_not_authorize_bad_credentials(self):
+        request = DummyRequest('/logtail/process1', None, None, None)
+        encoded = base64.b64encode("wrong:wrong")
+        request.header = ["Authorization: Basic %s" % encoded]
+        handler = DummyHandler()
+        auth_handler = self._makeOne({'user':'password'}, handler)
+        auth_handler.handle_request(request)
+        self.assertFalse(handler.handled_request)
+
 
 class TopLevelFunctionTests(unittest.TestCase):
     def _make_http_servers(self, sconfigs):
@@ -362,6 +394,13 @@ class TopLevelFunctionTests(unittest.TestCase):
                 self.assertTrue(isinstance(handler, supervisor_auth_handler),
                                 handler)
 
+class DummyHandler:
+    def __init__(self):
+        self.handled_request = False
+
+    def handle_request(self, request):
+        self.handled_request = True
+
 class DummyProducer:
     def __init__(self, *data):
         self.data = list(data)