lists.arthurdejong.org
RSS feed

nss-pam-ldapd branch master updated. 0.8.12-145-gadde1d4

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

nss-pam-ldapd branch master updated. 0.8.12-145-gadde1d4



This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "nss-pam-ldapd".

The branch, master has been updated
       via  adde1d4cd3b7bfdd9ed523ad9e0c81f1ca5f6de5 (commit)
       via  a75cfb9d5f67dd4be325f151f9e0fc9af0864ac2 (commit)
       via  585d38894b32551fba68ea9b202c12ce5f8cc966 (commit)
       via  d4c5c96f0c94e3f930dcda29a2b843baac37b07f (commit)
       via  11b1739afc43b5e444a5ac173b08b13b5b5fbc07 (commit)
       via  65a65adbf953ee8da43a76db2cd03a064a80cd46 (commit)
      from  46cf240eff487be2cdbe86439805f3adb8f570ef (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://arthurdejong.org/git/nss-pam-ldapd/commit/?id=adde1d4cd3b7bfdd9ed523ad9e0c81f1ca5f6de5

commit adde1d4cd3b7bfdd9ed523ad9e0c81f1ca5f6de5
Merge: 65a65ad a75cfb9
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Fri Mar 29 20:23:54 2013 +0100

    Implement clearing of nscd cache in pynslcd


http://arthurdejong.org/git/nss-pam-ldapd/commit/?id=a75cfb9d5f67dd4be325f151f9e0fc9af0864ac2

commit a75cfb9d5f67dd4be325f151f9e0fc9af0864ac2
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Fri Mar 29 20:14:49 2013 +0100

    Detect and handle connection failure and recovery
    
    Logs a connection recovery message and run a nscd cache invalidation if
    configured.

diff --git a/pynslcd/nscd.py b/pynslcd/nscd.py
index 89cb483..19e5ceb 100644
--- a/pynslcd/nscd.py
+++ b/pynslcd/nscd.py
@@ -24,6 +24,8 @@ import os
 import subprocess
 import struct
 
+import cfg
+
 
 # the file descriptor used for sending messages to the child process
 signalfd = None
@@ -100,7 +102,10 @@ def start_invalidator():
 def invalidate(db=None):
     if signalfd is None:
         return  # nothing to do
-    db = _db_to_char.get(db, '')
+    if db:
+        db = _db_to_char.get(db, '')
+    else:
+        db = ''.join(_db_to_char[x] for x in cfg.nscd_invalidate)
     try:
         os.write(signalfd, db)
     except:
diff --git a/pynslcd/search.py b/pynslcd/search.py
index 9629bec..219929b 100644
--- a/pynslcd/search.py
+++ b/pynslcd/search.py
@@ -25,6 +25,11 @@ import ldap
 import ldap.ldapobject
 
 import cfg
+import nscd
+
+
+# global indicator that there was some error connection to an LDAP server
+server_error = False
 
 
 class Connection(ldap.ldapobject.ReconnectLDAPObject):
@@ -50,6 +55,23 @@ class Connection(ldap.ldapobject.ReconnectLDAPObject):
         if cfg.ssl or cfg.uri.startswith('ldaps://'):
             self.set_option(ldap.OPT_X_TLS, ldap.OPT_X_TLS_HARD)
 
+    def reconnect_after_fail(self):
+        logging.info('connected to LDAP server %s', cfg.uri)
+        nscd.invalidate()
+
+    def search_s(self, *args, **kwargs):
+        # wrapper function to keep the global server_error state
+        global server_error
+        try:
+            res = ldap.ldapobject.ReconnectLDAPObject.search_s(self, *args, 
**kwargs)
+        except ldap.SERVER_DOWN:
+            server_error = True
+            raise
+        if server_error:
+            self.reconnect_after_fail()
+            server_error = False
+        return res
+
 
 class LDAPSearch(object):
     """

http://arthurdejong.org/git/nss-pam-ldapd/commit/?id=585d38894b32551fba68ea9b202c12ce5f8cc966

commit 585d38894b32551fba68ea9b202c12ce5f8cc966
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Fri Mar 29 17:03:53 2013 +0100

    Start the nscd invalidator process if needed

diff --git a/pynslcd/pynslcd.py b/pynslcd/pynslcd.py
index 0082f24..eedab78 100755
--- a/pynslcd/pynslcd.py
+++ b/pynslcd/pynslcd.py
@@ -35,6 +35,7 @@ import cfg
 import common
 import constants
 import mypidfile
+import nscd
 import search
 
 
@@ -316,6 +317,9 @@ if __name__ == '__main__':
                 logging.getLogger().setLevel(min(level for method, level in 
cfg.logs))
                 logging.getLogger().removeHandler(stderrhandler)
             logging.info('version %s starting', constants.VERSION)
+            # start nscd sub-process if needed
+            if cfg.nscd_invalidate:
+                nscd.start_invalidator()
             # create socket
             nslcd_serversocket = create_socket()
             # load supplementary groups

http://arthurdejong.org/git/nss-pam-ldapd/commit/?id=d4c5c96f0c94e3f930dcda29a2b843baac37b07f

commit d4c5c96f0c94e3f930dcda29a2b843baac37b07f
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sat Mar 9 19:30:18 2013 +0100

    Parse the nscd_invalidate option

diff --git a/pynslcd/cfg.py b/pynslcd/cfg.py
index b03b8c7..eaeaff0 100644
--- a/pynslcd/cfg.py
+++ b/pynslcd/cfg.py
@@ -89,6 +89,7 @@ nss_nested_groups = False
 validnames = re.compile(r'^[a-z0-9._@$][a-z0-9._@$ 
\\~-]{0,98}[a-z0-9._@$~-]$', re.IGNORECASE)
 pam_authz_searches = []
 pam_password_prohibit_message = None
+nscd_invalidate = set()
 
 
 # allowed boolean values
@@ -312,6 +313,16 @@ def read(filename):
             flags = 0 | re.IGNORECASE if m.group('flags') == 'i' else 0
             validnames = re.compile(m.group('value'), flags=flags)
             continue
+        # nscd_invalidate <MAP>,<MAP>,...
+        m = re.match('nscd_invalidate\s+(?P<value>\S.*)',
+                     line, re.IGNORECASE)
+        if m:
+            dbs = re.split('[ ,]+', m.group('value').lower())
+            for db in dbs:
+                if db not in maps:
+                    raise ParseError(filename, lineno, 'map %s unknown' % db)
+            nscd_invalidate.update(dbs)
+            continue
         # unrecognised line
         raise ParseError(filename, lineno, 'error parsing line %r' % line)
     # if logging is not configured, default to syslog

http://arthurdejong.org/git/nss-pam-ldapd/commit/?id=11b1739afc43b5e444a5ac173b08b13b5b5fbc07

commit 11b1739afc43b5e444a5ac173b08b13b5b5fbc07
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Fri Mar 29 20:13:45 2013 +0100

    Functionality for clearing the nscd cache in pynslcd

diff --git a/pynslcd/Makefile.am b/pynslcd/Makefile.am
index cff5629..6203d12 100644
--- a/pynslcd/Makefile.am
+++ b/pynslcd/Makefile.am
@@ -20,7 +20,7 @@
 pynslcddir = $(datadir)/pynslcd
 
 pynslcd_PYTHON = pynslcd.py attmap.py cache.py cfg.py common.py expr.py \
-                 mypidfile.py search.py tio.py \
+                 mypidfile.py nscd.py search.py tio.py \
                  alias.py ether.py group.py host.py netgroup.py network.py \
                  pam.py passwd.py protocol.py rpc.py service.py shadow.py
 nodist_pynslcd_PYTHON = constants.py
diff --git a/pynslcd/nscd.py b/pynslcd/nscd.py
new file mode 100644
index 0000000..89cb483
--- /dev/null
+++ b/pynslcd/nscd.py
@@ -0,0 +1,107 @@
+
+# nscd.py - functions for invalidating the nscd cache
+#
+# Copyright (C) 2013 Arthur de Jong
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+import fcntl
+import logging
+import os
+import subprocess
+import struct
+
+
+# the file descriptor used for sending messages to the child process
+signalfd = None
+
+
+# mapping between map name and signal character
+_db_to_char = dict(
+        aliases='A', ethers='E', group='G', hosts='H', netgroup='U',
+        networks='N', passwd='P', protocols='L', rpc='R', services='V',
+        shadow='S',
+    )
+_char_to_db = dict((reversed(item) for item in _db_to_char.items()))
+
+
+def exec_invalidate(db):
+    logging.debug('nscd_invalidator: nscd -i %s', db)
+    try:
+        p = subprocess.Popen(['nscd', '-i', 'passwd'],
+                             bufsize=4096, close_fds=True,
+                             stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+        output, ignored = p.communicate()
+        if output:
+            output = ': %s' % output[:1024].strip()
+        if p.returncode == 0:
+            logging.debug('nscd_invalidator: nscd -i %s (pid %d) success%s',
+                          db, p.pid, output)
+        elif p.returncode > 0:
+            logging.debug('nscd_invalidator: nscd -i %s (pid %d) failed 
(%d)%s',
+                          db, p.pid, p.returncode, output)
+        else:  # p.returncode < 0
+            logging.error('nscd_invalidator: nscd -i %s (pid %d) killed by 
signal %d%s',
+                          db, p.pid, -p.returncode, output)
+    except:
+        logging.warn('nscd_invalidator: nscd -i %s failed', db, exc_info=True)
+
+
+def loop(fd):
+    # set process title
+    try:
+        import setproctitle
+        setproctitle.setproctitle('(nscd invalidator)')
+    except ImportError:
+        pass
+    # set up clean environment
+    os.chdir('/')
+    os.environ['PATH'] = '/usr/sbin:/usr/bin:/sbin:/bin'
+    while True:
+        db = os.read(fd, 1)
+        # FIXME: define the characters and maps somewhere
+        if db == '':
+            break
+        db = _char_to_db.get(db, None)
+        if db:
+            exec_invalidate(db)
+
+
+def start_invalidator():
+    r, w = os.pipe()
+    # mark write end as non-blocking
+    flags = fcntl.fcntl(w, fcntl.F_GETFL)
+    fcntl.fcntl(w, fcntl.F_SETFL, flags | os.O_NONBLOCK)
+    cpid = os.fork()
+    if cpid == 0:
+        # we are the child
+        os.close(w)
+        loop(r)
+        os._exit(1)
+    # we are the parent
+    global signalfd
+    signalfd = w
+    os.close(r)
+
+
+def invalidate(db=None):
+    if signalfd is None:
+        return  # nothing to do
+    db = _db_to_char.get(db, '')
+    try:
+        os.write(signalfd, db)
+    except:
+        logging.warn('nscd_invalidator: nscd -i %s failed', db, exc_info=True)

http://arthurdejong.org/git/nss-pam-ldapd/commit/?id=65a65adbf953ee8da43a76db2cd03a064a80cd46

commit 65a65adbf953ee8da43a76db2cd03a064a80cd46
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Fri Mar 29 17:16:58 2013 +0100

    Switch to using os.environ instead of os.putenv()
    
    The os.putenv() call doesn't update os.environ and Python documentation
    recommends using os.environ.

diff --git a/pynslcd/pynslcd.py b/pynslcd/pynslcd.py
index 6c2d28a..0082f24 100755
--- a/pynslcd/pynslcd.py
+++ b/pynslcd/pynslcd.py
@@ -252,9 +252,9 @@ if __name__ == '__main__':
     parse_cmdline()
     # clean the environment
     os.environ.clear()
-    os.putenv('HOME', '/')
-    os.putenv('TMPDIR', '/tmp')
-    os.putenv('LDAPNOINIT', '1')
+    os.environ['HOME'] = '/'
+    os.environ['TMPDIR'] = '/tmp'
+    os.environ['LDAPNOINIT'] = '1'
     # set log level
     if debugging:
         logging.getLogger().setLevel(logging.DEBUG)

-----------------------------------------------------------------------

Summary of changes:
 pynslcd/Makefile.am |    2 +-
 pynslcd/cfg.py      |   11 +++++
 pynslcd/nscd.py     |  112 +++++++++++++++++++++++++++++++++++++++++++++++++++
 pynslcd/pynslcd.py  |   10 +++-
 pynslcd/search.py   |   22 ++++++++++
 5 files changed, 153 insertions(+), 4 deletions(-)
 create mode 100644 pynslcd/nscd.py


hooks/post-receive
-- 
nss-pam-ldapd
-- 
To unsubscribe send an email to
nss-pam-ldapd-commits-unsubscribe@lists.arthurdejong.org or see
http://lists.arthurdejong.org/nss-pam-ldapd-commits/