lists.arthurdejong.org
RSS feed

nss-pam-ldapd commit: r1570 - nss-pam-ldapd/pynslcd

[Date Prev][Date Next] [Thread Prev][Thread Next]

nss-pam-ldapd commit: r1570 - nss-pam-ldapd/pynslcd



Author: arthur
Date: Mon Dec 12 22:53:10 2011
New Revision: 1570
URL: http://arthurdejong.org/viewvc/nss-pam-ldapd?revision=1570&view=revision

Log:
move check of required attributes and other common tests to the 
Request.handle_entry() method

Modified:
   nss-pam-ldapd/pynslcd/alias.py
   nss-pam-ldapd/pynslcd/attmap.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      Sat Dec 10 23:17:33 2011        (r1569)
+++ nss-pam-ldapd/pynslcd/alias.py      Mon Dec 12 22:53:10 2011        (r1570)
@@ -30,21 +30,14 @@
 
 class AliasRequest(common.Request):
 
+    case_insensitive = ('cn', )
+    limit_attributes = ('cn', )
+    required = ('cn', 'rfc822MailMember')
+
     def write(self, dn, attributes, parameters):
-        # get name and check against requested name
+        # get values
         names = attributes['cn']
-        if not names:
-            logging.error('Error: entry %s does not contain %s value', dn, 
attmap['cn'])
-            return
-        if 'cn' in parameters:
-            if parameters['cn'].lower() not in (x.lower() for x in names):
-                return
-            names = ( parameters['cn'], )
-        # get the members of the alias
         members = attributes['rfc822MailMember']
-        if not members:
-            logging.error('Error: entry %s does not contain %s value', dn, 
attmap['rfc822MailMember'])
-            return
         # write results
         for name in names:
             self.fp.write_int32(constants.NSLCD_RESULT_BEGIN)

Modified: nss-pam-ldapd/pynslcd/attmap.py
==============================================================================
--- nss-pam-ldapd/pynslcd/attmap.py     Sat Dec 10 23:17:33 2011        (r1569)
+++ nss-pam-ldapd/pynslcd/attmap.py     Mon Dec 12 22:53:10 2011        (r1570)
@@ -1,5 +1,5 @@
 
-# attributes.py - attribute mapping functions
+# attmap.py - attribute mapping class
 #
 # Copyright (C) 2011 Arthur de Jong
 #
@@ -27,19 +27,18 @@
 ...                    gecos='"${gecos:-$cn}"',
 ...                    homeDirectory='homeDirectory',
 ...                    loginShell='loginShell')
