Hello community,

here is the log from the commit of package python-slapdsock for 
openSUSE:Factory checked in at 2017-07-04 09:11:49
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-slapdsock (Old)
 and      /work/SRC/openSUSE:Factory/.python-slapdsock.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-slapdsock"

Tue Jul  4 09:11:49 2017 rev:3 rq:507844 version:0.5.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-slapdsock/python-slapdsock.changes        
2017-03-20 17:13:41.882836516 +0100
+++ /work/SRC/openSUSE:Factory/.python-slapdsock.new/python-slapdsock.changes   
2017-07-04 09:12:06.468151731 +0200
@@ -1,0 +2,6 @@
+Sun Jul  2 16:20:19 UTC 2017 - [email protected]
+
+- update to upstream release 0.5.3
+- added source archive signature check
+
+-------------------------------------------------------------------

Old:
----
  slapdsock-0.5.2.tar.gz

New:
----
  python-slapdsock.keyring
  slapdsock-0.5.3.tar.gz
  slapdsock-0.5.3.tar.gz.asc

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-slapdsock.spec ++++++
--- /var/tmp/diff_new_pack.LSbWZ5/_old  2017-07-04 09:12:10.875531928 +0200
+++ /var/tmp/diff_new_pack.LSbWZ5/_new  2017-07-04 09:12:10.879531366 +0200
@@ -17,13 +17,15 @@
 
 
 Name:           python-slapdsock
-Version:        0.5.2
+Version:        0.5.3
 Release:        0
 Summary:        Python module for slapd-sock listeners
 License:        Apache-2.0
 Group:          Development/Languages/Python
 Url:            https://www.stroeder.com/slapdsockd.html
-Source:         
https://files.pythonhosted.org/packages/source/s/slapdsock/slapdsock-%{version}.tar.gz
+Source0:        
https://files.pythonhosted.org/packages/source/s/slapdsock/slapdsock-%{version}.tar.gz
+Source1:        
https://files.pythonhosted.org/packages/source/s/slapdsock/slapdsock-%{version}.tar.gz.asc
+Source2:        python-slapdsock.keyring
 BuildRequires: python-devel
 BuildRequires: python-setuptools
 BuildRequires: python-ldap

++++++ python-slapdsock.keyring ++++++
pub   rsa2048 2016-03-07 [SC]
      43C8730E84A20E560722806C07DC7AE36A8BC938
uid           [ unknown] Michael Ströder <[email protected]>
sub   rsa2048 2016-03-07 [E]

-----BEGIN PGP PUBLIC KEY BLOCK-----

mQENBFbdnRoBCADj0vYA4aRwKJ6AE4mf8oElLgMT/1eLNKpJ2FYBWcwj9d8dTk5/
p9b8DRxyS/qQIUUZqt9xRFZwUCm0vFeQMRDeN9xzAKoRzrJifoDOacOjG1lhZTKY
vVZGgUT89Ao3QeHhQ7gPzcAKNoueoR2y3FXStOYuRrbk5PlSjVAITjsotgc7PWE9
mmVYpeu8a+byK/DBHKUyolOA1UXYvDa7MbPhMtdNm8qnwtKs1Vsyk1VkErM+5cIe
+zTT6WYQcmZMRjCtWGiFTzk9W6MdlskkWRTKhKNgokTsgcy1ecaCBUZWxv/SyXgD
81+rwRi9b8Px+1reg43ayxi8sV7jrI1feybbABEBAAG0J01pY2hhZWwgU3Ryw7Zk
ZXIgPG1pY2hhZWxAc3Ryb2VkZXIuY29tPokBNwQTAQgAIQUCVt2dGgIbAwULCQgH
AgYVCAkKCwIEFgIDAQIeAQIXgAAKCRAH3HrjaovJOFpTCACjO773gcmJKvzjiNpU
Fl/gANyaJgIq4VbMQ7VthRb1F9X6YbdJ6Z99ntyESjGFCpjofcSomr2vJDpv6ht+
lY33yo20YwsMpqe2OeId0jPybG+FtabKjgBNoAk7iqnBGUvE4t0dz0n1LQVCQR2j
xyTKmcNqOYpsRZ3H+6kWwJMuVgsNZglINVZ8JgV5QuLYN5jhYz+pOuFnU11bV6nW
REvzZXzebe7g7Zus6AsWjtJ0lDvgBNzLlF3/eFrVch6Bejs0SvuFseIdZQk+4YU6
Rb8xul/jDFXIfo7eTmijO3dVT5AmC1cUi8czncwpgAJnEH8vYv23RoN/aw2gSMCS
2huIuQENBFbdnRoBCAC7L1cTVBVZZuM/yxSUM5CsgGBlTD1Cr7C2ngZFsHSYXVLq
6NUB8GZA2iLK96CrwnFw4/Jjz4llOjc50iVRMQKLRyFWOJAMrpPq2ew5T+Uoo524
D//dwVbqkFVVuvM8NPiKIDyPGCjP+acM1D8hXwhOXgQ8Iz8Q3/GRSYjitn9JrkF0
ia2nhariznBKVu0LDffxF/hOCx45+QRR2/rYYlshfZMB7nEJX9P+hVfMCSzltz9Z
8CldeUbiJvnyrISReR2XBw9oh8JkIUP0BtpIaify9A7EfzOk+W9BUnWe+YwdSUsB
fJxOhSv+umyW5GMqZGFu+4oYnkzbe+1LUs1JarCtABEBAAGJAR8EGAEIAAkFAlbd
nRoCGwwACgkQB9x642qLyTjEUgf+JX6Atatl/QKe37yCj1OZYNPd3B0rPLJRF5mE
mrADRXLZC9+uFeDSWxxln040gnR6rjBHrRcvVmlTDiZY26iuL16+V+0/aZ9uyXNQ
Szk2cwDSiI/8gvr72Y+FN5fhcGXpeNHxHilYc9onzDhxyE76cwzqTKm4q2ULIH2u
9IHQ5O86Fv6nHPYhe2fy1bhQapNwi/Xl3G3i2WNH/w7m+1zWU1IddZOjmXzoxLT1
BATwXGa0Tt5RjVb2mM1Wg3Zj6kqFkF2vvKcvrwj0q0Ap5uyfN5m0uWzQMCMoaV9H
Qf7f5MkS1lnwBqDgnojjVAieX5uk7olUiRuPKHMfhvXulYP8AA==
=D+4K
-----END PGP PUBLIC KEY BLOCK-----
++++++ slapdsock-0.5.2.tar.gz -> slapdsock-0.5.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/slapdsock-0.5.2/PKG-INFO new/slapdsock-0.5.3/PKG-INFO
--- old/slapdsock-0.5.2/PKG-INFO        2017-03-20 11:45:10.000000000 +0100
+++ new/slapdsock-0.5.3/PKG-INFO        2017-07-02 18:18:43.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: slapdsock
-Version: 0.5.2
+Version: 0.5.3
 Summary: Module package for back-sock listeners for OpenLDAP
 Home-page: https://www.stroeder.com/slapdsock.html
 Author: Michael Stroeder
