changeset 2679:dffb92224edf beta

removed ftp from allowed schemas - added tests for the schemas fix - moved parsing url if we only have came_from present
author Marcin Kuzminski <marcin@python-works.com>
date Tue, 31 Jul 2012 12:15:54 +0200
parents 04d2bcfbe7a6
children 3b179f1ac3a2
files rhodecode/controllers/login.py rhodecode/tests/functional/test_login.py
diffstat 2 files changed, 33 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/rhodecode/controllers/login.py	Tue Jul 31 00:27:22 2012 +0200
+++ b/rhodecode/controllers/login.py	Tue Jul 31 12:15:54 2012 +0200
@@ -43,7 +43,6 @@
 from rhodecode.model.meta import Session
 
 
-
 log = logging.getLogger(__name__)
 
 
@@ -54,7 +53,7 @@
 
     def index(self):
         # redirect if already logged in
-        c.came_from = request.GET.get('came_from', None)
+        c.came_from = request.GET.get('came_from')
 
         if self.rhodecode_user.is_authenticated \
                             and self.rhodecode_user.username != 'default':
@@ -97,20 +96,20 @@
                     # send set-cookie headers back to response to update cookie
                     headers = [('Set-Cookie', session.request['cookie_out'])]
 
-                allowed_schemes = ['http', 'https', 'ftp']
-                parsed = urlparse.urlparse(c.came_from)
-                server_parsed = urlparse.urlparse(url.current())
-
-                if parsed.scheme and parsed.scheme not in allowed_schemes:
-                    log.error('Suspicious URL scheme detected %s for url %s' %
-                              (parsed.scheme, parsed))
-                    c.came_from = url('home')
-                elif server_parsed.netloc != parsed.netloc:
-                    log.error('Suspicious NETLOC detected %s for url %s'
-                              'server url is: %s' %
-                              (parsed.netloc, parsed, server_parsed))
-                    c.came_from = url('home')
+                allowed_schemes = ['http', 'https']
                 if c.came_from:
+                    parsed = urlparse.urlparse(c.came_from)
+                    server_parsed = urlparse.urlparse(url.current())
+                    if parsed.scheme and parsed.scheme not in allowed_schemes:
+                        log.error(
+                            'Suspicious URL scheme detected %s for url %s' %
+                            (parsed.scheme, parsed))
+                        c.came_from = url('home')
+                    elif server_parsed.netloc != parsed.netloc:
+                        log.error('Suspicious NETLOC detected %s for url %s'
+                                  'server url is: %s' %
+                                  (parsed.netloc, parsed, server_parsed))
+                        c.came_from = url('home')
                     raise HTTPFound(location=c.came_from, headers=headers)
                 else:
                     raise HTTPFound(location=url('home'), headers=headers)
--- a/rhodecode/tests/functional/test_login.py	Tue Jul 31 00:27:22 2012 +0200
+++ b/rhodecode/tests/functional/test_login.py	Tue Jul 31 12:15:54 2012 +0200
@@ -55,6 +55,25 @@
         self.assertEqual(response.status, '200 OK')
         self.assertTrue('Users administration' in response.body)
 
+    @parameterized.expand([
+          ('data:text/html,<script>window.alert("xss")</script>',),
+          ('mailto:test@rhodecode.org',),
+          ('file:///etc/passwd',),
+          ('ftp://some.ftp.server',),
+          ('http://other.domain',),
+    ])
+    def test_login_bad_came_froms(self, url_came_from):
+        response = self.app.post(url(controller='login', action='index',
+                                     came_from=url_came_from),
+                                 {'username': 'test_admin',
+                                  'password': 'test12'})
+        self.assertEqual(response.status, '302 Found')
+        self.assertEqual(response._environ['paste.testing_variables']
+                         ['tmpl_context'].came_from, '/')
+        response = response.follow()
+
+        self.assertEqual(response.status, '200 OK')
+
     def test_login_short_password(self):
         response = self.app.post(url(controller='login', action='index'),
                                  {'username': 'test_admin',