# HG changeset patch # User Marcin Kuzminski # Date 2010-11-25 22:58:28 # Node ID 56c2850a5b5fe9cde55e2236201969bdf552ce9a # Parent fb7a3b291e6437e2acba801914c1d5eba327a962 ldap auth rewrite, moved split authfunc into two functions, made ldap case insensitive for uids added some extra debug messages for ldap, and auth function added some docs for utils diff --git a/rhodecode/controllers/login.py b/rhodecode/controllers/login.py --- a/rhodecode/controllers/login.py +++ b/rhodecode/controllers/login.py @@ -57,7 +57,7 @@ class LoginController(BaseController): try: c.form_result = login_form.to_python(dict(request.POST)) username = c.form_result['username'] - user = UserModel().get_by_username(username) + user = UserModel().get_by_username(username, case_insensitive=True) auth_user = AuthUser() auth_user.username = user.username auth_user.is_authenticated = True diff --git a/rhodecode/lib/auth.py b/rhodecode/lib/auth.py --- a/rhodecode/lib/auth.py +++ b/rhodecode/lib/auth.py @@ -77,38 +77,45 @@ def check_password(password, hashed): def authfunc(environ, username, password): """ - Authentication function used in Mercurial/Git/ and access control, + Dummy authentication function used in Mercurial/Git/ and access control, + + :param environ: needed only for using in Basic auth + """ + return authenticate(username, password) + + +def authenticate(username, password): + """ + Authentication function used for access control, firstly checks for db authentication then if ldap is enabled for ldap authentication, also creates ldap user if not in database - :param environ: needed only for using in Basic auth, can be None :param username: username :param password: password """ user_model = UserModel() user = user_model.get_by_username(username, cache=False) + log.debug('Authenticating user using RhodeCode account') if user is not None and user.is_ldap is False: if user.active: if user.username == 'default' and user.active: - log.info('user %s authenticated correctly', username) + log.info('user %s authenticated correctly as anonymous user', + username) return True elif user.username == username and check_password(password, user.password): log.info('user %s authenticated correctly', username) return True else: - log.error('user %s is disabled', username) - + log.warning('user %s is disabled', username) else: - - #since ldap is searching in case insensitive check if this user is still - #not in our system - username = username.lower() + log.debug('Regular authentication failed') user_obj = user_model.get_by_username(username, cache=False, case_insensitive=True) + if user_obj is not None and user_obj.is_ldap is False: log.debug('this user already exists as non ldap') return False @@ -120,7 +127,7 @@ def authfunc(environ, username, password # FALLBACK TO LDAP AUTH IN ENABLE #====================================================================== if ldap_settings.get('ldap_active', False): - + log.debug("Authenticating user using ldap") kwargs = { 'server':ldap_settings.get('ldap_host', ''), 'base_dn':ldap_settings.get('ldap_base_dn', ''), @@ -134,18 +141,17 @@ def authfunc(environ, username, password try: aldap = AuthLdap(**kwargs) res = aldap.authenticate_ldap(username, password) + log.debug('Got ldap response %s', res) - authenticated = res[1]['uid'][0] == username - - if authenticated and user_model.create_ldap(username, password): + if user_model.create_ldap(username, password): log.info('created new ldap user') - return authenticated - except (LdapUsernameError, LdapPasswordError): - return False - except: + return True + except (LdapUsernameError, LdapPasswordError,): + pass + except (Exception,): log.error(traceback.format_exc()) - return False + pass return False class AuthUser(object): diff --git a/rhodecode/lib/utils.py b/rhodecode/lib/utils.py --- a/rhodecode/lib/utils.py +++ b/rhodecode/lib/utils.py @@ -128,6 +128,13 @@ def get_repos(path, recursive=False, ini pass def check_repo_fast(repo_name, base_path): + """ + Check given path for existance of directory + :param repo_name: + :param base_path: + + :return False: if this directory is present + """ if os.path.isdir(os.path.join(base_path, repo_name)):return False return True diff --git a/rhodecode/model/forms.py b/rhodecode/model/forms.py --- a/rhodecode/model/forms.py +++ b/rhodecode/model/forms.py @@ -19,24 +19,27 @@ list=[1,2,3,4,5] for SELECT use formencode.All(OneOf(list), Int()) """ +import os +import re +import logging + +import formencode from formencode import All from formencode.validators import UnicodeString, OneOf, Int, Number, Regex, \ Email, Bool, StringBoolean -from pylons import session + from pylons.i18n.translation import _ -from rhodecode.lib.auth import authfunc, get_crypt_password + +import rhodecode.lib.helpers as h +from rhodecode.lib.auth import authenticate, get_crypt_password from rhodecode.lib.exceptions import LdapImportError from rhodecode.model import meta from rhodecode.model.user import UserModel from rhodecode.model.repo import RepoModel from rhodecode.model.db import User +from rhodecode import BACKENDS + from webhelpers.pylonslib.secure_form import authentication_token -from rhodecode import BACKENDS -import formencode -import logging -import os -import re -import rhodecode.lib.helpers as h log = logging.getLogger(__name__) @@ -142,7 +145,7 @@ class ValidAuth(formencode.validators.Fa username = value['username'] user = UserModel().get_by_username(username) - if authfunc(None, username, password): + if authenticate(username, password): return value else: if user and user.active is False: diff --git a/rhodecode/model/user.py b/rhodecode/model/user.py --- a/rhodecode/model/user.py +++ b/rhodecode/model/user.py @@ -1,8 +1,14 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Model for users -# Copyright (C) 2009-2010 Marcin Kuzminski -# +# -*- coding: utf-8 -*- +""" + package.rhodecode.model.user + ~~~~~~~~~~~~~~ + + users model for RhodeCode + :created_on: Apr 9, 2010 + :author: marcink + :copyright: (C) 2009-2010 Marcin Kuzminski + :license: GPLv3, see COPYING for more details. +""" # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; version 2 @@ -17,24 +23,21 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. -""" -Created on April 9, 2010 -Model for users -:author: marcink -""" - -from pylons.i18n.translation import _ -from rhodecode.model import BaseModel -from rhodecode.model.caching_query import FromCache -from rhodecode.model.db import User -from rhodecode.lib.exceptions import * import logging import traceback -log = logging.getLogger(__name__) +from pylons.i18n.translation import _ + +from rhodecode.model import BaseModel +from rhodecode.model.caching_query import FromCache +from rhodecode.model.db import User +from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException +from sqlalchemy.exc import DatabaseError + +log = logging.getLogger(__name__) class UserModel(BaseModel): @@ -79,10 +82,11 @@ class UserModel(BaseModel): :param password: """ from rhodecode.lib.auth import get_crypt_password - if self.get_by_username(username) is None: + log.debug('Checking for such ldap account in RhodeCode database') + if self.get_by_username(username, case_insensitive=True) is None: try: new_user = User() - new_user.username = username + new_user.username = username.lower()#add ldap account always lowercase new_user.password = get_crypt_password(password) new_user.email = '%s@ldap.server' % username new_user.active = True @@ -94,11 +98,12 @@ class UserModel(BaseModel): self.sa.add(new_user) self.sa.commit() return True - except: + except (DatabaseError,): log.error(traceback.format_exc()) self.sa.rollback() raise - + log.debug('this %s user exists skipping creation of ldap account', + username) return False def create_registration(self, form_data):