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
13 class LDAP(LoginFormBase, Log):
15 def __init__(self, site, mgr, page):
16 super(LDAP, self).__init__(site, mgr, page)
19 def _ldap_connect(self):
21 tls = self.lm.tls.lower()
24 tls_req_opt = ldap.OPT_X_TLS_NEVER
26 tls_req_opt = ldap.OPT_X_TLS_DEMAND
28 tls_req_opt = ldap.OPT_X_TLS_ALLOW
30 tls_req_opt = ldap.OPT_X_TLS_TRY
31 if tls_req_opt is not None:
32 ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, tls_req_opt)
34 conn = ldap.initialize(self.lm.server_url)
37 if not self.lm.server_url.startswith("ldaps"):
41 def _authenticate(self, username, password):
43 conn = self._ldap_connect()
44 dn = self.lm.bind_dn_tmpl % {'username': username}
45 conn.simple_bind_s(dn, password)
47 # Bypass info plugins to optimize data retrieval
48 if self.lm.get_user_info:
51 if not self.ldap_info:
52 self.ldap_info = LDAPInfo(self._site)
54 return self.ldap_info.get_user_data_from_conn(conn, dn)
58 def POST(self, *args, **kwargs):
59 username = kwargs.get("login_name")
60 password = kwargs.get("login_password")
65 if username and password:
67 userattrs = self._authenticate(username, password)
69 except Exception, e: # pylint: disable=broad-except
70 errmsg = "Authentication failed"
71 self.error("Exception raised: [%s]" % repr(e))
73 errmsg = "Username or password is missing"
77 return self.lm.auth_successful(self.trans, username, 'password',
80 context = self.create_tmpl_context(
83 error_password=not password,
84 error_username=not username
86 self.lm.set_auth_error()
87 # pylint: disable=star-args
88 return self._template('login/form.html', **context)
91 class LoginManager(LoginManagerBase):
93 def __init__(self, *args, **kwargs):
94 super(LoginManager, self).__init__(*args, **kwargs)
99 self.service_name = 'ldap'
100 self.description = """
101 Form based login Manager that uses a simple bind LDAP operation to perform
107 'The LDAP server url.',
108 'ldap://example.com'),
111 'Template to turn username into DN.',
112 'uid=%(username)s,ou=People,dc=example,dc=com'),
115 'Get user info via ldap using user credentials',
119 'What TLS level show be required',
120 ['Demand', 'Allow', 'Try', 'Never', 'NoTLS'],
124 'Text used to ask for the username at login time.',
128 'Text used to ask for the password at login time.',
132 'Text used to guide the user at login time.',
133 'Provide your Username and Password')
138 return self.get_config_value('help text')
141 def username_text(self):
142 return self.get_config_value('username text')
145 def password_text(self):
146 return self.get_config_value('password text')
149 def server_url(self):
150 return self.get_config_value('server url')
154 return self.get_config_value('tls')
157 def get_user_info(self):
158 return self.get_config_value('get user info')
161 def bind_dn_tmpl(self):
162 return self.get_config_value('bind dn template')
164 def get_tree(self, site):
165 self.page = LDAP(site, self, 'login/ldap')
169 class Installer(LoginManagerInstaller):
171 def __init__(self, *pargs):
172 super(Installer, self).__init__()
176 def install_args(self, group):
177 group.add_argument('--ldap', choices=['yes', 'no'], default='no',
178 help='Configure LDAP authentication')
179 group.add_argument('--ldap-server-url', action='store',
180 help='LDAP Server Url')
181 group.add_argument('--ldap-bind-dn-template', action='store',
182 help='LDAP Bind DN Template')
184 def configure(self, opts):
185 if opts['ldap'] != 'yes':
188 # Add configuration data to database
189 po = PluginObject(*self.pargs)
192 po.wipe_config_values()
195 if 'ldap_server_url' in opts:
196 config['server url'] = opts['ldap_server_url']
197 if 'ldap_bind_dn_template' in opts:
198 config['bind dn template'] = opts['ldap_bind_dn_template']
199 config['tls'] = 'Demand'
200 po.save_plugin_config(config)
202 # Update global config to add login plugin
204 po.save_enabled_state()
206 # For selinux enabled platforms permit httpd to connect to ldap,
209 subprocess.call(['/usr/sbin/setsebool', '-P',
210 'httpd_can_connect_ldap=on'])
211 except Exception: # pylint: disable=broad-except