Binary files old/slapdsock-0.5.2/examples/openldap/accesslog/data.mdb and 
new/slapdsock-0.5.3/examples/openldap/accesslog/data.mdb differ
Binary files old/slapdsock-0.5.2/examples/openldap/accesslog/lock.mdb and 
new/slapdsock-0.5.3/examples/openldap/accesslog/lock.mdb differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/slapdsock-0.5.2/examples/openldap/realdb.conf 
new/slapdsock-0.5.3/examples/openldap/realdb.conf
--- old/slapdsock-0.5.2/examples/openldap/realdb.conf   2017-03-20 
10:43:48.000000000 +0100
+++ new/slapdsock-0.5.3/examples/openldap/realdb.conf   2017-07-01 
23:36:38.000000000 +0200
@@ -4,11 +4,11 @@
 
 database  mdb
 
-suffix    "ou=realdb,dc=example,dc=org"
+suffix    "ou=data,dc=example,dc=org"
 
 directory realdb
 
-rootdn    "cn=root,ou=realdb,dc=example,dc=org"
+rootdn    "cn=root,ou=data,dc=example,dc=org"
 rootpw    testsecret
 lastmod   on
 
@@ -16,11 +16,27 @@
 
 overlay sock
 extensions binddn peername ssf connid
-socketpath sockoverlay-listener
-sockops bind unbind search compare modify modrdn add delete
-sockresps result search
+socketpath /tmp/modify-listener
+sockops modify
+
+#overlay sock
+#extensions binddn peername ssf connid
+#socketpath /tmp/bind-listener
+#sockops bind
+
+access to
+  dn.subtree="ou=data,dc=example,dc=org"
+  attrs=userPassword
+    by self =wx
+    by anonymous auth
+    by * none
 
 access to
-  dn.subtree="ou=realdb,dc=example,dc=org"
+  dn.subtree="ou=data,dc=example,dc=org"
+  attrs=entry
+    by self write
     by * read
 
+access to
+  dn.subtree="ou=data,dc=example,dc=org"
+    by * read
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/slapdsock-0.5.2/examples/openldap/realdb.ldif 
new/slapdsock-0.5.3/examples/openldap/realdb.ldif
--- old/slapdsock-0.5.2/examples/openldap/realdb.ldif   2016-04-22 
22:37:55.000000000 +0200
+++ new/slapdsock-0.5.3/examples/openldap/realdb.ldif   2017-06-21 
19:52:01.000000000 +0200
@@ -1,12 +1,16 @@
-dn: ou=realdb,dc=example,dc=org
+dn: ou=data,dc=example,dc=org
 objectClass: organizationalUnit
 ou: realdb
 
-dn: uid=test1,ou=realdb,dc=example,dc=org
+dn: uid=test1,ou=data,dc=example,dc=org
 objectClass: account
+objectClass: simpleSecurityObject
 uid: test1
+userPassword: testpw1
 
-dn: uid=test2,ou=realdb,dc=example,dc=org
+dn: uid=test2,ou=data,dc=example,dc=org
 objectClass: account
+objectClass: simpleSecurityObject
 uid: test2
