Changeset - dffb92224edf
[Not reviewed]
beta
0 2 0
Marcin Kuzminski - 13 years ago 2012-07-31 12:15:54
marcin@python-works.com
removed ftp from allowed schemas
- added tests for the schemas fix
- moved parsing url if we only have came_from present
2 files changed with 24 insertions and 6 deletions:
0 comments (0 inline, 0 general)
rhodecode/controllers/login.py
Show inline comments
 
@@ -22,116 +22,115 @@
 
#
 
# You should have received a copy of the GNU General Public License
 
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 

	
 
import logging
 
import formencode
 
import datetime
 
import urlparse
 

	
 
from formencode import htmlfill
 
from webob.exc import HTTPFound
 
from pylons.i18n.translation import _
 
from pylons.controllers.util import abort, redirect
 
from pylons import request, response, session, tmpl_context as c, url
 

	
 
import rhodecode.lib.helpers as h
 
from rhodecode.lib.auth import AuthUser, HasPermissionAnyDecorator
 
from rhodecode.lib.base import BaseController, render
 
from rhodecode.model.db import User
 
from rhodecode.model.forms import LoginForm, RegisterForm, PasswordResetForm
 
from rhodecode.model.user import UserModel
 
from rhodecode.model.meta import Session
 

	
 

	
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class LoginController(BaseController):
 

	
 
    def __before__(self):
 
        super(LoginController, self).__before__()
 

	
 
    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':
 

	
 
            return redirect(url('home'))
 

	
 
        if request.POST:
 
            # import Login Form validator class
 
            login_form = LoginForm()
 
            try:
 
                session.invalidate()
 
                c.form_result = login_form.to_python(dict(request.POST))
 
                # form checks for username/password, now we're authenticated
 
                username = c.form_result['username']
 
                user = User.get_by_username(username, case_insensitive=True)
 
                auth_user = AuthUser(user.user_id)
 
                auth_user.set_authenticated()
 
                cs = auth_user.get_cookie_store()
 
                session['rhodecode_user'] = cs
 
                user.update_lastlogin()
 
                Session().commit()
 

	
 
                # If they want to be remembered, update the cookie
 
                if c.form_result['remember'] is not False:
 
                    _year = (datetime.datetime.now() +
 
                             datetime.timedelta(seconds=60 * 60 * 24 * 365))
 
                    session._set_cookie_expires(_year)
 

	
 
                session.save()
 

	
 
                log.info('user %s is now authenticated and stored in '
 
                         'session, session attrs %s' % (username, cs))
 

	
 
                # dumps session attrs back to cookie
 
                session._update_cookie_out()
 

	
 
                # we set new cookie
 
                headers = None
 
                if session.request['set_cookie']:
 
                    # send set-cookie headers back to response to update cookie
 
                    headers = [('Set-Cookie', session.request['cookie_out'])]
 

	
 
                allowed_schemes = ['http', 'https', 'ftp']
 
                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' %
 
                        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')
 
                if c.came_from:
 
                    raise HTTPFound(location=c.came_from, headers=headers)
 
                else:
 
                    raise HTTPFound(location=url('home'), headers=headers)
 

	
 
            except formencode.Invalid, errors:
 
                return htmlfill.render(
 
                    render('/login.html'),
 
                    defaults=errors.value,
 
                    errors=errors.error_dict or {},
 
                    prefix_error=False,
 
                    encoding="UTF-8")
 

	
 
        return render('/login.html')
 

	
 
    @HasPermissionAnyDecorator('hg.admin', 'hg.register.auto_activate',
 
                               'hg.register.manual_activate')
 
    def register(self):
 
        c.auto_active = False
 
        for perm in User.get_by_username('default').user_perms:
 
            if perm.permission.permission_name == 'hg.register.auto_activate':
 
                c.auto_active = True
 
                break
 

	
 
        if request.POST:
rhodecode/tests/functional/test_login.py
Show inline comments
 
@@ -34,48 +34,67 @@ class TestLoginController(TestController
 
    def test_login_regular_ok(self):
 
        response = self.app.post(url(controller='login', action='index'),
 
                                 {'username': 'test_regular',
 
                                  'password': 'test12'})
 

	
 
        self.assertEqual(response.status, '302 Found')
 
        self.assertEqual(response.session['rhodecode_user'].get('username'),
 
                         'test_regular')
 
        response = response.follow()
 
        self.assertTrue('%s repository' % HG_REPO in response.body)
 
        self.assertTrue('<a title="Admin" href="/_admin">' not in response.body)
 

	
 
    def test_login_ok_came_from(self):
 
        test_came_from = '/_admin/users'
 
        response = self.app.post(url(controller='login', action='index',
 
                                     came_from=test_came_from),
 
                                 {'username': 'test_admin',
 
                                  'password': 'test12'})
 
        self.assertEqual(response.status, '302 Found')
 
        response = response.follow()
 

	
 
        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',
 
                                  'password': 'as'})
 
        self.assertEqual(response.status, '200 OK')
 

	
 
        self.assertTrue('Enter 3 characters or more' in response.body)
 

	
 
    def test_login_wrong_username_password(self):
 
        response = self.app.post(url(controller='login', action='index'),
 
                                 {'username': 'error',
 
                                  'password': 'test12'})
 

	
 
        self.assertTrue('invalid user name' in response.body)
 
        self.assertTrue('invalid password' in response.body)
 

	
 
    #==========================================================================
 
    # REGISTRATIONS
 
    #==========================================================================
 
    def test_register(self):
 
        response = self.app.get(url(controller='login', action='register'))
 
        self.assertTrue('Sign Up to RhodeCode' in response.body)
 

	
 
    def test_register_err_same_username(self):
0 comments (0 inline, 0 general)