->>> attrs.attributes()
-('uid', 'userPassword', 'uidNumber', 'gidNumber', 'gecos', 'cn', 
'homeDirectory', 'loginShell')
->>> attrs.value('gecos', {'cn': 'test'})
-['test']
->>> attrs.search('uidNumber', 100)
-'(uidNumber=100)'
->>> attrs['foo'] = '\"bar\"'
->>> attrs.get('foo', {})
-['bar']
+>>> 'cn' in attrs.attributes()
+True
+>>> attrs.translate({'uid': ['UIDVALUE', '2nduidvalue'], 'cn': ['COMMON NAME', 
]})
+{'uid': ['UIDVALUE', '2nduidvalue'], 'loginShell': [], 'userPassword': [], 
'uidNumber': [], 'gidNumber': [], 'gecos': ['COMMON NAME'], 'homeDirectory': []}
+>>> attrs['uidNumber']  # a representation fit for logging and filters
+'uidNumber'
+>>> attrs['gecos']
+'"${gecos:-$cn}"'
 """
 
 # exported names
-__all__ = ( 'Attributes', )
+__all__ = ('Attributes', )
 
 
 # FIXME: support multiple attribute values
@@ -57,7 +56,7 @@
 
     def next(self):
         self.pos += 1
-        return self.value[self.pos-1]
+        return self.value[self.pos - 1]
 
     def back(self):
         self.pos -= 1
@@ -65,19 +64,20 @@
     def __iter__(self):
         return self
 
-
-class DollarExpression(object):
-    """Class for handling a variable $xxx ${xxx}, ${xxx:-yyy} or ${xxx:+yyy}
-    expression."""
-
-    def _parse_varname(self, value):
+    def get_name(self):
         """Read a variable name from the value iterator."""
         name = ''
-        for c in value:
+        for c in self:
             if not c.isalnum():
-                value.back()
+                self.back()
                 return name
             name += c
+        return name
+
+
+class DollarExpression(object):
+    """Class for handling a variable $xxx ${xxx}, ${xxx:-yyy} or ${xxx:+yyy}
+    expression."""
 
     def __init__(self, value):
         """Parse the expression as the start of a $-expression."""
@@ -85,7 +85,7 @@
         self.expr = None
         c = value.next()
         if c == '{':
-            self.name = self._parse_varname(value)
+            self.name = value.get_name()
             c = value.next()
             if c == '}':
                 return
@@ -93,7 +93,7 @@
             self.expr = Expression(value, endat='}')
         else:
             value.back()
-            self.name = self._parse_varname(value)
+            self.name = value.get_name()
 
     def value(self, variables):
         """Expand the expression using the variables specified."""
@@ -105,11 +105,11 @@
             return self.expr.value(variables) if value else ''
         return value
 
-    def variables(self, results):
-        """Add the variables used in the expression to results."""
+    def attributes(self, results):
+        """Add the attributes used in the expression to results."""
         results.add(self.name)
         if self.expr:
-            self.expr.variables(results)
+            self.expr.attributes(results)
 
 
 class Expression(object):
@@ -118,9 +118,10 @@
     def __init__(self, value, endat=None):
         """Parse the expression as a string."""
         if not isinstance(value, MyIter):
+            self.expression = value
             value = MyIter(value)
         if not endat:
-            endat = value.next() # skip opening quote
+            endat = value.next()  # skip opening quote
         expr = []
         literal = ''
         c = value.next()
@@ -149,18 +150,24 @@
                 res += x
         return res
 
-    def variables(self, results=None):
-        """Return the variables defined in the expression."""
+    def attributes(self, results=None):
+        """Return the attributes defined in the expression."""
         if not results:
             results = set()
         for x in self.expr:
-            if hasattr(x, 'variables'):
-                x.variables(results)
+            if hasattr(x, 'attributes'):
+                x.attributes(results)
         return results
 
+    def __str__(self):
+        return self.expression
+
+    def __repr__(self):
+        return repr(str(self))
+
 
 class Attributes(dict):
-    """Dictionary-like class for handling a list of attributes."""
+    """Dictionary-like class for handling attribute mapping."""
 
     def _prepare(self):
         """Go over all values to parse any expressions."""
@@ -171,18 +178,18 @@
         self.update(updates)
 
     def attributes(self):
-        """Return a set of attributes that are referenced in this attribute
+        """Return the list of attributes that are referenced in this attribute
         mapping."""
         self._prepare()
-        results = set()
+        attributes = set()
         for value in self.itervalues():
-            if hasattr(value, 'variables'):
-                results.update(value.variables())
+            if hasattr(value, 'attributes'):
+                attributes.update(value.attributes())
             else:
-                results.add(value)
-        return list(results)
+                attributes.add(value)
+        return list(attributes)
 
-    def mapped(self, variables):
+    def translate(self, variables):
         """Return a dictionary with every attribute mapped to their value from
         the specified variables."""
         results = dict()

Modified: nss-pam-ldapd/pynslcd/common.py
==============================================================================
--- nss-pam-ldapd/pynslcd/common.py     Sat Dec 10 23:17:33 2011        (r1569)
+++ nss-pam-ldapd/pynslcd/common.py     Mon Dec 12 22:53:10 2011        (r1570)
@@ -30,6 +30,7 @@
 
 _validname_re = re.compile(r'^[a-z0-9._@$][a-z0-9._@$ 
\\~-]{0,98}[a-z0-9._@$~-]$', re.IGNORECASE)
 
+
 def isvalidname(name):
     """Checks to see if the specified name seems to be a valid user or group
     name.
@@ -45,6 +46,7 @@
     character. As an extension this test allows some more characters."""
     return bool(_validname_re.match(name))
 
+
 def validate_name(name):
     """Checks to see if the specified name seems to be a valid user or group
     name. See isvalidname()."""
@@ -57,12 +59,29 @@
     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