+userPassword: testpw2
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/slapdsock-0.5.2/examples/openldap/schema/init.schema 
new/slapdsock-0.5.3/examples/openldap/schema/init.schema
--- old/slapdsock-0.5.2/examples/openldap/schema/init.schema    2017-03-20 
10:39:03.000000000 +0100
+++ new/slapdsock-0.5.3/examples/openldap/schema/init.schema    1970-01-01 
01:00:00.000000000 +0100
@@ -1,11 +0,0 @@
-##################################################################
-# Erforderliche Schema-Definitionen
-##################################################################
-
-# Schemata aus der OpenLDAP-Distribution
-include /etc/openldap/schema/core.schema
-include /etc/openldap/schema/cosine.schema
-include /etc/openldap/schema/inetorgperson.schema
-include /etc/openldap/schema/misc.schema
-include /etc/openldap/schema/openldap.schema
-include /etc/openldap/schema/ppolicy.schema
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/slapdsock-0.5.2/examples/openldap/slapd-sock-test.args 
new/slapdsock-0.5.3/examples/openldap/slapd-sock-test.args
--- old/slapdsock-0.5.2/examples/openldap/slapd-sock-test.args  2017-03-20 
10:43:49.000000000 +0100
+++ new/slapdsock-0.5.3/examples/openldap/slapd-sock-test.args  1970-01-01 
01:00:00.000000000 +0100
@@ -1 +0,0 @@
-/usr/sbin/slapd -d stats,shell -h ldap://0.0.0.0:9876 
ldapi://%2Fhome%2Fmichael%2FProj%2Fslapd_sockd%2Fexamples%2Fopenldap%2Fldapi -n 
slapd-sock-test -f slapd.conf 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/slapdsock-0.5.2/examples/openldap/slapd-sock-test.pid 
new/slapdsock-0.5.3/examples/openldap/slapd-sock-test.pid
--- old/slapdsock-0.5.2/examples/openldap/slapd-sock-test.pid   2017-03-20 
10:43:49.000000000 +0100
+++ new/slapdsock-0.5.3/examples/openldap/slapd-sock-test.pid   1970-01-01 
01:00:00.000000000 +0100
@@ -1 +0,0 @@
-28352
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/slapdsock-0.5.2/examples/openldap/slapd.conf 
new/slapdsock-0.5.3/examples/openldap/slapd.conf
--- old/slapdsock-0.5.2/examples/openldap/slapd.conf    2016-04-22 
22:37:55.000000000 +0200
+++ new/slapdsock-0.5.3/examples/openldap/slapd.conf    2017-06-28 
13:27:58.000000000 +0200
@@ -2,27 +2,38 @@
 # Test configuration for demonstrating back-sock as database and overlay
 ############################################################################
 
-include schema/init.schema
+# include standard OpenLDAP schema files
+include /etc/openldap/schema/core.schema
+include /etc/openldap/schema/cosine.schema
+include /etc/openldap/schema/inetorgperson.schema
+include /etc/openldap/schema/misc.schema
+include /etc/openldap/schema/openldap.schema
+include /etc/openldap/schema/ppolicy.schema
 
 #---------------------------------------------------------------------------
 # Load dynamic backend modules
 #---------------------------------------------------------------------------
 
-moduleload  back_mdb.la
-moduleload  back_sock.la
-moduleload  back_monitor.la
+moduleload back_mdb.la
+moduleload back_sock.la
+moduleload back_monitor.la
+moduleload back_ldap.la
+moduleload back_relay.la
 
 #---------------------------------------------------------------------------
 # Load dynamic overlay modules
 #---------------------------------------------------------------------------
 
+moduleload accesslog
+moduleload ppolicy
+moduleload rwm
 
 #---------------------------------------------------------------------------
 # slapd global parameters
 #---------------------------------------------------------------------------
 
-#loglevel conns filter stats
-threads 6
+#loglevel conns filter stats stats2 acl
+threads 2
 
 pidfile slapd-sock-test.pid
 argsfile slapd-sock-test.args
@@ -31,6 +42,8 @@
 
 modulepath /opt/openldap/lib64/openldap
 
+password-hash {CLEARTEXT}
+#password-hash {SSHA}
 
 #---------------------------------------------------------------------------
 # Rewrite SASL identity to DIT identity
@@ -39,22 +52,22 @@
 # Only for local tests!
 authz-regexp
   "gidnumber=100\\+uidnumber=1000,cn=peercred,cn=external,cn=auth"
-  "cn=root,ou=realdb,dc=example,dc=org"
+  "cn=root,ou=data,dc=example,dc=org"
 
 # Map root user to rootdn when SASL/EXTERNAL is used with LDAPI
 authz-regexp
   "gidnumber=0\\+uidnumber=0,cn=peercred,cn=external,cn=auth"
-  "cn=root,ou=realdb,dc=example,dc=org"
+  "cn=root,ou=data,dc=example,dc=org"
 
 # EXTERNAL over Unix Domain socket
 authz-regexp
   "gidnumber=([0-9]+)\\+uidnumber=([0-9]+),cn=peercred,cn=external,cn=auth"
-  
"ldap:///ou=realdb,dc=example,dc=org??sub?(&(objectClass=posixAccount)(uidNumber=$2)(gidNumber=$1))"
+  
"ldap:///ou=data,dc=example,dc=org??sub?(&(objectClass=posixAccount)(uidNumber=$2)(gidNumber=$1))"
 
 # All mechs based on userID most times with password
 authz-regexp
   "uid=([a-zA-Z0-9]+),cn=(digest-md5|cram-md5|ntlm|plain|login|gssapi),cn=auth"
-  "ldap:///ou=realdb,dc=example,dc=org??sub?(uid=$1)"
+  "ldap:///ou=data,dc=example,dc=org??sub?(uid=$1)"
 
 #---------------------------------------------------------------------------
 # Global access control
