nss-pam-ldapd commit: r1571 - nss-pam-ldapd/pynslcd
[
Date Prev][
Date Next]
[
Thread Prev][
Thread Next]
nss-pam-ldapd commit: r1571 - nss-pam-ldapd/pynslcd
- From: Commits of the nss-pam-ldapd project <nss-pam-ldapd-commits [at] lists.arthurdejong.org>
- To: nss-pam-ldapd-commits [at] lists.arthurdejong.org
- Reply-to: nss-pam-ldapd-users [at] lists.arthurdejong.org
- Subject: nss-pam-ldapd commit: r1571 - nss-pam-ldapd/pynslcd
- Date: Mon, 12 Dec 2011 23:59:02 +0100 (CET)
Author: arthur
Date: Mon Dec 12 23:59:00 2011
New Revision: 1571
URL: http://arthurdejong.org/viewvc/nss-pam-ldapd?revision=1571&view=revision
Log:
define the search separately from the request
Modified:
nss-pam-ldapd/pynslcd/alias.py
nss-pam-ldapd/pynslcd/common.py
nss-pam-ldapd/pynslcd/ether.py
nss-pam-ldapd/pynslcd/group.py
nss-pam-ldapd/pynslcd/host.py
nss-pam-ldapd/pynslcd/netgroup.py
nss-pam-ldapd/pynslcd/network.py
nss-pam-ldapd/pynslcd/passwd.py
nss-pam-ldapd/pynslcd/protocol.py
nss-pam-ldapd/pynslcd/rpc.py
nss-pam-ldapd/pynslcd/service.py
nss-pam-ldapd/pynslcd/shadow.py
Modified: nss-pam-ldapd/pynslcd/alias.py
==============================================================================
--- nss-pam-ldapd/pynslcd/alias.py Mon Dec 12 22:53:10 2011 (r1570)
+++ nss-pam-ldapd/pynslcd/alias.py Mon Dec 12 23:59:00 2011 (r1571)
@@ -28,12 +28,15 @@
filter = '(objectClass=nisMailAlias)'
-class AliasRequest(common.Request):
+class Search(common.Search):
case_insensitive = ('cn', )
limit_attributes = ('cn', )
required = ('cn', 'rfc822MailMember')
+
+class AliasRequest(common.Request):
+
def write(self, dn, attributes, parameters):
# get values
names = attributes['cn']
Modified: nss-pam-ldapd/pynslcd/common.py
==============================================================================
--- nss-pam-ldapd/pynslcd/common.py Mon Dec 12 22:53:10 2011 (r1570)
+++ nss-pam-ldapd/pynslcd/common.py Mon Dec 12 23:59:00 2011 (r1571)
@@ -54,12 +54,10 @@
raise ValueError('%r: invalid user name' % name)
-class Request(object):
+class Search(object):
"""
- Request handler class. Subclasses are expected to handle actual requests
- and should implement the following members:
-
- action - the NSLCD_ACTION_* action that should trigger this handler
+ Class that performs a search. Subclasses are expected to define the actual
+ searches and should implement the following members:
case_sensitive - check that these attributes are present in the response
if they were in the request
@@ -69,10 +67,7 @@
required - attributes that are required
canonical_first - search the DN for these attributes and ensure that
they are listed first in the attribute values
- read_parameters() - a function that reads the request parameters of the
- request stream
mk_filter() (optional) - function that returns the LDAP search filter
- write() - function that writes a single LDAP entry to the result stream
The module that contains the Request class can also contain the following
definitions:
@@ -84,38 +79,61 @@
"""
- def __init__(self, fp, conn, calleruid):
- self.fp = fp
- self.conn = conn
- self.calleruid = calleruid
+ canonical_first = []
+ required = []
+ case_sensitive = []
+ case_insensitive = []
+ limit_attributes = []
+
+ def __init__(self, conn, base=None, scope=None, filter=None,
attributes=None,
+ parameters=None):
# load information from module that defines the class
+ self.conn = conn
module = sys.modules[self.__module__]
self.attmap = getattr(module, 'attmap', None)
- self.filter = getattr(module, 'filter', None)
- self.bases = getattr(module, 'bases', cfg.bases)
- self.scope = getattr(module, 'scope', cfg.scope)
+ self.filter = filter or getattr(module, 'filter', None)
+ self.parameters = parameters or {}
+ if base:
+ self.bases = [base]
+ else:
+ self.bases = getattr(module, 'bases', cfg.bases)
+ self.scope = scope or getattr(module, 'scope', cfg.scope)
+ self.attributes = attributes or self.attmap.attributes()
- def read_parameters(self, fp):
- """This method should read the parameters from ths stream and
- store them in self."""
- pass
+ def __iter__(self):
+ return self()
- def mk_filter(self, parameters):
+ def __call__(self):
+ # get search results
+ filter = self.mk_filter()
+ for base in self.bases:
+ # do the LDAP search
+ try:
+ for entry in self.conn.search_s(base, self.scope, filter,
self.attributes):
+ if entry[0]:
+ entry = self.handle_entry(entry[0], entry[1])
+ if entry:
+ yield entry
+ except ldap.NO_SUCH_OBJECT:
+ # FIXME: log message
+ pass
+
+ def mk_filter(self):
"""Return the active search filter (based on the read parameters)."""
- if parameters:
+ if self.parameters:
return '(&%s(%s))' % (self.filter,
')('.join('%s=%s' % (self.attmap[attribute],
ldap.filter.escape_filter_chars(str(value)))
- for attribute, value in parameters.items()))
+ for attribute, value in self.parameters.items()))
return self.filter
- def handle_entry(self, dn, attributes, parameters):
+ def handle_entry(self, dn, attributes):
"""Handle an entry with the specified attributes, filtering it with
the request parameters where needed."""
# translate the attributes using the attribute mapping
attributes = self.attmap.translate(attributes)
# make sure value from DN is first value
- for attr in getattr(self, 'canonical_first', []):
+ for attr in self.canonical_first:
primary_value = get_rdn_value(dn, self.attmap[attr])
if primary_value:
values = attributes[attr]
@@ -123,44 +141,60 @@
values.remove(primary_value)
attributes[attr] = [primary_value] + values
# check that these attributes have at least one value
- for attr in getattr(self, 'required', []):
+ for attr in self.required:
if not attributes.get(attr, None):
print '%s: attribute %s not found' % (dn, self.attmap[attr])
return
# check that requested attribute is present (case sensitive)
- for attr in getattr(self, 'case_sensitive', []):
- value = parameters.get(attr, None)
+ for attr in self.case_sensitive:
+ value = self.parameters.get(attr, None)
if value and str(value) not in attributes[attr]:
print '%s: attribute %s does not contain %r value' % (dn,
self.attmap[attr], value)
return # not found, skip entry
# check that requested attribute is present (case insensitive)
- for attr in getattr(self, 'case_insensitive', []):
- value = parameters.get(attr, None)
+ for attr in self.case_insensitive:
+ value = self.parameters.get(attr, None)
if value and str(value).lower() not in (x.lower() for x in
attributes[attr]):
print '%s: attribute %s does not contain %r value' % (dn,
self.attmap[attr], value)
return # not found, skip entry
# limit attribute values to requested value
- for attr in getattr(self, 'limit_attributes', []):
- if attr in parameters:
- attributes[attr] = [parameters[attr]]
- # write the result entry
- self.write(dn, attributes, parameters)
+ for attr in self.limit_attributes:
+ if attr in self.parameters:
+ attributes[attr] = [self.parameters[attr]]
+ # return the entry
+ return dn, attributes
+
+
+class Request(object):
+ """
+ Request handler class. Subclasses are expected to handle actual requests
+ and should implement the following members:
+
+ action - the NSLCD_ACTION_* action that should trigger this handler
+
+ read_parameters() - a function that reads the request parameters of the
+ request stream
+ write() - function that writes a single LDAP entry to the result stream
+
+ """
+
+ def __init__(self, fp, conn, calleruid):
+ self.fp = fp
+ self.conn = conn
+ self.calleruid = calleruid
+ module = sys.modules[self.__module__]
+ self.search = getattr(module, 'Search', None)
+
+ def read_parameters(self, fp):
+ """This method should read the parameters from ths stream and
+ store them in self."""
+ pass
def handle_request(self, parameters):
"""This method handles the request based on the parameters read
with read_parameters()."""
- # get search results
- for base in self.bases:
- # do the LDAP search
- try:
- res = self.conn.search_s(base, self.scope,
self.mk_filter(parameters),
- self.attmap.attributes())
- for entry in res:
- if entry[0]:
- self.handle_entry(entry[0], entry[1], parameters)
- except ldap.NO_SUCH_OBJECT:
- # FIXME: log message
- pass
+ for dn, attributes in self.search(conn=self.conn,
parameters=parameters):
+ self.write(dn, attributes, parameters)
# write the final result code
self.fp.write_int32(constants.NSLCD_RESULT_END)
Modified: nss-pam-ldapd/pynslcd/ether.py
==============================================================================
--- nss-pam-ldapd/pynslcd/ether.py Mon Dec 12 22:53:10 2011 (r1570)
+++ nss-pam-ldapd/pynslcd/ether.py Mon Dec 12 23:59:00 2011 (r1571)
@@ -38,23 +38,19 @@
filter = '(objectClass=ieee802Device)'
-class EtherRequest(common.Request):
+class Search(common.Search):
case_insensitive = ('cn', )
limit_attributes = ('cn', 'macAddress')
required = ('cn', 'macAddress')
+
+class EtherRequest(common.Request):
+
def write(self, dn, attributes, parameters):
- # get names
+ # get values
names = attributes['cn']
- # get addresses and convert to binary form
addresses = [ether_aton(x) for x in attributes['macAddress']]
- if 'macAddress' in parameters:
- address = ether_aton(parameters['macAddress'])
- if address not in addresses:
- print 'value %r for attribute %s not found in %s' %
(parameters['macAddress'], attmap['macAddress'], dn)
- return
- addresses = ( address, )
# write results
for name in names:
for ether in addresses:
Modified: nss-pam-ldapd/pynslcd/group.py
==============================================================================
--- nss-pam-ldapd/pynslcd/group.py Mon Dec 12 22:53:10 2011 (r1570)
+++ nss-pam-ldapd/pynslcd/group.py Mon Dec 12 23:59:00 2011 (r1571)
@@ -40,10 +40,33 @@
filter = '(|(objectClass=posixGroup)(objectClass=groupOfNames))'
-class GroupRequest(common.Request):
+class Search(common.Search):
case_sensitive = ('cn', )
limit_attributes = ('cn', 'gidNumber')
+
+ def __init__(self, *args, **kwargs):
+ super(Search, self).__init__(*args, **kwargs)
+ if attmap['member'] and 'memberUid' in self.parameters:
+ # set up our own attributes that leave out membership attributes
+ self.attmap = common.Attributes(self.attmap)
+ del self.attmap['memberUid']
+ del self.attmap['member']
+
+ def mk_filter(self):
+ # we still need a custom mk_filter because this is an | query
+ if attmap['member'] and 'memberUid' in self.parameters:
+ memberuid = self.parameters['memberUid']
+ dn = uid2dn(self.conn, memberuid)
+ if dn:
+ return '(&%s(|(%s=%s)(%s=%s)))' % ( self.filter,
+ attmap['memberUid'],
ldap.filter.escape_filter_chars(memberuid),
+ attmap['member'],
ldap.filter.escape_filter_chars(dn) )
+ return super(Search, self).mk_filter()
+
+
+class GroupRequest(common.Request):
+
wantmembers = True
def write(self, dn, attributes, parameters):
@@ -96,6 +119,8 @@
return dict(gidNumber=fp.read_gid_t())
+
+
class GroupByMemberRequest(GroupRequest):
action = constants.NSLCD_ACTION_GROUP_BYMEMBER
@@ -113,18 +138,6 @@
common.validate_name(memberuid)
return dict(memberUid=memberuid)
- def mk_filter(self, parameters):
- # we still need a custom mk_filter because this is an | query
- memberuid = parameters['memberUid']
- if attmap['member']:
- dn = uid2dn(self.conn, memberuid)
- if dn:
- return '(&%s(|(%s=%s)(%s=%s)))' % ( self.filter,
- attmap['memberUid'],
ldap.filter.escape_filter_chars(memberuid),
- attmap['member'],
ldap.filter.escape_filter_chars(dn) )
- return '(&%s(%s=%s))' % ( self.filter,
- attmap['memberUid'],
ldap.filter.escape_filter_chars(memberuid) )
-
class GroupAllRequest(GroupRequest):
Modified: nss-pam-ldapd/pynslcd/host.py
==============================================================================
--- nss-pam-ldapd/pynslcd/host.py Mon Dec 12 22:53:10 2011 (r1570)
+++ nss-pam-ldapd/pynslcd/host.py Mon Dec 12 23:59:00 2011 (r1571)
@@ -28,11 +28,14 @@
filter = '(objectClass=ipHost)'
-class HostRequest(common.Request):
+class Search(common.Search):
canonical_first = ('cn', )
required = ('cn', )
+
+class HostRequest(common.Request):
+
def write(self, dn, attributes, parameters):
# get values
hostnames = attributes['cn']
Modified: nss-pam-ldapd/pynslcd/netgroup.py
==============================================================================
--- nss-pam-ldapd/pynslcd/netgroup.py Mon Dec 12 22:53:10 2011 (r1570)
+++ nss-pam-ldapd/pynslcd/netgroup.py Mon Dec 12 23:59:00 2011 (r1571)
@@ -34,11 +34,14 @@
filter = '(objectClass=nisNetgroup)'
-class NetgroupRequest(common.Request):
+class Search(common.Search):
case_sensitive = ('cn', )
required = ('cn', )
+
+class NetgroupRequest(common.Request):
+
def write(self, dn, attributes, parameters):
# write the netgroup triples
for triple in attributes['nisNetgroupTriple']:
Modified: nss-pam-ldapd/pynslcd/network.py
==============================================================================
--- nss-pam-ldapd/pynslcd/network.py Mon Dec 12 22:53:10 2011 (r1570)
+++ nss-pam-ldapd/pynslcd/network.py Mon Dec 12 23:59:00 2011 (r1571)
@@ -29,11 +29,14 @@
filter = '(objectClass=ipNetwork)'
-class NetworkRequest(common.Request):
+class Search(common.Search):
canonical_first = ('cn', )
required = ('cn', )
+
+class NetworkRequest(common.Request):
+
def write(self, dn, attributes, parameters):
# get values
networknames = attributes['cn']
Modified: nss-pam-ldapd/pynslcd/passwd.py
==============================================================================
--- nss-pam-ldapd/pynslcd/passwd.py Mon Dec 12 22:53:10 2011 (r1570)
+++ nss-pam-ldapd/pynslcd/passwd.py Mon Dec 12 23:59:00 2011 (r1571)
@@ -37,13 +37,16 @@
bases = ( 'ou=people,dc=test,dc=tld', )
-class PasswdRequest(common.Request):
+class Search(common.Search):
case_sensitive = ('uid', 'uidNumber', )
limit_attributes = ('uid', 'uidNumber', )
required = ('uid', 'uidNumber', 'gidNumber', 'gecos', 'homeDirectory',
'loginShell')
+
+class PasswdRequest(common.Request):
+
def write(self, dn, attributes, parameters):
# get values
names = attributes['uid']
@@ -95,32 +98,12 @@
action = constants.NSLCD_ACTION_PASSWD_ALL
-# FIXME: have something in common that does this
-def do_search(conn, flt=None, base=None):
- mybases = ( base, ) if base else bases
- flt = flt or filter
- import cfg
- # perform a search for each search base
- for base in mybases:
- # do the LDAP search
- try:
- scope = locals().get('scope', cfg.scope)
- res = conn.search_s(base, scope, flt, [attmap['uid']])
- for entry in res:
- if entry[0]:
- yield entry
- except ldap.NO_SUCH_OBJECT:
- # FIXME: log message
- pass
-
def uid2entry(conn, uid):
"""Look up the user by uid and return the LDAP entry or None if the user
was not found."""
- myfilter = '(&%s(%s=%s))' % ( filter,
- attmap['uid'], ldap.filter.escape_filter_chars(uid) )
- for dn, attributes in do_search(conn, myfilter):
- if uid in attributes[attmap['uid']]:
- return dn, attributes
+ for dn, attributes in Search(conn, parameters=dict(uid=uid)):
+ return dn, attributes
+
def uid2dn(conn, uid):
"""Look up the user by uid and return the DN or None if the user was
@@ -131,11 +114,9 @@
# FIXME: use cache of dn2uid and try to use DN to get uid attribute
+
def dn2uid(conn, dn):
"""Look up the user by dn and return a uid or None if the user was
not found."""
- try:
- for dn, attributes in do_search(conn, base=dn):
- return attributes[attmap['uid']][0]
- except ldap.NO_SUCH_OBJECT:
- return None
+ for dn, attributes in Search(conn, base=dn):
+ return attributes['uid'][0]
Modified: nss-pam-ldapd/pynslcd/protocol.py
==============================================================================
--- nss-pam-ldapd/pynslcd/protocol.py Mon Dec 12 22:53:10 2011 (r1570)
+++ nss-pam-ldapd/pynslcd/protocol.py Mon Dec 12 23:59:00 2011 (r1571)
@@ -28,12 +28,15 @@
filter = '(objectClass=ipProtocol)'
-class ProtocolRequest(common.Request):
+class Search(common.Search):
case_sensitive = ('cn', )
canonical_first = ('cn', )
required = ('cn', 'ipProtocolNumber')
+
+class ProtocolRequest(common.Request):
+
def write(self, dn, attributes, parameters):
# get values
names = attributes['cn']
Modified: nss-pam-ldapd/pynslcd/rpc.py
==============================================================================
--- nss-pam-ldapd/pynslcd/rpc.py Mon Dec 12 22:53:10 2011 (r1570)
+++ nss-pam-ldapd/pynslcd/rpc.py Mon Dec 12 23:59:00 2011 (r1571)
@@ -28,12 +28,15 @@
filter = '(objectClass=oncRpc)'
-class RpcRequest(common.Request):
+class Search(common.Search):
case_sensitive = ('cn', )
canonical_first = ('cn', )
required = ('cn', 'oncRpcNumber')
+
+class RpcRequest(common.Request):
+
def write(self, dn, attributes, parameters):
# get values
names = attributes['cn']
Modified: nss-pam-ldapd/pynslcd/service.py
==============================================================================
--- nss-pam-ldapd/pynslcd/service.py Mon Dec 12 22:53:10 2011 (r1570)
+++ nss-pam-ldapd/pynslcd/service.py Mon Dec 12 23:59:00 2011 (r1571)
@@ -31,13 +31,16 @@
filter = '(objectClass=ipService)'
-class ServiceRequest(common.Request):
+class Search(common.Search):
case_sensitive = ('cn', 'ipServiceProtocol')
limit_attributes = ('ipServiceProtocol', )
canonical_first = ('cn', )
required = ('cn', 'ipServicePort', 'ipServiceProtocol')
+
+class ServiceRequest(common.Request):
+
def write(self, dn, attributes, parameters):
# get values
names = attributes['cn']
Modified: nss-pam-ldapd/pynslcd/shadow.py
==============================================================================
--- nss-pam-ldapd/pynslcd/shadow.py Mon Dec 12 22:53:10 2011 (r1570)
+++ nss-pam-ldapd/pynslcd/shadow.py Mon Dec 12 23:59:00 2011 (r1571)
@@ -37,12 +37,15 @@
bases = ( 'ou=people,dc=test,dc=tld', )
-class ShadowRequest(common.Request):
+class Search(common.Search):
case_sensitive = ('uid', )
limit_attributes = ('uid', )
required = ('uid', )
+
+class ShadowRequest(common.Request):
+
def write(self, dn, attributes, parameters):
# get name and check against requested name
names = attributes['uid']
--
To unsubscribe send an email to
nss-pam-ldapd-commits-unsubscribe@lists.arthurdejong.org or see
http://lists.arthurdejong.org/nss-pam-ldapd-commits/
- nss-pam-ldapd commit: r1571 - nss-pam-ldapd/pynslcd,
Commits of the nss-pam-ldapd project