annotate rhodecode/lib/auth_ldap.py @ 902:07a6e8c65526 beta

fixed copyright year to 2011
author Marcin Kuzminski <marcin@python-works.com>
date Fri, 31 Dec 2010 19:46:56 +0100
parents 22eca93bea97
children b232a36cc51f a3b2b4b4e440
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
713
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
1 #!/usr/bin/env python
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
2 # encoding: utf-8
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
3 # ldap authentication lib
902
07a6e8c65526 fixed copyright year to 2011
Marcin Kuzminski <marcin@python-works.com>
parents: 794
diff changeset
4 # Copyright (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
713
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
5 #
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
6 # This program is free software; you can redistribute it and/or
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
7 # modify it under the terms of the GNU General Public License
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
8 # as published by the Free Software Foundation; version 2
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
9 # of the License or (at your opinion) any later version of the license.
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
10 #
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
11 # This program is distributed in the hope that it will be useful,
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
14 # GNU General Public License for more details.
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
15 #
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
16 # You should have received a copy of the GNU General Public License
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
17 # along with this program; if not, write to the Free Software
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
19 # MA 02110-1301, USA.
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
20 """
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
21 Created on Nov 17, 2010
700
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
22
713
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
23 @author: marcink
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
24 """
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
25
713
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
26 from rhodecode.lib.exceptions import *
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
27 import logging
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
28
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
29 log = logging.getLogger(__name__)
700
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
30
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
31 try:
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
32 import ldap
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
33 except ImportError:
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
34 pass
700
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
35
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
36 class AuthLdap(object):
700
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
37
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
38 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
39 use_ldaps=False, ldap_version=3):
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
40 self.ldap_version = ldap_version
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
41 if use_ldaps:
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
42 port = port or 689
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
43 self.LDAP_USE_LDAPS = use_ldaps
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
44 self.LDAP_SERVER_ADDRESS = server
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
45 self.LDAP_SERVER_PORT = port
700
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
46
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
47 #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
48 self.LDAP_BIND_DN = bind_dn
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
49 self.LDAP_BIND_PASS = bind_pass
700
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
50
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
51 ldap_server_type = 'ldap'
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
52 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
53 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
54 self.LDAP_SERVER_ADDRESS,
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
55 self.LDAP_SERVER_PORT)
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 self.BASE_DN = base_dn
700
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
58
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
59 def authenticate_ldap(self, username, password):
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
60 """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
61
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
62 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
63 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
64
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
65 :param username: username
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
66 :param password: password
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
67 """
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
68
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
69 from rhodecode.lib.helpers import chop_at
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
70
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
71 uid = chop_at(username, "@%s" % self.LDAP_SERVER_ADDRESS)
775
aaf2fc59a39a fixes #77 and adds extendable base Dn with custom uid specification
Marcin Kuzminski <marcin@python-works.com>
parents: 739
diff changeset
72
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
73 if "," in username:
713
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
74 raise LdapUsernameError("invalid character in username: ,")
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
75 try:
739
554ed64953ff fixes #76 added confirmation dialog for user removal.
Marcin Kuzminski <marcin@python-works.com>
parents: 713
diff changeset
76 ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, '/etc/openldap/cacerts')
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
77 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
78 server = ldap.initialize(self.LDAP_SERVER)
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
79 if self.ldap_version == 2:
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
80 server.protocol = ldap.VERSION2
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
81 else:
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
82 server.protocol = ldap.VERSION3
700
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
83
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
84 if self.LDAP_BIND_DN and self.LDAP_BIND_PASS:
794
22eca93bea97 fixes a bug with two-pass ldap auth (thanks for TK Soh for that)
Marcin Kuzminski <marcin@python-works.com>
parents: 775
diff changeset
85 server.simple_bind_s(self.LDAP_BIND_DN, self.LDAP_BIND_PASS)
700
07fd56c36bfe added basic ldap auth lib
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
86
775
aaf2fc59a39a fixes #77 and adds extendable base Dn with custom uid specification
Marcin Kuzminski <marcin@python-works.com>
parents: 739
diff changeset
87 dn = self.BASE_DN % {'user':uid}
aaf2fc59a39a fixes #77 and adds extendable base Dn with custom uid specification
Marcin Kuzminski <marcin@python-works.com>
parents: 739
diff changeset
88 log.debug("Authenticating %r at %s", dn, self.LDAP_SERVER)
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
89 server.simple_bind_s(dn, password)
775
aaf2fc59a39a fixes #77 and adds extendable base Dn with custom uid specification
Marcin Kuzminski <marcin@python-works.com>
parents: 739
diff changeset
90
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
91 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
92 if not properties:
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
93 raise ldap.NO_SUCH_OBJECT()
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
94 except ldap.NO_SUCH_OBJECT, e:
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
95 log.debug("LDAP says no such user '%s' (%s)", uid, username)
713
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
96 raise LdapUsernameError()
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
97 except ldap.INVALID_CREDENTIALS, e:
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
98 log.debug("LDAP rejected password for user '%s' (%s)", uid, username)
713
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
99 raise LdapPasswordError()
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
100 except ldap.SERVER_DOWN, e:
713
1bb0fcdec895 fixed #72 show warning on removal when user still is owner of existing repositories
Marcin Kuzminski <marcin@python-works.com>
parents: 705
diff changeset
101 raise LdapConnectionError("LDAP can't access authentication server")
705
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
102
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
103 return properties[0]
9e9f1b919c0c implements #60, ldap configuration and authentication.
Marcin Kuzminski <marcin@python-works.com>
parents: 701
diff changeset
104