@@ -74,7 +87,36 @@
 
 access to
   dn.subtree="cn=config"
-    by dn.exact="cn=root,ou=realdb,dc=example,dc=org" read
+    by dn.exact="cn=root,ou=data,dc=example,dc=org" read
+
+#######################################################################
+# Audit database cn=accesslog
+#######################################################################
+
+database mdb
+
+suffix "cn=accesslog"
+directory accesslog
+
+# Always set rootdn since needed by internally writing overlays
+rootdn "cn=root,cn=accesslog"
+# rootpw not needed in production!
+#rootpw donotenable!!!
+
+sizelimit -1
+
+# Index-Konfiguration
+index reqStart eq
+index reqType eq
+index reqDN eq
+index reqAuthzID eq
+index reqResult eq
+index reqEntryUUID eq
+index objectClass eq
+
+access to
+  dn.subtree="cn=accesslog"
+    by * read
 
 #***************************************************************************
 # Backend databases defined in external files
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/slapdsock-0.5.2/examples/openldap/sockdb.conf 
new/slapdsock-0.5.3/examples/openldap/sockdb.conf
--- old/slapdsock-0.5.2/examples/openldap/sockdb.conf   2016-04-22 
22:37:55.000000000 +0200
+++ new/slapdsock-0.5.3/examples/openldap/sockdb.conf   2017-06-21 
19:53:01.000000000 +0200
@@ -12,11 +12,10 @@
 
 sizelimit -1
 
-socketpath sockdb-listener
+socketpath sock-listener
 extensions binddn peername ssf connid
 
 access to
   dn.subtree="ou=sock,dc=example,dc=org"
-    by dn.exact="cn=root,ou=realdb,dc=example,dc=org" write
+    by dn.exact="cn=root,ou=data,dc=example,dc=org" write
     by * read
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/slapdsock-0.5.2/examples/openldap/start-slapd.sh 
new/slapdsock-0.5.3/examples/openldap/start-slapd.sh
--- old/slapdsock-0.5.2/examples/openldap/start-slapd.sh        2016-04-22 
22:37:55.000000000 +0200
+++ new/slapdsock-0.5.3/examples/openldap/start-slapd.sh        2017-06-28 
13:27:17.000000000 +0200
@@ -1,7 +1,7 @@
 #!/bin/sh
 
-#OPENLDAP_EXEC="/opt/openldap/lib64/slapd"
-OPENLDAP_EXEC="/usr/sbin/slapd"
+OPENLDAP_EXEC="/opt/openldap-RE24/lib64/slapd"
+#OPENLDAP_EXEC="/usr/sbin/slapd"
 
 LOCALDIR="$(dirname $0)"
 PWD="$(pwd)"
@@ -12,10 +12,10 @@
 
 cd "${LOCALDIR}"
 
-#  -d config,stats,stats2,acl,args,trace,sync
+#  -d config,stats,stats2,acl,args,shell,trace,sync
 
 ${OPENLDAP_EXEC}   \
