##// END OF EJS Templates
pep8
marcink -
r1170:6a9a5af4 beta
parent child Browse files
Show More
@@ -1,126 +1,130 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # ldap authentication lib
3 # ldap authentication lib
4 # Copyright (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20 """
20 """
21 Created on Nov 17, 2010
21 Created on Nov 17, 2010
22
22
23 @author: marcink
23 @author: marcink
24 """
24 """
25
25
26 from rhodecode.lib.exceptions import *
26 from rhodecode.lib.exceptions import *
27 import logging
27 import logging
28
28
29 log = logging.getLogger(__name__)
29 log = logging.getLogger(__name__)
30
30
31 try:
31 try:
32 import ldap
32 import ldap
33 except ImportError:
33 except ImportError:
34 pass
34 pass
35
35
36 class AuthLdap(object):
36 class AuthLdap(object):
37
37
38 def __init__(self, server, base_dn, port=389, bind_dn='', bind_pass='',
38 def __init__(self, server, base_dn, port=389, bind_dn='', bind_pass='',
39 use_ldaps=False, tls_reqcert='DEMAND', ldap_version=3,
39 use_ldaps=False, tls_reqcert='DEMAND', ldap_version=3,
40 ldap_filter='(&(objectClass=user)(!(objectClass=computer)))',
40 ldap_filter='(&(objectClass=user)(!(objectClass=computer)))',
41 search_scope='SUBTREE',
41 search_scope='SUBTREE',
42 attr_login='uid'):
42 attr_login='uid'):
43 self.ldap_version = ldap_version
43 self.ldap_version = ldap_version
44 if use_ldaps:
44 if use_ldaps:
45 port = port or 689
45 port = port or 689
46 self.LDAP_USE_LDAPS = use_ldaps
46 self.LDAP_USE_LDAPS = use_ldaps
47 self.TLS_REQCERT = ldap.__dict__['OPT_X_TLS_' + tls_reqcert]
47 self.TLS_REQCERT = ldap.__dict__['OPT_X_TLS_' + tls_reqcert]
48 self.LDAP_SERVER_ADDRESS = server
48 self.LDAP_SERVER_ADDRESS = server
49 self.LDAP_SERVER_PORT = port
49 self.LDAP_SERVER_PORT = port
50
50
51 #USE FOR READ ONLY BIND TO LDAP SERVER
51 #USE FOR READ ONLY BIND TO LDAP SERVER
52 self.LDAP_BIND_DN = bind_dn
52 self.LDAP_BIND_DN = bind_dn
53 self.LDAP_BIND_PASS = bind_pass
53 self.LDAP_BIND_PASS = bind_pass
54
54
55 ldap_server_type = 'ldap'
55 ldap_server_type = 'ldap'
56 if self.LDAP_USE_LDAPS:ldap_server_type = ldap_server_type + 's'
56 if self.LDAP_USE_LDAPS:ldap_server_type = ldap_server_type + 's'
57 self.LDAP_SERVER = "%s://%s:%s" % (ldap_server_type,
57 self.LDAP_SERVER = "%s://%s:%s" % (ldap_server_type,
58 self.LDAP_SERVER_ADDRESS,
58 self.LDAP_SERVER_ADDRESS,
59 self.LDAP_SERVER_PORT)
59 self.LDAP_SERVER_PORT)
60
60
61 self.BASE_DN = base_dn
61 self.BASE_DN = base_dn
62 self.LDAP_FILTER = ldap_filter
62 self.LDAP_FILTER = ldap_filter
63 self.SEARCH_SCOPE = ldap.__dict__['SCOPE_' + search_scope]
63 self.SEARCH_SCOPE = ldap.__dict__['SCOPE_' + search_scope]
64 self.attr_login = attr_login
64 self.attr_login = attr_login
65
65
66
66
67 def authenticate_ldap(self, username, password):
67 def authenticate_ldap(self, username, password):
68 """Authenticate a user via LDAP and return his/her LDAP properties.
68 """Authenticate a user via LDAP and return his/her LDAP properties.
69
69
70 Raises AuthenticationError if the credentials are rejected, or
70 Raises AuthenticationError if the credentials are rejected, or
71 EnvironmentError if the LDAP server can't be reached.
71 EnvironmentError if the LDAP server can't be reached.
72
72
73 :param username: username
73 :param username: username
74 :param password: password
74 :param password: password
75 """
75 """
76
76
77 from rhodecode.lib.helpers import chop_at
77 from rhodecode.lib.helpers import chop_at
78
78
79 uid = chop_at(username, "@%s" % self.LDAP_SERVER_ADDRESS)
79 uid = chop_at(username, "@%s" % self.LDAP_SERVER_ADDRESS)
80
80
81 if "," in username:
81 if "," in username:
82 raise LdapUsernameError("invalid character in username: ,")
82 raise LdapUsernameError("invalid character in username: ,")
83 try:
83 try:
84 ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, '/etc/openldap/cacerts')
84 ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, '/etc/openldap/cacerts')
85 ldap.set_option(ldap.OPT_REFERRALS, ldap.OPT_OFF)
85 ldap.set_option(ldap.OPT_REFERRALS, ldap.OPT_OFF)
86 ldap.set_option(ldap.OPT_RESTART, ldap.OPT_ON)
86 ldap.set_option(ldap.OPT_RESTART, ldap.OPT_ON)
87 ldap.set_option(ldap.OPT_TIMEOUT, 20)
87 ldap.set_option(ldap.OPT_TIMEOUT, 20)
88 ldap.set_option(ldap.OPT_NETWORK_TIMEOUT, 10)
88 ldap.set_option(ldap.OPT_NETWORK_TIMEOUT, 10)
89 ldap.set_option(ldap.OPT_TIMELIMIT, 15)
89 ldap.set_option(ldap.OPT_TIMELIMIT, 15)
90 if self.LDAP_USE_LDAPS:
90 if self.LDAP_USE_LDAPS:
91 ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, self.TLS_REQCERT)
91 ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, self.TLS_REQCERT)
92 server = ldap.initialize(self.LDAP_SERVER)
92 server = ldap.initialize(self.LDAP_SERVER)
93 if self.ldap_version == 2:
93 if self.ldap_version == 2:
94 server.protocol = ldap.VERSION2
94 server.protocol = ldap.VERSION2
95 else:
95 else:
96 server.protocol = ldap.VERSION3
96 server.protocol = ldap.VERSION3
97
97
98 if self.LDAP_BIND_DN and self.LDAP_BIND_PASS:
98 if self.LDAP_BIND_DN and self.LDAP_BIND_PASS:
99 server.simple_bind_s(self.LDAP_BIND_DN, self.LDAP_BIND_PASS)
99 server.simple_bind_s(self.LDAP_BIND_DN, self.LDAP_BIND_PASS)
100
100
101 filt = '(&%s(%s=%s))' % (self.LDAP_FILTER, self.attr_login, username)
101 filt = '(&%s(%s=%s))' % (self.LDAP_FILTER, self.attr_login, username)
102 log.debug("Authenticating %r filt %s at %s", self.BASE_DN, filt, self.LDAP_SERVER)
102 log.debug("Authenticating %r filt %s at %s", self.BASE_DN,
103 lobjects = server.search_ext_s(self.BASE_DN, self.SEARCH_SCOPE, filt)
103 filt, self.LDAP_SERVER)
104 lobjects = server.search_ext_s(self.BASE_DN, self.SEARCH_SCOPE,
105 filt)
104
106
105 if not lobjects:
107 if not lobjects:
106 raise ldap.NO_SUCH_OBJECT()
108 raise ldap.NO_SUCH_OBJECT()
107
109
108 for (dn, attrs) in lobjects:
110 for (dn, attrs) in lobjects:
109 try:
111 try:
110 server.simple_bind_s(dn, password)
112 server.simple_bind_s(dn, password)
111 break
113 break
112
114
113 except ldap.INVALID_CREDENTIALS, e:
115 except ldap.INVALID_CREDENTIALS, e:
114 log.debug("LDAP rejected password for user '%s' (%s): %s", uid, username, dn)
116 log.debug("LDAP rejected password for user '%s' (%s): %s",
117 uid, username, dn)
115
118
116 else:
119 else:
117 log.debug("No matching LDAP objecs for authentication of '%s' (%s)", uid, username)
120 log.debug("No matching LDAP objects for authentication "
121 "of '%s' (%s)", uid, username)
118 raise LdapPasswordError()
122 raise LdapPasswordError()
119
123
120 except ldap.NO_SUCH_OBJECT, e:
124 except ldap.NO_SUCH_OBJECT, e:
121 log.debug("LDAP says no such user '%s' (%s)", uid, username)
125 log.debug("LDAP says no such user '%s' (%s)", uid, username)
122 raise LdapUsernameError()
126 raise LdapUsernameError()
123 except ldap.SERVER_DOWN, e:
127 except ldap.SERVER_DOWN, e:
124 raise LdapConnectionError("LDAP can't access authentication server")
128 raise LdapConnectionError("LDAP can't access authentication server")
125
129
126 return (dn, attrs)
130 return (dn, attrs)
General Comments 0
You need to be logged in to leave comments. Login now