-    filter: LDAP search filter
-    mk_filter (optional): function that returns the LDAP search filter
-    write: function that writes a single LDAP entry to the result stream
+      action - the NSLCD_ACTION_* action that should trigger this handler
+
+      case_sensitive - check that these attributes are present in the response
+                       if they were in the request
+      case_insensitive - check that these attributes are present in the
+                         response if they were in the request
+      limit_attributes - override response attributes with request attributes
+      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:
+
+      attmap - an attribute mapping definition (using he Attributes class)
+      filter - an LDAP search filter
+      bases - search bases to be used, falls back to cfg.bases
+      scope - search scope, falls back to cfg.scope
+
     """
 
     def __init__(self, fp, conn, calleruid):
@@ -81,19 +100,52 @@
         store them in self."""
         pass
 
-    def attributes(self):
-        """Return the attributes that should be used in the LDAP search."""
-        return self.attmap.attributes()
-
     def mk_filter(self, parameters):
         """Return the active search filter (based on the read parameters)."""
         if parameters:
-            return '(&%s(%s))' % ( self.filter,
+            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 parameters.items()))
         return self.filter
 
+    def handle_entry(self, dn, attributes, parameters):
+        """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', []):
+            primary_value = get_rdn_value(dn, self.attmap[attr])
+            if primary_value:
+                values = attributes[attr]
+                if primary_value in values:
+                    values.remove(primary_value)
+                attributes[attr] = [primary_value] + values
+        # check that these attributes have at least one value
+        for attr in getattr(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)
+            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)
+            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)
+
     def handle_request(self, parameters):
         """This method handles the request based on the parameters read
         with read_parameters()."""
@@ -101,10 +153,11 @@
         for base in self.bases:
             # do the LDAP search
             try:
-                res = self.conn.search_s(base, self.scope, 
self.mk_filter(parameters), self.attributes())
+                res = self.conn.search_s(base, self.scope, 
self.mk_filter(parameters),
+                                         self.attmap.attributes())
                 for entry in res:
                     if entry[0]:
-                        self.write(entry[0], self.attmap.mapped(entry[1]), 
parameters)
+                        self.handle_entry(entry[0], entry[1], parameters)
             except ldap.NO_SUCH_OBJECT:
                 # FIXME: log message
                 pass
@@ -130,5 +183,6 @@
             res[cls.action] = cls
     return res
 
+
 def get_rdn_value(dn, attribute):
     return dict((x, y) for x, y, z in ldap.dn.str2dn(dn)[0])[attribute]

Modified: nss-pam-ldapd/pynslcd/ether.py
==============================================================================
--- nss-pam-ldapd/pynslcd/ether.py      Sat Dec 10 23:17:33 2011        (r1569)
+++ nss-pam-ldapd/pynslcd/ether.py      Mon Dec 12 22:53:10 2011        (r1570)
@@ -40,23 +40,21 @@
 
 class EtherRequest(common.Request):
 
+    case_insensitive = ('cn', )
+    limit_attributes = ('cn', 'macAddress')
+    required = ('cn', 'macAddress')
+
     def write(self, dn, attributes, parameters):
-        # get name and check against requested name
+        # get names
         names = attributes['cn']
-        if not names:
-            print 'Error: entry %s does not contain %s value' % ( dn, 
attmap['cn'])
-        if 'cn' in parameters:
-            if parameters['cn'].lower() not in (x.lower() for x in names):
-                return # skip entry
-            names = ( parameters['cn'], )
         # get addresses and convert to binary form
         addresses = [ether_aton(x) for x in attributes['macAddress']]
-        if not addresses:
-            print 'Error: entry %s does not contain %s value' % ( dn, 
attmap['macAddress'])
         if 'macAddress' in parameters:
-            if ether_aton(parameters['macAddress']) not in addresses:
+            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 = ( ether_aton(parameters['macAddress']), )
+            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      Sat Dec 10 23:17:33 2011        (r1569)
+++ nss-pam-ldapd/pynslcd/group.py      Mon Dec 12 22:53:10 2011        (r1570)
@@ -42,20 +42,17 @@
 
 class GroupRequest(common.Request):
 
+    case_sensitive = ('cn', )
+    limit_attributes = ('cn', 'gidNumber')
     wantmembers = True
 
     def write(self, dn, attributes, parameters):
         # get group names and check against requested group name
         names = attributes['cn']
-        if 'cn' in parameters:
-            if parameters['cn'] not in names:
-                return
-            names = ( parameters['cn'], )
         # get group group password
         passwd = attributes['userPassword'][0]
         # get group id(s)
-        gids = (  parameters['gidNumber'], ) if 'gidNumber' in parameters else 
attributes['gidNumber']
-        gids = [ int(x) for x in gids ]
+        gids = [ int(x) for x in attributes['gidNumber'] ]
         # build member list
         members = set()
         if self.wantmembers:
@@ -116,9 +113,6 @@
         common.validate_name(memberuid)
         return dict(memberUid=memberuid)
 
-    def attributes(self):
-        return self.attmap.attributes()
-
     def mk_filter(self, parameters):
         # we still need a custom mk_filter because this is an | query
         memberuid = parameters['memberUid']

Modified: nss-pam-ldapd/pynslcd/host.py
==============================================================================
--- nss-pam-ldapd/pynslcd/host.py       Sat Dec 10 23:17:33 2011        (r1569)
+++ nss-pam-ldapd/pynslcd/host.py       Mon Dec 12 22:53:10 2011        (r1570)
@@ -30,18 +30,14 @@
 
 class HostRequest(common.Request):
 
+    canonical_first = ('cn', )
+    required = ('cn', )
+
     def write(self, dn, attributes, parameters):
-        hostname = common.get_rdn_value(dn, attmap['cn'])
+        # get values
         hostnames = attributes['cn']
-        if not hostnames:
-            print 'Error: entry %s does not contain %s value' % ( dn, 
attmap['cn'] )
-        if not hostname:
-            hostname = hostnames.pop(0)
-        elif hostname in hostnames:
-            hostnames.remove(hostname)
+        hostname = hostnames.pop(0)
         addresses = attributes['ipHostNumber']
-        if not addresses:
-            print 'Error: entry %s does not contain %s value' % ( dn, 
attmap['ipHostNumber'] )
         # write result
         self.fp.write_int32(constants.NSLCD_RESULT_BEGIN)
         self.fp.write_string(hostname)

Modified: nss-pam-ldapd/pynslcd/netgroup.py
==============================================================================
--- nss-pam-ldapd/pynslcd/netgroup.py   Sat Dec 10 23:17:33 2011        (r1569)
+++ nss-pam-ldapd/pynslcd/netgroup.py   Mon Dec 12 22:53:10 2011        (r1570)
@@ -36,15 +36,10 @@
 
 class NetgroupRequest(common.Request):
 
+    case_sensitive = ('cn', )
+    required = ('cn', )
+
     def write(self, dn, attributes, parameters):
-        # get names and check against requested user name
-        names = attributes['cn']
-        if 'cn' in parameters:
-            if parameters['cn'] not in names:
-                return
-            names = ( parameters['cn'], )
-        if not names:
-            print 'Error: entry %s does not contain %s value' % (dn, 
attmap['cn'])
         # write the netgroup triples
         for triple in attributes['nisNetgroupTriple']:
             m = _netgroup_triple_re.match(triple)

Modified: nss-pam-ldapd/pynslcd/network.py
==============================================================================
--- nss-pam-ldapd/pynslcd/network.py    Sat Dec 10 23:17:33 2011        (r1569)
+++ nss-pam-ldapd/pynslcd/network.py    Mon Dec 12 22:53:10 2011        (r1570)
@@ -31,18 +31,14 @@
 
 class NetworkRequest(common.Request):
 
+    canonical_first = ('cn', )
+    required = ('cn', )
+
     def write(self, dn, attributes, parameters):
-        networkname = common.get_rdn_value(dn, attmap['cn'])
+        # get values
         networknames = attributes['cn']
-        if not networknames:
-            print 'Error: entry %s does not contain %s value' % (dn, 
attmap['cn'])
-        if not networkname:
-            networkname = networknames.pop(0)
-        elif networkname in networknames:
-            networknames.remove(networkname)
+        networkname = networknames.pop(0)
         addresses = attributes['ipNetworkNumber']
-        if not addresses:
-            print 'Error: entry %s does not contain %s value' % (dn, 
attmap['ipNetworkNumber'])
         # write result
         self.fp.write_int32(constants.NSLCD_RESULT_BEGIN)
         self.fp.write_string(networkname)

Modified: nss-pam-ldapd/pynslcd/passwd.py
==============================================================================
--- nss-pam-ldapd/pynslcd/passwd.py     Sat Dec 10 23:17:33 2011        (r1569)
+++ nss-pam-ldapd/pynslcd/passwd.py     Mon Dec 12 22:53:10 2011        (r1570)
@@ -39,22 +39,19 @@
 
 class PasswdRequest(common.Request):
 
+    case_sensitive = ('uid', 'uidNumber', )
+    limit_attributes = ('uid', 'uidNumber', )
+    required = ('uid', 'uidNumber', 'gidNumber', 'gecos', 'homeDirectory',
+                'loginShell')
+
     def write(self, dn, attributes, parameters):
-        # get uid attribute and check against requested user name
+        # get values
         names = attributes['uid']
-        if 'uid' in parameters:
-            if parameters['uid'] not in names:
-                return
-            names = ( parameters['uid'], )
-        # get user password entry
         if 'shadowAccount' in attributes['objectClass']:
             passwd = 'x'
         else:
             passwd = attributes['userPassword'][0]
-        # get numeric user and group ids
-        uids = ( parameters['uidNumber'], ) if 'uidNumber' in parameters else 
attributes['uidNumber']
-        uids = [ int(x) for x in uids ]
-        # get other passwd properties
+        uids = [ int(x) for x in attributes['uidNumber'] ]
         gid = int(attributes['gidNumber'][0])
         gecos = attributes['gecos'][0]
         home = attributes['homeDirectory'][0]

Modified: nss-pam-ldapd/pynslcd/protocol.py
==============================================================================
--- nss-pam-ldapd/pynslcd/protocol.py   Sat Dec 10 23:17:33 2011        (r1569)
+++ nss-pam-ldapd/pynslcd/protocol.py   Mon Dec 12 22:53:10 2011        (r1570)
@@ -30,23 +30,15 @@
 
 class ProtocolRequest(common.Request):
 
+    case_sensitive = ('cn', )
+    canonical_first = ('cn', )
+    required = ('cn', 'ipProtocolNumber')
+
     def write(self, dn, attributes, parameters):
-        # get name
-        name = common.get_rdn_value(dn, attmap['cn'])
+        # get values
         names = attributes['cn']
-        if not names:
-            print 'Error: entry %s does not contain %s value' % (dn, 
attmap['cn'])
-        if 'cn' in parameters and parameters['cn'] not in names:
-            return # case of result entry did not match
-        if not name:
-            name = names.pop(0)
-        elif name in names:
-            names.remove(name)
-        # get number
-        ( number, ) = attributes['ipProtocolNumber']
-        if not number:
-            print 'Error: entry %s does not contain %s value' % (dn, 
attmap['ipProtocolNumber'])
-        number = int(number)
+        name = names.pop(0)
+        number = int(attributes['ipProtocolNumber'][0])
         # write result
         self.fp.write_int32(constants.NSLCD_RESULT_BEGIN)
         self.fp.write_string(name)

Modified: nss-pam-ldapd/pynslcd/rpc.py
==============================================================================
--- nss-pam-ldapd/pynslcd/rpc.py        Sat Dec 10 23:17:33 2011        (r1569)
+++ nss-pam-ldapd/pynslcd/rpc.py        Mon Dec 12 22:53:10 2011        (r1570)
@@ -30,23 +30,15 @@
 
 class RpcRequest(common.Request):
 
+    case_sensitive = ('cn', )
+    canonical_first = ('cn', )
+    required = ('cn', 'oncRpcNumber')
+
     def write(self, dn, attributes, parameters):
-        # get name
-        name = common.get_rdn_value(dn, attmap['cn'])
+        # get values
         names = attributes['cn']
-        if not names:
-            print 'Error: entry %s does not contain %s value' % ( dn, 
attmap['cn'] )
-        if 'cn' in parameters and parameters['cn'] not in names:
-            return # case of result entry did not match
-        if not name:
-            name = names.pop(0)
-        elif name in names:
-            names.remove(name)
-        # get number
-        ( number, ) = attributes['oncRpcNumber']
-        if not number:
-            print 'Error: entry %s does not contain %s value' % ( dn, 
attmap['oncRpcNumber'])
-        number = int(number)
+        name = names.pop(0)
+        number = int(attributes['oncRpcNumber'][0])
         # write result
         self.fp.write_int32(constants.NSLCD_RESULT_BEGIN)
         self.fp.write_string(name)

Modified: nss-pam-ldapd/pynslcd/service.py
==============================================================================
--- nss-pam-ldapd/pynslcd/service.py    Sat Dec 10 23:17:33 2011        (r1569)
+++ nss-pam-ldapd/pynslcd/service.py    Mon Dec 12 22:53:10 2011        (r1570)
@@ -33,29 +33,17 @@
 
 class ServiceRequest(common.Request):
 
+    case_sensitive = ('cn', 'ipServiceProtocol')
+    limit_attributes = ('ipServiceProtocol', )
+    canonical_first = ('cn', )
+    required = ('cn', 'ipServicePort', 'ipServiceProtocol')
+
     def write(self, dn, attributes, parameters):
-        # get name
-        name = common.get_rdn_value(dn, attmap['cn'])
+        # get values
         names = attributes['cn']
-        if not names:
-            print 'Error: entry %s does not contain %s value' % (dn, 
attmap['cn'])
-        if 'cn' in parameters and parameters['cn'] not in names + [ name, ]:
-            return # case of result entry did not match
-        if not name:
-            name = names.pop(0)
-        elif name in names:
-            names.remove(name)
-        # get port number
-        ( port, ) = attributes['ipServicePort']
-        if not port:
-            print 'Error: entry %s does not contain %s value' % (dn, 
attmap['ipServicePort'])
-        port = int(port)
-        # get protocol
+        name = names.pop(0)
+        port = int(attributes['ipServicePort'][0])
         protocols = attributes['ipServiceProtocol']
-        if 'ipServiceProtocol' in parameters:
-            if parameters['ipServiceProtocol'] not in protocols:
-                return
-            protocols = ( parameters['ipServiceProtocol'], )
         # write result
         for protocol in protocols:
             self.fp.write_int32(constants.NSLCD_RESULT_BEGIN)

Modified: nss-pam-ldapd/pynslcd/shadow.py
==============================================================================
--- nss-pam-ldapd/pynslcd/shadow.py     Sat Dec 10 23:17:33 2011        (r1569)
+++ nss-pam-ldapd/pynslcd/shadow.py     Mon Dec 12 22:53:10 2011        (r1570)
@@ -39,16 +39,13 @@
 
 class ShadowRequest(common.Request):
 
+    case_sensitive = ('uid', )
+    limit_attributes = ('uid', )
+    required = ('uid', )
+
     def write(self, dn, attributes, parameters):
         # get name and check against requested name
         names = attributes['uid']
-        if not names:
-            print 'Error: entry %s does not contain %s value' % ( dn, 
attmap['uid'] )
-            return
-        if 'uid' in parameters:
-            if parameters['uid'] not in names:
-                return
-            names = ( parameters['uid'], )
         # get password
         (passwd, ) = attributes['userPassword']
         if not passwd or self.calleruid != 0:
@@ -56,11 +53,11 @@
         # function for making an int
         def mk_int(attr):
             try:
-                return
+                return int(attr)
             except TypeError:
                 return None
         # get lastchange date
-        lastchangedate = int(attributes.get('shadowLastChange', [0])[0])
+        lastchangedate = mk_int(attributes.get('shadowLastChange', [0])[0])
         # we expect an AD 64-bit datetime value;
         # we should do date=date/864000000000-134774
         # but that causes problems on 32-bit platforms,
@@ -69,12 +66,12 @@
         if attmap['shadowLastChange'] == 'pwdLastSet':
             lastchangedate = ( lastchangedate / 864000000000 ) - 134774
         # get longs
-        mindays = int(attributes.get('shadowMin', [-1])[0])
-        maxdays = int(attributes.get('shadowMax', [-1])[0])
-        warndays = int(attributes.get('shadowWarning', [-1])[0])
-        inactdays = int(attributes.get('shadowInactive', [-1])[0])
-        expiredate = int(attributes.get('shadowExpire', [-1])[0])
-        flag = int(attributes.get('shadowFlag', [0])[0])
+        mindays = mk_int(attributes.get('shadowMin', [-1])[0])
+        maxdays = mk_int(attributes.get('shadowMax', [-1])[0])
+        warndays = mk_int(attributes.get('shadowWarning', [-1])[0])
+        inactdays = mk_int(attributes.get('shadowInactive', [-1])[0])
+        expiredate = mk_int(attributes.get('shadowExpire', [-1])[0])
+        flag = mk_int(attributes.get('shadowFlag', [0])[0])
         if attmap['shadowFlag'] == 'pwdLastSet':
             if flag & 0x10000:
                 maxdays = -1
-- 
To unsubscribe send an email to
nss-pam-ldapd-commits-unsubscribe@lists.arthurdejong.org or see
http://lists.arthurdejong.org/nss-pam-ldapd-commits/