-  -d stats,shell \
+  -d stats,shell,acl \
   -h "ldap://0.0.0.0:9876 ${LDAPI_URI}" \
   -n slapd-sock-test \
   -f slapd.conf
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/slapdsock-0.5.2/examples/passmod.py 
new/slapdsock-0.5.3/examples/passmod.py
--- old/slapdsock-0.5.2/examples/passmod.py     1970-01-01 01:00:00.000000000 
+0100
+++ new/slapdsock-0.5.3/examples/passmod.py     2017-07-02 18:16:44.000000000 
+0200
@@ -0,0 +1,466 @@
+#!/usr/bin/python -OO
+# -*- coding: utf-8 -*-
+"""
+slapd-sock listener demon queried by OpenLDAP's slapd-sock
+
+this demon intercepts password changes in ADD and MODIFY operations
+and exports the userPassword value
+"""
+
+#-----------------------------------------------------------------------
+# Imports
+#-----------------------------------------------------------------------
+
+# from Python's standard lib
+import datetime
+import logging
+import os
+import sys
+
+# passlib
+import passlib.context
+
+# from jwcrypto
+#from jwcrypto.jwk import JWK
+#from jwcrypto.jwe import JWE
+
+# python-ldap
+import ldap
+from ldap import LDAPError
+from ldap.controls.simple import ProxyAuthzControl
+
+# local modules
+from slapdsock.ldaphelper import ldap_datetime
+from slapdsock.ldaphelper import MyLDAPUrl
+from slapdsock.loghelper import combined_logger
+from slapdsock.handler import SlapdSockHandler, SlapdSockHandlerError
+from slapdsock.message import RESULTResponse
+
+# run multi-threaded
+from slapdsock.service import SlapdSockThreadingServer
+
+#-----------------------------------------------------------------------
+# Configuration constants
+#-----------------------------------------------------------------------
+
+__version__ = '0.0.1'
+__author__ = u'Michael Ströder <[email protected]>'
+
+# DN of default pwdPolicy entry used
+# in case attribute pwdPolicySubentry is missing
+#PWD_POLICY_SUBENTRY_DEFAULT = 'cn=ppolicy-default,cn=ae,ou=ae-dir'
+PWD_POLICY_SUBENTRY_DEFAULT = None
+
+PWD_MIN_LENGTH = 0
+PWD_MIN_AGE = 0
+PWD_SCHEME = '{CRYPT}'
+PWD_CRYPT_SCHEME = 'sha512_crypt'
+PWD_CRYPT_SCHEME_ARGS = {
+    'rounds': 5000,
+}
+
+# UIDs and peer GIDS of peers which are granted access
+# (list of int/strings)
+ALLOWED_UIDS = [0, 'ldap', os.getuid()]
+ALLOWED_GIDS = [0]
+
+# String with octal representation of socket permissions
+SOCKET_PERMISSIONS = '0666'
+
+# Trace level for python-ldap logs
+PYLDAP_TRACELEVEL = int(os.environ.get('PYLDAP_TRACELEVEL', 0))
+
+# Number of times connecting to local LDAPI is retried before sending a
+# failed response for a query
+LDAP_MAXRETRYCOUNT = 10
+# Time to wait before retrying to connect within one query
+LDAP_RETRYDELAY = 0.1
+
+# SASL authz-ID to be sent along with SASL/EXTERNAL bind
+#LDAP_SASL_AUTHZID = 'dn:uid=simple_bind_proxy,dc=example,dc=com'
+LDAP_SASL_AUTHZID = None
+
+# Time in seconds for which normal LDAP searches will be valid in cache
+LDAP_CACHE_TTL = 5.0
+# Time in seconds for which pwdPolicy and oathHOTPParams entries will be
+# valid in cache
+LDAP_LONG_CACHE_TTL = 20 * LDAP_CACHE_TTL
+
+# Timeout in seconds when connecting to local and remote LDAP servers
+# used for ldap.OPT_NETWORK_TIMEOUT and ldap.OPT_TIMEOUT
+LDAP_TIMEOUT = 3.0
+
+# attribute containing username
+LDAP_USERNAME_ATTR = 'uid'
+
+# Timeout in seconds for the server (Unix domain) socket
+SOCKET_TIMEOUT = 2 * LDAP_TIMEOUT
+
+# Logging formats
+SYS_LOG_FORMAT = '%(levelname)s %(message)s'
+CONSOLE_LOG_FORMAT = '%(asctime)s %(levelname)s %(message)s'
+
+# Base number for floating average value of response delay
+AVERAGE_COUNT = 100
+
+# Default log level to use
+LOG_LEVEL = int(os.environ.get('LOG_LEVEL', logging.INFO))
+
+# Time (seconds) for assuming an userPassword+OTP value to be valid in cache
+CACHE_TTL = -1.0
+
+DEBUG_VARS = [
+    'pwd_changed_time',
+    'pwd_policy_subentry_dn',
+    'pwd_policy_subentry',
+    'user_class',
+    'user_entry',
+]
+
+# Error messages
+if __debug__:
+    DEBUG_VARS.extend([
+        'new_passwd',
+    ])
+
+#-----------------------------------------------------------------------
+# Classes and functions
+#-----------------------------------------------------------------------
+
+
+class PassModServer(SlapdSockThreadingServer):
+
+    """
+    This is used to pass in more parameters to the server instance
+    """
+    ldapi_authz_id = LDAP_SASL_AUTHZID
+    ldap_retry_max = LDAP_MAXRETRYCOUNT
+    ldap_retry_delay = LDAP_RETRYDELAY
+    ldap_cache_ttl = LDAP_CACHE_TTL
+
+    def __init__(
+            self,
+            server_address,
+            RequestHandlerClass,
+            logger,
+            average_count,
+            socket_timeout,
+            socket_permissions,
+            allowed_uids,
+            allowed_gids,
+            bind_and_activate=True,
+            log_vars=None,
+        ):
+        self._ldap_conn = None
+        SlapdSockThreadingServer.__init__(
+            self,
+            server_address,
+            RequestHandlerClass,
+            logger,
+            average_count,
+            socket_timeout,
+            socket_permissions,
+            allowed_uids,
+            allowed_gids,
+            bind_and_activate,
+            monitor_dn=None,
+            log_vars=log_vars,
+        )
+
+
+class PassModHandler(SlapdSockHandler):
+
+    """
+    Handler class which proxies some simple bind requests to remote server
+    """
+
+    def _read_user_entry(self, request):
+        # Try to read the user entry for the given request dn
+        try:
+            try:
+                local_ldap_conn = self.server.get_ldapi_conn()
+                ldap_result = local_ldap_conn.search_s(
+                    request.dn.encode('utf-8'),
+                    ldap.SCOPE_BASE,
+                    '(objectClass=*)',
+                    attrlist=[
+                        'objectClass',
+                        'structuralObjectClass',
+                        'pwdChangedTime',
+                        'pwdPolicySubentry',
+                        'uid',
+                        'uidNumber',
+                    ],
+                )
+            except ldap.SERVER_DOWN, ldap_error:
+                self.server.disable_ldapi_conn()
+                raise ldap_error
+        except LDAPError, ldap_error:
+            raise SlapdSockHandlerError(
+                ldap_error,
+                log_level=logging.WARN,
+                response=RESULTResponse(request.msgid, ldap_error),
+                log_vars=self.server._log_vars,
+            )
+        return ldap_result[0][1] # _read_user_entry()
+
+    def _get_new_passwd(self, request):
+        """
+        Try to extract userPassword from request
+        """
+        for mod_op, mod_type, mod_vals in request.modops:
+            if mod_op in (ldap.MOD_REPLACE, ldap.MOD_ADD) and \
+               (mod_type.lower() == 'userpassword' or mod_type == '2.5.4.35'):
+                if len(set(mod_vals)) != 1:
+                    raise SlapdSockHandlerError(
+                        '%d != 1 different userPassword values in %s for %r' % 
(
+                            len(set(mod_vals)),
+                            request.__class__.__name__,
+                            request.dn,
+                        ),
+                        log_level=logging.ERROR,
+                        response='CONTINUE\n',
+                        log_vars=self.server._log_vars,
+                    )
+                new_passwd = mod_vals[0]
+                if new_passwd.startswith(PWD_SCHEME):
+                    raise SlapdSockHandlerError(
+                        'userPassword value already begins with %r' % 
PWD_SCHEME,
+                        log_level=logging.DEBUG,
+                        response='CONTINUE\n',
+                        log_vars=self.server._log_vars,
+                    )
+                pw_context = 
passlib.context.CryptContext(schemes=[PWD_CRYPT_SCHEME])
+                # save hashed password into request
+                mod_vals[0] = '{0}{1}'.format(
+                    PWD_SCHEME,
+                    pw_context.hash(new_passwd, **PWD_CRYPT_SCHEME_ARGS),
+                )
+                return new_passwd
+        # nothing to do because there's no userPassword attribute in request
+        raise SlapdSockHandlerError(
+            'No userPassword value in %s for %r' % (
+                request.__class__.__name__,
+                request.dn,
+            ),
+            log_level=logging.DEBUG,
+            response='CONTINUE\n',
+            log_vars=self.server._log_vars,
+        )
+        # end of _get_new_passwd()
+
+    def _check_pwd_policy(self, request, new_passwd_len, 
pwd_policy_subentry_dn, pwd_changed_time):
+        if pwd_policy_subentry_dn is None:
+            self._log(logging.DEBUG, 'no password policy to check')
+            return
+        # Try to determine password policy
+        pwd_min_age = PWD_MIN_AGE
+        pwd_min_length = PWD_MIN_LENGTH
+        try:
+            try:
+                local_ldap_conn = self.server.get_ldapi_conn()
+                pwd_policy_subentry = local_ldap_conn.read_s(
+                    pwd_policy_subentry_dn,
+                    '(objectClass=pwdPolicy)',
+                    attrlist=[
+                        'pwdMinAge',
+                        'pwdMinLength',
+                    ],
+                    cache_time=LDAP_LONG_CACHE_TTL,
+                )
+            except ldap.SERVER_DOWN, ldap_error:
+                self.server.disable_ldapi_conn()
+                raise ldap_error
+        except LDAPError, ldap_error:
+            raise SlapdSockHandlerError(
+                ldap_error,
+                log_level=logging.WARN,
+                response=RESULTResponse(request.msgid, ldap_error),
+                log_vars=self.server._log_vars,
+            )
+        else:
+            pwd_min_age = int(pwd_policy_subentry.get('pwdMinAge', 
[PWD_MIN_AGE])[0])
+            pwd_min_length = int(pwd_policy_subentry.get('pwdMinLength', 
[PWD_MIN_LENGTH])[0])
+        # Check if minimum password length is ok
+        if new_passwd_len < pwd_min_length:
+            raise SlapdSockHandlerError(
+                'Password for %r too short!' % (request.dn),
+                log_level=logging.INFO,
+                response=RESULTResponse(
+                    request.msgid,
+                    'constraintViolation',
+                    info='Password too short! Required minimum length is %d.' 
% (
+                        pwd_min_length
+                    ),
+                ),
+                log_vars=self.server._log_vars,
+            )
+        # Check if next password change is already allowed
+        if pwd_changed_time is not None and \
+           
(datetime.datetime.utcnow()-ldap_datetime(pwd_changed_time)).total_seconds < 
pwd_min_age:
+            raise SlapdSockHandlerError(
+                'Password of %r too young to change!' % (request.dn),
+                log_level=logging.INFO,
+                response=RESULTResponse(
+                    request.msgid,
+                    'constraintViolation',
+                    info='Password too young to change!',
+                ),
+                log_vars=self.server._log_vars,
+            )
+        return # end of _check_pwd_policy()
+
+    def _export_password(self, request, user_entry, password):
+        """
+        write reversible encrypted new password to sync queue
+        """
+        try:
+            # all export actions which could fail goes here
+            _ = user_entry
+            self._log(logging.ERROR, 'Exported password: %r', password)
+        except Exception, err:
+            raise SlapdSockHandlerError(
+                'Error exporting password of %r: %s' % (request.dn, err),
+                log_level=logging.ERROR,
+                response=RESULTResponse(
+                    request.msgid,
+                    'operationsError',
+                    info='export error',
+                ),
+                log_vars=self.server._log_vars,
+            )
+        else:
+            self._log(logging.INFO, 'Exported password of %r', request.dn)
+        return # end of _export_password()
+
+    def _update_user_entry(self, request):
+        """
+        write modifications of request to LDAP entry
+        """
+        try:
+            local_ldap_conn = self.server.get_ldapi_conn()
+            local_ldap_conn.modify_ext_s(
+                request.dn.encode('utf-8'),
+                request.modops,
+                serverctrls=[
+                    ProxyAuthzControl(
+                        True,
+                        'dn:{0}'.format(request.binddn.encode('utf-8')),
+                    ),
+                ],
+            )
+        except ldap.LDAPError, ldap_error:
+            raise SlapdSockHandlerError(
+                'LDAPError modifying entry %r: %s' % (request.dn, ldap_error),
+                log_level=logging.ERROR,
+                response=RESULTResponse(request.msgid, ldap_error),
+                log_vars=self.server._log_vars,
+            )
+        else:
+            self._log(
+                logging.INFO,
+                'Successfully modified userPassword for %r (from %r)',
+                request.dn,
+                request.peername,
+            )
+        return # end of _update_user_entry()
+
+    def do_modify(self, request):
+        """
+        Handle MODIFY operation
+        """
+        new_passwd = self._get_new_passwd(request)
+        user_entry = self._read_user_entry(request)
+        # Attributes from user entry
+        #user_class = user_entry.get('structuralObjectClass', [None])[0]
+        pwd_changed_time = user_entry.get('pwdChangedTime', [None])[0]
+        pwd_policy_subentry_dn = user_entry.get(
+            'pwdPolicySubentry',
+            [PWD_POLICY_SUBENTRY_DEFAULT]
+        )[0]
+        self._check_pwd_policy(
+            request,
+            len(new_passwd),
+            pwd_policy_subentry_dn,
+            pwd_changed_time
+        )
+        self._update_user_entry(request)
+        self._export_password(request, user_entry, new_passwd)
+        return RESULTResponse(request.msgid, 'success') # end of do_modify()
+
+
+#-----------------------------------------------------------------------
+# Main
+#-----------------------------------------------------------------------
+
+def run_this():
+    """
+    The main script
+    """
+
+    script_name = os.path.abspath(sys.argv[0])
+
+    log_level = LOG_LEVEL
+    console_log_format = None
+    if __debug__ and os.environ.get('DEBUG', 'no') == 'yes':
+        log_level = logging.DEBUG
+        console_log_format = CONSOLE_LOG_FORMAT
+
+    my_logger = combined_logger(
+        os.path.basename(script_name),
+        log_level,
+        sys_log_format=SYS_LOG_FORMAT,
+        console_log_format=console_log_format,
+    )
+
+    my_logger.info(
+        'Starting %s %s (log level %d)',
+        script_name,
+        __version__,
+        my_logger.level
+    )
+
+    if __debug__:
+        my_logger.error(
+            '!!! Running in debug mode (log level %d)! '
+            'Secret data will be logged! Don\'t do that!!!',
+            my_logger.level
+        )
+
+    try:
+        socket_path = sys.argv[1]
+        local_ldap_uri = sys.argv[2]
+    except IndexError:
+        my_logger.error('Not enough arguments => abort')
+        sys.exit(1)
+
+    local_ldap_uri_obj = MyLDAPUrl(local_ldap_uri)
+
+    try:
+        slapd_sock_listener = PassModServer(
+            socket_path,
+            PassModHandler,
+            my_logger,
+            AVERAGE_COUNT,
+            SOCKET_TIMEOUT, SOCKET_PERMISSIONS,
+            ALLOWED_UIDS, ALLOWED_GIDS,
+            log_vars=DEBUG_VARS,
+        )
+        slapd_sock_listener.ldapi_uri = local_ldap_uri_obj.initializeUrl()
+        slapd_sock_listener.ldap_trace_level = PYLDAP_TRACELEVEL
+        try:
+            slapd_sock_listener.serve_forever()
+        except KeyboardInterrupt:
+            my_logger.warn('Received interrupt signal => shutdown')
+    finally:
+        my_logger.debug('Remove socket path %s', repr(socket_path))
+        try:
+            os.remove(socket_path)
+        except OSError:
+            pass
+
+    return # end of main()
+
+
+if __name__ == '__main__':
+    run_this()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/slapdsock-0.5.2/slapdsock/message.py 
new/slapdsock-0.5.3/slapdsock/message.py
--- old/slapdsock-0.5.2/slapdsock/message.py    2017-03-20 11:23:32.000000000 
+0100
+++ new/slapdsock-0.5.3/slapdsock/message.py    2017-07-02 00:43:16.000000000 
+0200
@@ -39,6 +39,7 @@
 # from python-ldap
 import ldif
 from ldif import LDIFWriter
