annotate rhodecode/lib/auth_ldap.py @ 709:a23b686fb14d beta

bugfix for application name
author Marcin Kuzminski <marcin@python-works.com>
date Thu, 18 Nov 2010 02:25:12 +0100
parents 9e9f1b919c0c
children 1bb0fcdec895
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
700
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
1 #==============================================================================
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
2 # LDAP
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
3 #Name = Just a description for the auth modes page
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
4 #Host = DepartmentName.OrganizationName.local/ IP
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
5 #Port = 389 default for ldap
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
6 #LDAPS = no set True if You need to use ldaps
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
7 #Account = DepartmentName\UserName (or UserName@MyDomain depending on AD server)
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
8 #Password = <password>
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
9 #Base DN = DC=DepartmentName,DC=OrganizationName,DC=local
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
10
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
11 #==============================================================================
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
12
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
13 from rhodecode.lib.exceptions import LdapImportError, UsernameError, \
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
14 PasswordError, ConnectionError
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
15 import logging
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
16
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
17 log = logging.getLogger(__name__)
700
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
18
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
19 try:
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
20 import ldap
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
21 except ImportError:
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
22 pass
700
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
23
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
24 class AuthLdap(object):
700
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
25
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
26 def __init__(self, server, base_dn, port=389, bind_dn='', bind_pass='',
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
27 use_ldaps=False, ldap_version=3):
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
28 self.ldap_version = ldap_version
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
29 if use_ldaps:
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
30 port = port or 689
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
31 self.LDAP_USE_LDAPS = use_ldaps
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
32 self.LDAP_SERVER_ADDRESS = server
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
33 self.LDAP_SERVER_PORT = port
700
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
34
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
35 #USE FOR READ ONLY BIND TO LDAP SERVER
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
36 self.LDAP_BIND_DN = bind_dn
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
37 self.LDAP_BIND_PASS = bind_pass
700
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
38
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
39 ldap_server_type = 'ldap'
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
40 if self.LDAP_USE_LDAPS:ldap_server_type = ldap_server_type + 's'
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
41 self.LDAP_SERVER = "%s://%s:%s" % (ldap_server_type,
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
42 self.LDAP_SERVER_ADDRESS,
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
43 self.LDAP_SERVER_PORT)
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
44
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
45 self.BASE_DN = base_dn
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
46 self.AUTH_DN = "uid=%s,%s"
700
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
47
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
48 def authenticate_ldap(self, username, password):
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
49 """Authenticate a user via LDAP and return his/her LDAP properties.
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
50
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
51 Raises AuthenticationError if the credentials are rejected, or
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
52 EnvironmentError if the LDAP server can't be reached.
701
6602bf1c5546 ldap two phase auth fix
Marcin Kuzminski <marcin@python-works.com>
parents: 700
diff changeset
53
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
54 :param username: username
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
55 :param password: password
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
56 """
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
57
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
58 from rhodecode.lib.helpers import chop_at
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
59
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
60 uid = chop_at(username, "@%s" % self.LDAP_SERVER_ADDRESS)
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
61 dn = self.AUTH_DN % (uid, self.BASE_DN)
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
62 log.debug("Authenticating %r at %s", dn, self.LDAP_SERVER)
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
63 if "," in username:
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
64 raise UsernameError("invalid character in username: ,")
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
65 try:
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
66 ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, '/etc/openldap/cacerts')
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
67 ldap.set_option(ldap.OPT_NETWORK_TIMEOUT, 10)
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
68 server = ldap.initialize(self.LDAP_SERVER)
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
69 if self.ldap_version == 2:
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
70 server.protocol = ldap.VERSION2
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
71 else:
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
72 server.protocol = ldap.VERSION3
700
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
73
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
74 if self.LDAP_BIND_DN and self.LDAP_BIND_PASS:
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
75 server.simple_bind_s(self.AUTH_DN % (self.LDAP_BIND_DN,
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
76 self.BASE_DN),
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
77 self.LDAP_BIND_PASS)
700
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
78
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
79 server.simple_bind_s(dn, password)
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
80 properties = server.search_s(dn, ldap.SCOPE_SUBTREE)
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
81 if not properties:
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
82 raise ldap.NO_SUCH_OBJECT()
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
83 except ldap.NO_SUCH_OBJECT, e:
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
84 log.debug("LDAP says no such user '%s' (%s)", uid, username)
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
85 raise UsernameError()
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
86 except ldap.INVALID_CREDENTIALS, e:
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
87 log.debug("LDAP rejected password for user '%s' (%s)", uid, username)
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
88 raise PasswordError()
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
89 except ldap.SERVER_DOWN, e:
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
90 raise ConnectionError("LDAP can't access authentication server")
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
91
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
92 return properties[0]
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
93