| |
@@ -6,6 +6,7 @@
|
| |
from ipsilon.util.policy import Policy
|
| |
from ipsilon.util import config as pconfig
|
| |
import ldap
|
| |
+ import ldap.filter
|
| |
import subprocess
|
| |
|
| |
|
| |
@@ -42,6 +43,14 @@
|
| |
'user dn template',
|
| |
'Template to turn username into DN.',
|
| |
'uid=%(username)s,ou=People,dc=example,dc=com'),
|
| |
+ pconfig.Condition(
|
| |
+ 'lookup dn',
|
| |
+ 'Look up user DNs?',
|
| |
+ False),
|
| |
+ pconfig.String(
|
| |
+ 'lookup dn filter template',
|
| |
+ 'Search filter template used to look up DNs.',
|
| |
+ '(mail=%(username)s)'),
|
| |
pconfig.Pick(
|
| |
'tls',
|
| |
'What TLS level show be required',
|
| |
@@ -81,6 +90,14 @@
|
| |
return self.get_config_value('user dn template')
|
| |
|
| |
@property
|
| |
+ def lookup_dn(self):
|
| |
+ return self.get_config_value('lookup dn')
|
| |
+
|
| |
+ @property
|
| |
+ def lookup_dn_filter_template(self):
|
| |
+ return self.get_config_value('lookup dn filter template')
|
| |
+
|
| |
+ @property
|
| |
def base_dn(self):
|
| |
return self.get_config_value('base dn')
|
| |
|
| |
@@ -126,10 +143,12 @@
|
| |
data[name] = value
|
| |
return data
|
| |
|
| |
- def _get_user_groups(self, conn, base, username):
|
| |
+ def _get_user_groups(self, conn, base, username, group_filter=None):
|
| |
+ if group_filter is None:
|
| |
+ group_filter = "memberuid=%s" % username
|
| |
+ self.debug("Searching for groups using filter %s" % group_filter)
|
| |
# TODO: fixme to support RFC2307bis schemas
|
| |
- results = conn.search_s(base, ldap.SCOPE_SUBTREE,
|
| |
- filterstr='memberuid=%s' % username)
|
| |
+ results = conn.search_s(base, ldap.SCOPE_SUBTREE, filterstr=group_filter)
|
| |
if results is None or results == []:
|
| |
self.debug('No groups for %s' % username)
|
| |
return []
|
| |
@@ -139,13 +158,13 @@
|
| |
groups.append(r[1]['cn'][0])
|
| |
return groups
|
| |
|
| |
- def get_user_data_from_conn(self, conn, dn, base, username):
|
| |
+ def get_user_data_from_conn(self, conn, dn, base, username, group_filter):
|
| |
reply = dict()
|
| |
try:
|
| |
ldapattrs = self._get_user_data(conn, dn)
|
| |
self.debug('LDAP attrs for %s: %s' % (dn, ldapattrs))
|
| |
userattrs, extras = self.mapper.map_attributes(ldapattrs)
|
| |
- groups = self._get_user_groups(conn, base, username)
|
| |
+ groups = self._get_user_groups(conn, base, username, group_filter)
|
| |
reply = userattrs
|
| |
reply['_groups'] = groups
|
| |
reply['_extras'] = {'ldap': extras}
|
| |
@@ -155,8 +174,28 @@
|
| |
return reply
|
| |
|
| |
def get_user_attrs(self, user):
|
| |
+ username = user
|
| |
try:
|
| |
- dn = self.user_dn_tmpl % {'username': user}
|
| |
+ if self.lookup_dn:
|
| |
+ conn = self._ldap_bind()
|
| |
+ conn.simple_bind_s(self.lookup_bind_dn, self.lookup_bind_pw)
|
| |
+ search_filter = self.lookup_dn_filter_template % { 'username': ldap.filter.escape_filter_chars(user) }
|
| |
+ result = conn.search_s(self.base_dn, ldap.SCOPE_SUBTREE, search_filter, ["dn"])
|
| |
+ if result is not None and result != []:
|
| |
+ if len(result) > 1:
|
| |
+ self.error("User query failed to yeild a unique result.")
|
| |
+ else:
|
| |
+ dn = result[0][0]
|
| |
+ # In case we're using get_user_info below, get the UID or CN attribute that uniquely identifies the user...
|
| |
+ uidattr = dn.split(',')[0]
|
| |
+ uid = uidattr.split('=')[1]
|
| |
+ username = uid
|
| |
+ else:
|
| |
+ self.error("User not found.")
|
| |
+ # reset the ldap connection
|
| |
+ conn.unbind()
|
| |
+ else:
|
| |
+ dn = self.user_dn_tmpl % {'username': user}
|
| |
except ValueError as e:
|
| |
self.error(
|
| |
'DN generation failed with template %s, user %s: %s'
|
| |
@@ -173,7 +212,7 @@
|
| |
try:
|
| |
base = self.base_dn
|
| |
conn = self._ldap_bind()
|
| |
- return self.get_user_data_from_conn(conn, dn, base, user)
|
| |
+ return self.get_user_data_from_conn(conn, dn, base, username)
|
| |
except ldap.LDAPError as e:
|
| |
self.error(
|
| |
'LDAP search failed for DN %s on base %s: %s' %
|
| |
Signed-off-by: Kendal Montgomery kmontgomery@cbuscollaboratory.com
Added configuration options and code for optional LDAP functionality to look up user's DN - search for user's DN based on a filter rather than assuming the DN by format string. This allows the administrator to configure a lookup user and search filter to find the authenticating user's DN based on alternate attributes (such as mail), and then authenticate the user.
Discussion and comments can be found on pull request 299: https://pagure.io/ipsilon/pull-request/299. Recommendations were implemented from this conversation in this pull request.