+from ldap import LDAPError
 
 from slapdsock.ldaphelper import RESULT_CODE
 
@@ -362,13 +363,17 @@
     """
     req_attrs = {
         'msgid': int,
+        'binddn': ldap_str,
+        'peername': ldap_str,
+        'ssf': int,
+        'connid': int,
         'code': int,
         'matched': ldap_str,
         'info': ldap_str,
     }
 
 
-class ENTRYRequest(SockRequest):
+class ENTRYRequest(ADDRequest):
 
     """
     ENTRY
@@ -378,6 +383,10 @@
     """
     req_attrs = {
         'msgid': int,
+        'binddn': ldap_str,
+        'peername': ldap_str,
+        'ssf': int,
+        'connid': int,
     }
 
 
@@ -468,15 +477,32 @@
     <blank line>
     """
 
-    def __init__(self, msgid, code=0, matched=None, info=None):
-        msgid = msgid or 0
-        if isinstance(code, basestring):
-            code = RESULT_CODE[code]
+    def __init__(self, msgid, code, matched=None, info=None):
         assert type(msgid) == IntType, ValueError(
-            'Argument msgid must be integer but was: %s' % repr(msgid)
+            'Argument msgid must be integer but was: %r' % msgid
         )
+        msgid = msgid or 0
+        if isinstance(code, int):
+            code = code
+        elif isinstance(code, basestring):
+            # result code specified by name
+            code = RESULT_CODE[code]
+        elif isinstance(code, LDAPError):
+            # clone response args from LDAPError instance
+            ldap_error = code
+            code = RESULT_CODE.get(type(ldap_error), RESULT_CODE['other'])
+            try:
+                info = ldap_error.args[0]['info'].decode('utf-8')
+            except (AttributeError, KeyError):
+                pass
+            try:
+                matched = ldap_error.args[0]['matched'].decode('utf-8')
+            except (AttributeError, KeyError):
+                pass
+        else:
+            raise TypeError('Invalid type of argument code=%r' % (code))
         assert type(code) == IntType, ValueError(
-            'Argument code must be integer but was: %s' % repr(code)
+            'Argument code must be integer but was: %r' % code
         )
         resp_lines = [
             #('msgid', str(msgid)),
@@ -534,7 +560,7 @@
 
 class InternalErrorResponse(RESULTResponse):
     """
-    Convenience wrapper class for returning unwillingToPerform and 
+    Convenience wrapper class for returning unwillingToPerform and
     diagnostic message 'internal error'
     """
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/slapdsock-0.5.2/slapdsock/pkginfo.py 
new/slapdsock-0.5.3/slapdsock/pkginfo.py
--- old/slapdsock-0.5.2/slapdsock/pkginfo.py    2017-03-20 11:37:15.000000000 
+0100
+++ new/slapdsock-0.5.3/slapdsock/pkginfo.py    2017-07-01 20:06:32.000000000 
+0200
@@ -2,6 +2,6 @@
 """
 meta attributes for packaging which does not import any dependencies
 """
-__version__ = '0.5.2'
+__version__ = '0.5.3'
 __author__ = u'Michael Ströder <[email protected]>'
 __license__ = 'Apache License, Version 2.0'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/slapdsock-0.5.2/slapdsock.egg-info/PKG-INFO 
new/slapdsock-0.5.3/slapdsock.egg-info/PKG-INFO
--- old/slapdsock-0.5.2/slapdsock.egg-info/PKG-INFO     2017-03-20 
11:45:10.000000000 +0100
+++ new/slapdsock-0.5.3/slapdsock.egg-info/PKG-INFO     2017-07-02 
18:18:43.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: slapdsock
-Version: 0.5.2
+Version: 0.5.3
 Summary: Module package for back-sock listeners for OpenLDAP
 Home-page: https://www.stroeder.com/slapdsock.html
 Author: Michael Stroeder
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/slapdsock-0.5.2/slapdsock.egg-info/SOURCES.txt 
new/slapdsock-0.5.3/slapdsock.egg-info/SOURCES.txt
--- old/slapdsock-0.5.2/slapdsock.egg-info/SOURCES.txt  2017-03-20 
11:45:10.000000000 +0100
+++ new/slapdsock-0.5.3/slapdsock.egg-info/SOURCES.txt  2017-07-02 
18:18:43.000000000 +0200
@@ -4,16 +4,17 @@
 setup.cfg
 setup.py
 examples/noop_logger.py
+examples/passmod.py
 examples/simple_bind_demo.py
 examples/openldap/realdb.conf
 examples/openldap/realdb.ldif
-examples/openldap/slapd-sock-test.args
-examples/openldap/slapd-sock-test.pid
 examples/openldap/slapd.conf
 examples/openldap/sockdb.conf
 examples/openldap/start-slapd.sh
+examples/openldap/accesslog/.placeholder
+examples/openldap/accesslog/data.mdb
+examples/openldap/accesslog/lock.mdb
 examples/openldap/realdb/.placeholder
-examples/openldap/schema/init.schema
 slapdsock/__init__.py
 slapdsock/cache.py
 slapdsock/handler.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/slapdsock-0.5.2/tests/t_message.py 
new/slapdsock-0.5.3/tests/t_message.py
--- old/slapdsock-0.5.2/tests/t_message.py      2017-03-20 11:25:37.000000000 
+0100
+++ new/slapdsock-0.5.3/tests/t_message.py      2017-06-21 21:26:13.000000000 
+0200
@@ -180,6 +180,14 @@
 
     def test_modify_userpassword(self):
         req = 
MODIFYRequest(self.prepare_request_msg(modify_message_userpassword))
+        self.assertEquals(req.reqtype, u'MODIFY')
+        self.assertEquals(req.msgid, 2)
+        self.assertEquals(req.binddn, u'cn=root,ou=realdb,dc=example,dc=org')
+        self.assertEquals(req.peername, 
u'PATH=/tmp/slapd_sockd/examples/openldap/ldapi')
+        self.assertEquals(req.ssf, 71)
+        self.assertEquals(req.connid, 1004)
+        self.assertEquals(req.dn, u'uid=test1,ou=realdb,dc=example,dc=org')
+        self.assertEquals(req.modops, [(2, 'userPassword', 
['{SSHA}5/WxVWC6CtRetVnVNP3Sv5s4F/kQRURR'])])
 
 
 if __name__ == '__main__':


Reply via email to