1 # Copyright (C) 2014 Ipsilon Contributors, see COPYING for license
3 from ipsilon.login.common import LoginFormBase, LoginManagerBase, \
5 from ipsilon.util.plugin import PluginObject
6 from ipsilon.util.log import Log
7 from ipsilon.util import config as pconfig
8 from ipsilon.info.infoldap import InfoProvider as LDAPInfo
12 class LDAP(LoginFormBase, Log):
14 def __init__(self, site, mgr, page):
15 super(LDAP, self).__init__(site, mgr, page)
18 def _ldap_connect(self):
20 tls = self.lm.tls.lower()
23 tls_req_opt = ldap.OPT_X_TLS_NEVER
25 tls_req_opt = ldap.OPT_X_TLS_DEMAND
27 tls_req_opt = ldap.OPT_X_TLS_ALLOW
29 tls_req_opt = ldap.OPT_X_TLS_TRY
30 if tls_req_opt is not None:
31 ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, tls_req_opt)
33 conn = ldap.initialize(self.lm.server_url)
36 if not self.lm.server_url.startswith("ldaps"):
40 def _authenticate(self, username, password):
42 conn = self._ldap_connect()
43 dn = self.lm.bind_dn_tmpl % {'username': username}
44 conn.simple_bind_s(dn, password)
46 # Bypass info plugins to optimize data retrieval
47 if self.lm.get_user_info:
50 if not self.ldap_info:
51 self.ldap_info = LDAPInfo(self._site)
53 return self.ldap_info.get_user_data_from_conn(conn, dn)
57 def POST(self, *args, **kwargs):
58 username = kwargs.get("login_name")
59 password = kwargs.get("login_password")
64 if username and password:
66 userattrs = self._authenticate(username, password)
68 except Exception, e: # pylint: disable=broad-except
69 errmsg = "Authentication failed"
70 self.error("Exception raised: [%s]" % repr(e))
72 errmsg = "Username or password is missing"
76 return self.lm.auth_successful(self.trans, username, 'password',
79 context = self.create_tmpl_context(
82 error_password=not password,
83 error_username=not username
85 self.lm.set_auth_error()
86 # pylint: disable=star-args
87 return self._template('login/form.html', **context)
90 class LoginManager(LoginManagerBase):
92 def __init__(self, *args, **kwargs):
93 super(LoginManager, self).__init__(*args, **kwargs)
98 self.service_name = 'ldap'
99 self.description = """
100 Form based login Manager that uses a simple bind LDAP operation to perform
106 'The LDAP server url.',
107 'ldap://example.com'),
110 'Template to turn username into DN.',
111 'uid=%(username)s,ou=People,dc=example,dc=com'),
114 'Get user info via ldap using user credentials',
118 'What TLS level show be required',
119 ['Demand', 'Allow', 'Try', 'Never', 'NoTLS'],
123 'Text used to ask for the username at login time.',
127 'Text used to ask for the password at login time.',
131 'Text used to guide the user at login time.',
132 'Provide your Username and Password')
137 return self.get_config_value('help text')
140 def username_text(self):
141 return self.get_config_value('username text')
144 def password_text(self):
145 return self.get_config_value('password text')
148 def server_url(self):
149 return self.get_config_value('server url')
153 return self.get_config_value('tls')
156 def get_user_info(self):
157 return self.get_config_value('get user info')
160 def bind_dn_tmpl(self):
161 return self.get_config_value('bind dn template')
163 def get_tree(self, site):
164 self.page = LDAP(site, self, 'login/ldap')
168 class Installer(LoginManagerInstaller):
170 def __init__(self, *pargs):
171 super(Installer, self).__init__()
175 def install_args(self, group):
176 group.add_argument('--ldap', choices=['yes', 'no'], default='no',
177 help='Configure LDAP authentication')
178 group.add_argument('--ldap-server-url', action='store',
179 help='LDAP Server Url')
180 group.add_argument('--ldap-bind-dn-template', action='store',
181 help='LDAP Bind DN Template')
183 def configure(self, opts):
184 if opts['ldap'] != 'yes':
187 # Add configuration data to database
188 po = PluginObject(*self.pargs)
191 po.wipe_config_values()
194 if 'ldap_server_url' in opts:
195 config['server url'] = opts['ldap_server_url']
196 if 'ldap_bind_dn_template' in opts:
197 config['bind dn template'] = opts['ldap_bind_dn_template']
198 config['tls'] = 'Demand'
199 po.save_plugin_config(config)
201 # Update global config to add login plugin
203 po.save_enabled_state()