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