diff -Nur orig/contrib/slapd-modules/smbkrb5pwd/LICENSE new/contrib/slapd-modules/smbkrb5pwd/LICENSE
--- orig/contrib/slapd-modules/smbkrb5pwd/LICENSE	1970-01-01 02:00:00.000000000 +0200
+++ new/contrib/slapd-modules/smbkrb5pwd/LICENSE	2015-01-05 17:38:40.365210283 +0200
@@ -0,0 +1,47 @@
+The OpenLDAP Public License
+  Version 2.8, 17 August 2003
+
+Redistribution and use of this software and associated documentation
+("Software"), with or without modification, are permitted provided
+that the following conditions are met:
+
+1. Redistributions in source form must retain copyright statements
+   and notices,
+
+2. Redistributions in binary form must reproduce applicable copyright
+   statements and notices, this list of conditions, and the following
+   disclaimer in the documentation and/or other materials provided
+   with the distribution, and
+
+3. Redistributions must contain a verbatim copy of this document.
+
+The OpenLDAP Foundation may revise this license from time to time.
+Each revision is distinguished by a version number.  You may use
+this Software under terms of this license revision or under the
+terms of any subsequent revision of the license.
+
+THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS
+CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT
+SHALL THE OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S)
+OR OWNER(S) OF THE SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+The names of the authors and copyright holders must not be used in
+advertising or otherwise to promote the sale, use or other dealing
+in this Software without specific, written prior permission.  Title
+to copyright in this Software shall at all times remain with copyright
+holders.
+
+OpenLDAP is a registered trademark of the OpenLDAP Foundation.
+
+Copyright 1999-2003 The OpenLDAP Foundation, Redwood City,
+California, USA.  All Rights Reserved.  Permission to copy and
+distribute verbatim copies of this document is granted.
diff -Nur orig/contrib/slapd-modules/smbkrb5pwd/Makefile new/contrib/slapd-modules/smbkrb5pwd/Makefile
--- orig/contrib/slapd-modules/smbkrb5pwd/Makefile	1970-01-01 02:00:00.000000000 +0200
+++ new/contrib/slapd-modules/smbkrb5pwd/Makefile	2015-01-05 17:38:40.365210283 +0200
@@ -0,0 +1,70 @@
+# $OpenLDAP: pkg/ldap/contrib/slapd-modules/smbk5pwd/Makefile,v 1.1.6.4 2009/10/02 21:16:53 quanah Exp $
+# This work is part of OpenLDAP Software <http://www.openldap.org/>.
+#
+# Copyright 1998-2009 The OpenLDAP Foundation.
+# Copyright 2004 Howard Chu, Symas Corp. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted only as authorized by the OpenLDAP
+# Public License.
+#
+# A copy of this license is available in the file LICENSE in the
+# top-level directory of the distribution or, alternatively, at
+# <http://www.OpenLDAP.org/license.html>.
+
+LDAP_SRC=../../..
+LDAP_BUILD=$(LDAP_SRC)
+LDAP_INC=-I$(LDAP_BUILD)/include -I$(LDAP_SRC)/include -I$(LDAP_SRC)/servers/slapd
+
+SSL_INC=
+SSL_LIB=-lcrypto
+
+LIBTOOL=$(LDAP_BUILD)/libtool
+CC=gcc
+OPT=-g -O2
+CLNT_OPT=-DSMBKRB5PWD_KADM5_CLNT
+SRV_OPT=-DSMBKRB5PWD_KADM5_SRV
+
+MIT_KRB5_INC=-I/usr/include/mit-krb5
+MIT_KRB5_LIB=-L/usr/lib/$(shell gcc -print-multiarch)/mit-krb5 -lkrb5
+
+DEFS=
+INCS=$(LDAP_INC) $(MIT_KRB5_INC) $(SSL_INC)
+LIBS=$(MIT_KRB5_LIB) $(SSL_LIB)
+
+MIT_KRB5_SRV_LIB=-lkadm5srv_mit
+MIT_KRB5_CLNT_LIB=-lkadm5clnt_mit
+
+prefix=/usr/local
+ldap_subdir=/openldap
+
+libdir=$(prefix)/lib
+libexecdir=$(prefix)/libexec
+moduledir=$(libexecdir)$(ldap_subdir)
+
+.PHONY: all
+all:	smbkrb5pwd.la smbkrb5pwd_srv.la
+
+smbkrb5pwd.lo:	smbkrb5pwd.c
+	$(LIBTOOL) --mode=compile $(CC) $(CLNT_OPT) $(OPT) $(DEFS) $(INCS) -c $?
+
+smbkrb5pwd.la:	smbkrb5pwd.lo
+	$(LIBTOOL) --mode=link $(CC) $(MIT_KRB5_CLNT_LIB) $(OPT) -version-info 0:1:0 \
+	-rpath $(moduledir) -module -o $@ $? $(LIBS) $(MIT_KRB5_CLNT_LIB)
+
+smbkrb5pwd_srv.lo:	smbkrb5pwd.c
+	$(LIBTOOL) --mode=compile $(CC) $(SRV_OPT) $(OPT) $(DEFS) $(INCS) -c smbkrb5pwd.c -o smbkrb5pwd_srv.o
+
+smbkrb5pwd_srv.la:	smbkrb5pwd_srv.lo
+	$(LIBTOOL) --mode=link $(CC)  $(MIT_KRB5_SRV_LIB) $(OPT) -version-info 0:0:0 \
+	-rpath $(moduledir) -module -o $@ $? $(LIBS) $(MIT_KRB5_SRV_LIB)
+
+.PHONY: clean
+clean:
+	rm -f smbkrb5pwd.lo smbkrb5pwd.la smbkrb5pwd_srv.lo smbkrb5pwd_srv.la
+
+.PHONY: install
+install: smbkrb5pwd.la
+	mkdir -p $(DESTDIR)$(moduledir)
+	$(LIBTOOL) --mode=install cp smbkrb5pwd.la $(DESTDIR)$(moduledir)
+	$(LIBTOOL) --mode=install cp smbkrb5pwd_srv.la $(DESTDIR)$(moduledir)
diff -Nur orig/contrib/slapd-modules/smbkrb5pwd/README new/contrib/slapd-modules/smbkrb5pwd/README
--- orig/contrib/slapd-modules/smbkrb5pwd/README	1970-01-01 02:00:00.000000000 +0200
+++ new/contrib/slapd-modules/smbkrb5pwd/README	2015-01-05 17:38:40.365210283 +0200
@@ -0,0 +1,171 @@
+Documentation is available at: https://github.com/opinsys/smbkrb5pwd/wiki
+
+
+OVERVIEW
+
+smbkrb5pwd is an OpenLDAP (slapd) overlay to change LDAP, Samba and MIT 
+Kerberos passwords at the same time. It intercepts the LDAP 
+PasswordModify Extended Operations and changes all the passwords. It is 
+based on the smbk5pwd overlay that provides similar functionality for 
+Heimdal kerberos.
+
+The makefile creates two different versions of the overlay - smbkrb5pwd 
+and smbkrb5pwd_srv. smbkrb5pwd is linked against libkadm5clnt_mit and it 
+contacts kadmind to modify the kerberos principal. This was previously 
+the only operation mode available. When using kadmind to modify the 
+principals, smbkrb5pwd needs a kerberos principal to manage the user 
+principals. MIT Kerberos can use LDAP backend to store its data, but it 
+should not be necessary.
+
+smbkrb5pwd_srv uses libkadm5srv_mit to modify the kerberos principal and 
+it requires that the slapd is able to read all kerberos configuration 
+files including the kerberos stash files and ldap secrets. All file 
+operations are done within the slapd process so there may be security 
+considerations.
+
+When LDAP password is changed, the overlay checks whether a principal 
+uid@REALM exists and creates it if it does not. If the principal exists, 
+only the password is changed.
+
+
+KNOWN LIMITATIONS
+
+* Because of locking issues, kerberos data cannot be stored in same 
+  objects as users
+* Principals are always named uid@REALM and cannot be changed
+* If uid in LDAP is changed, the old kerberos principal is not deleted 
+  automatically
+* If LDAP user is deleted, the kerberos principal is not deleted 
+  automatically
+
+
+INSTALLATION
+
+To compile the overlay the easiest way is to get the full source code 
+for OpenLDAP and place the smbkrb5pwd directory under 
+contrib/slapd-modules directory. After compiling OpenLDAP normally the 
+overlay can be compiled simply by running make in the smbkrb5pwd 
+directory.
+
+
+cd contrib/slapd-modules/smbkrb5pwd
+make
+sudo cp .libs/* /usr/lib/ldap/
+
+
+SLAPD CONFIGURATION
+
+To configure the overlay, the module needs to be loaded and configured 
+for the database.
+
+Depending on the version to be loaded, the module name needs to be 
+changed. The older version that contacts kadmind:
+
+dn: cn=module{0},cn=config
+objectClass: olcModuleList
+cn: module
+olcModulepath: /usr/lib/ldap
+olcModuleload: {0}back_hdb
+olcModuleload: {1}smbkrb5pwd
+
+The new mode that does not use kadmind:
+
+dn: cn=module{0},cn=config
+objectClass: olcModuleList
+cn: module
+olcModulepath: /usr/lib/ldap
+olcModuleload: {0}back_hdb
+olcModuleload: {1}smbkrb5pwd_srv
+
+Overlay configuration is the same for both:
+
+dn: olcOverlay={0}smbkrb5pwd,olcDatabase={1}hdb,cn=config
+objectClass: olcOverlayConfig
+objectClass: olcSmbKrb5PwdConfig
+olcOverlay: {0}smbkrb5pwd
+olcSmbKrb5PwdEnable: samba
+olcSmbKrb5PwdEnable: krb5
+olcSmbKrb5PwdMustChange: 2592012
+olcSmbKrb5PwdKrb5Realm: EDU.EXAMPLE.ORG
+olcSmbKrb5PwdRequiredClass: posixAccount
+
+
+The overlay accepts the following configuration attributes:
+
+* olcSmbKrb5PwdEnable - samba / krb5
+  - Enable samba/kerberos functionality of the module, same as 
+    olcSmbK5PwdEnable in smbk5pwd. If attribute is not set or both are set, 
+    both passwords are changed.
+* olcSmbKrb5PwdMustChange - e.g. 31536000 (year), 2592000 (30 seconds)
+  - Time in seconds before the password expires (currently affects only Samba)
+* olcSmbKrb5PwdKrb5Realm - e.g. EDU.EXAMPLE.ORG
+  - Kerberos realm used to create user principals
+* olcSmbKrb5PwdRequiredClass - e.g. posixAccount
+  - If set, the entry needs to have this object class for the kerberos 
+    principal and samba passwords to be modified
+
+
+KERBEROS PRINCIPAL
+
+smbkrb5pwd connects to kadmind using a principal found in keytab file 
+/etc/ldap/slapd.d/openldap-krb5.keytab. The keytab is searched for 
+principal that has name smbkrb5pwd/FQDN@REALM. Note that “hostname -f” 
+should return fqdn. One way to achieve this is to put fqdn as the first 
+name in /etc/hosts for the server’s ip address (here 10.11.12.13):
+
+
+10.11.12.13   server.edu.example.org server
+
+
+Creating the principal and exporting it to a keytab file can be done 
+with the following commands:
+
+
+kadmin.local -q "addprinc -randkey smbkrb5pwd/server.edu.example.org@EDU.EXAMPLE.ORG"
+kadmin.local -q "ktadd -e des-cbc-crc:normal -k /etc/ldap/slapd.d/openldap-krb5.keytab \
+ smbkrb5pwd/server.edu.example.org@EDU.EXAMPLE.ORG"
+
+chown openldap.openldap /etc/ldap/slapd.d/openldap-krb5.keytab
+
+
+SMBKRB5PWD_SRV FILE PERMISSIONS
+
+smbkrb5pwd_srv needs read access to all kerberos configuration files (no 
+write access is needed). On Debian/Ubuntu these files are:
+
+/etc/krb5.conf
+/etc/krb5.secrets
+/etc/krb5kdc/*
+
+
+TESTING
+
+The overlay activates itself when an password change exop request is 
+made. This can be done for example with ldappasswd command:
+
+ldappasswd -x -D uid=admin,ou=people,dc=edu,dc=example,dc=org -W \
+ uid=user1,ou=people,dc=edu,dc=example,dc=org
+
+smbkrb5pwd writes debug information to slapd’s logfile which is normally 
+/var/log/syslog in Ubuntu.
+
+
+LICENSE
+
+smbkrb5pwd is based on smbk5pwd overlay that can be found under 
+http://www.openldap.org/devel/cvsweb.cgi/contrib/slapd-modules/smbk5pwd
+in OpenLDAP's sources. smbkrb5pwd is licensed under The OpenLDAP Public 
+License that is also used for smbk5pwd.
+
+
+Copyright 2004-2010 The OpenLDAP Foundation.
+Portions Copyright 2004-2005 Howard Chu, Symas Corp. All rights reserved.
+Portions Copyright 2010-2013 Opinsys Oy.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted only as authorized by the OpenLDAP
+Public License.
+
+A copy of this license is available in the file LICENSE in the
+top-level directory of the distribution or, alternatively, at
+<http://www.OpenLDAP.org/license.html>.
diff -Nur orig/contrib/slapd-modules/smbkrb5pwd/smbkrb5pwd.c new/contrib/slapd-modules/smbkrb5pwd/smbkrb5pwd.c
--- orig/contrib/slapd-modules/smbkrb5pwd/smbkrb5pwd.c	1970-01-01 02:00:00.000000000 +0200
+++ new/contrib/slapd-modules/smbkrb5pwd/smbkrb5pwd.c	2015-01-05 18:08:35.609184556 +0200
@@ -0,0 +1,962 @@
+/* smbkrb5pwd.c - Overlay for managing Samba and MIT Kerberos passwords */
+/* $OpenLDAP: pkg/ldap/contrib/slapd-modules/smbk5pwd/smbk5pwd.c,v 1.17.2.16 2009/08/17 21:49:00 quanah Exp $ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2004-2009 The OpenLDAP Foundation.
+ * Portions Copyright 2004-2005 by Howard Chu, Symas Corp.
+ * Other portions Copyright 2010 Opinsys.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* ACKNOWLEDGEMENTS:
+ * Support for table-driven configuration added by Pierangelo Masarati.
+ * Support for sambaPwdMustChange and sambaPwdCanChange added by Marco D'Ettorre.
+ *
+ * Modified to support MIT Kerberos by Opinsys.
+ * Renamed the module from smbk5pwd to smbkrb5pwd.
+ */
+
+#include <portable.h>
+
+#include <netdb.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#ifndef SLAPD_OVER_SMBKRB5PWD
+#define SLAPD_OVER_SMBKRB5PWD SLAPD_MOD_DYNAMIC
+#endif
+
+#ifdef SLAPD_OVER_SMBKRB5PWD
+
+#include <slap.h>
+
+#include "slap-config.h"
+
+#include <krb5/krb5.h>
+#include <kadm5/admin.h>
+
+#define KRB5_KEYTAB "/etc/ldap/slapd.d/openldap-krb5.keytab"
+
+static AttributeDescription *ad_objectclass;
+static AttributeDescription *ad_uid;
+
+#ifdef HAVE_GNUTLS
+#include <gcrypt.h>
+typedef unsigned char DES_cblock[8];
+#else
+#include <openssl/des.h>
+#include <openssl/md4.h>
+#endif
+#include "ldap_utf8.h"
+
+static AttributeDescription *ad_sambaNTPassword;
+static AttributeDescription *ad_sambaPwdLastSet;
+static AttributeDescription *ad_sambaPwdMustChange;
+static AttributeDescription *ad_sambaPwdCanChange;
+static ObjectClass *oc_sambaSamAccount;
+
+/* Per-instance configuration information */
+typedef struct smbkrb5pwd_t {
+	unsigned	mode;
+#define	SMBKRB5PWD_F_KRB5	(0x1U)
+#define	SMBKRB5PWD_F_SAMBA	(0x2U)
+
+#define SMBKRB5PWD_DO_KRB5(pi)	((pi)->mode & SMBKRB5PWD_F_KRB5)
+#define SMBKRB5PWD_DO_SAMBA(pi)	((pi)->mode & SMBKRB5PWD_F_SAMBA)
+
+	/* How many seconds before forcing a password change? */
+	time_t	smb_must_change;
+	/* How many seconds after allowing a password change? */
+	time_t  smb_can_change;
+	char    *kerberos_realm;
+	char    *admin_princstr;
+	ldap_pvt_thread_mutex_t krb5_mutex;
+	ObjectClass *oc_requiredObjectclass;
+} smbkrb5pwd_t;
+
+static const unsigned SMBKRB5PWD_F_ALL	=
+	0
+	| SMBKRB5PWD_F_KRB5
+	| SMBKRB5PWD_F_SAMBA
+;
+
+static int smbkrb5pwd_modules_init( smbkrb5pwd_t *pi );
+
+static const char hex[] = "0123456789abcdef";
+
+#define MAX_PWLEN 256
+#define	HASHLEN	16
+
+static void hexify(
+	const char in[HASHLEN],
+	struct berval *out)
+{
+	int i;
+	char *a;
+	unsigned char *b;
+
+	out->bv_val = ch_malloc(HASHLEN*2 + 1);
+	out->bv_len = HASHLEN*2;
+
+	a = out->bv_val;
+	b = (unsigned char *)in;
+	for (i=0; i<HASHLEN; i++) {
+		*a++ = hex[*b >> 4];
+		*a++ = hex[*b++ & 0x0f];
+	}
+	*a++ = '\0';
+}
+
+static void nthash(
+	struct berval *passwd,
+	struct berval *hash)
+{
+	/* Windows currently only allows 14 character passwords, but
+	 * may support up to 256 in the future. We assume this means
+	 * 256 UCS2 characters, not 256 bytes...
+	 */
+	char hbuf[HASHLEN];
+#ifdef HAVE_OPENSSL
+	MD4_CTX ctx;
+#endif
+
+	if (passwd->bv_len > MAX_PWLEN*2)
+		passwd->bv_len = MAX_PWLEN*2;
+
+#ifdef HAVE_OPENSSL
+	MD4_Init( &ctx );
+	MD4_Update( &ctx, passwd->bv_val, passwd->bv_len );
+	MD4_Final( (unsigned char *)hbuf, &ctx );
+#elif defined(HAVE_GNUTLS)
+	gcry_md_hash_buffer(GCRY_MD_MD4, hbuf, passwd->bv_val, passwd->bv_len );
+#endif
+
+	hexify( hbuf, hash );
+}
+
+static int
+lookup_admin_princstr(
+	char *kerberos_realm,
+	char **admin_princstr)
+{
+	char fqdn[NI_MAXHOST] = "";
+	char hostname[HOST_NAME_MAX+1];
+	struct addrinfo *host_addr = NULL;
+	int rc;
+
+	rc = -1;
+
+#ifdef SMBKRB5PWD_KADM5_CLNT
+	if (gethostname(hostname, HOST_NAME_MAX+1)     ||
+	    getaddrinfo(hostname, NULL, NULL, &host_addr)) {
+		Log0(LDAP_DEBUG_ANY, LDAP_LEVEL_NOTICE,
+		     "smbkrb5pwd : an error occurred in gethostname()"
+		     " or getaddrinfo(), check your dns settings\n");
+		goto error;
+	}
+
+	if (getnameinfo(host_addr->ai_addr, host_addr->ai_addrlen, fqdn,
+			NI_MAXHOST, NULL, 0, 0)) {
+		Log0(LDAP_DEBUG_ANY, LDAP_LEVEL_NOTICE,
+		     "smbkrb5pwd : an error occurred in getnameinfo(),"
+		     " check your dns settings\n");
+		goto error_with_host_addr;
+	}
+
+	size_t princstr_size = sizeof("smbkrb5pwd/")
+			       + strlen(fqdn)
+			       + sizeof("@")
+			       + strlen(kerberos_realm) + 1;
+#endif
+
+#ifdef SMBKRB5PWD_KADM5_SRV
+	size_t princstr_size = strlen("root/admin@") + strlen(kerberos_realm) + 1;
+#endif
+
+	if (*admin_princstr)
+		free(*admin_princstr);
+
+	if ((*admin_princstr = calloc(princstr_size, 1)) == NULL)
+		goto error_with_host_addr;
+
+#ifdef SMBKRB5PWD_KADM5_CLNT
+	snprintf(*admin_princstr, princstr_size, "smbkrb5pwd/%s@%s", fqdn,
+		 kerberos_realm);
+#endif
+#ifdef SMBKRB5PWD_KADM5_SRV
+	snprintf(*admin_princstr, princstr_size, "root/admin@%s", kerberos_realm);
+#endif
+
+	rc = 0;
+
+error_with_host_addr:
+	if (host_addr)
+		freeaddrinfo(host_addr);
+error:
+	return rc;
+}
+
+static int krb5_set_passwd(
+	Operation *op,
+	req_pwdexop_s *qpw,
+	Entry *e,
+	smbkrb5pwd_t *pi)
+{
+	void *kadm5_handle;
+	kadm5_config_params params;
+	kadm5_principal_ent_rec princ;
+	kadm5_ret_t retval;
+	krb5_context context;
+	Attribute *a_objectclass, *a_uid;
+	char *user_uid = NULL, *user_password = NULL, *user_princstr = NULL;
+	int rc;
+	size_t user_princstr_size;
+	pid_t worker_pid = 0;
+	pid_t timeout_pid = 0;
+	int status = 0;
+
+	if (!access_allowed(op, e, slap_schema.si_ad_userPassword, NULL,
+			    ACL_WRITE, NULL))
+		return LDAP_INSUFFICIENT_ACCESS;
+
+	rc = LDAP_LOCAL_ERROR;
+
+	/* The krb5 kadm5 libraries seem to use global variables that hold the 
+           master key for the realm and some other realm specific data. Mutexes
+	   did not seem to get rid of all the problems related to this and 
+	   some lockups still happened, so fork the process instead before 
+	   doing any krb5 operations. The process is forked and the child sets 
+	   an alarm that kills the forked process if the password change is not 
+	   finished in 15 seconds.
+	*/
+
+	worker_pid = fork();
+
+	if (worker_pid == -1) {
+		switch (errno) {
+			case EAGAIN:
+				Log(LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
+				      "smbkrb5pwd %s : failed to fork process for password change (EAGAIN)!\n",
+				      op->o_log_prefix);
+
+				return LDAP_LOCAL_ERROR;
+			case ENOMEM:
+				Log(LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
+				      "smbkrb5pwd %s : failed to fork process for password change (ENOMEM - No memory)!\n",
+				      op->o_log_prefix);
+
+				return LDAP_LOCAL_ERROR;
+			case ENOSYS:
+				Log(LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
+				      "smbkrb5pwd %s : failed to fork process for password change (ENOSYS - Not supported)!\n",
+				      op->o_log_prefix);
+
+				return LDAP_LOCAL_ERROR;
+			default:
+				Log(LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
+				      "smbkrb5pwd %s : failed to fork process for password change!\n",
+				      op->o_log_prefix);
+
+				return LDAP_LOCAL_ERROR;
+		}
+	}
+
+	if (worker_pid) {
+		waitpid(worker_pid, &status, 0);
+
+		if (status == SIGALRM) {
+			Log(LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
+			      "smbkrb5pwd %s : forked password change process did not complete in 15s\n",
+			      op->o_log_prefix);
+
+			return LDAP_LOCAL_ERROR;
+		}
+
+		return status;
+	}
+
+	signal(SIGALRM, SIG_DFL);
+	alarm(15);
+
+	kadm5_handle = NULL;
+	memset(&princ, 0, sizeof(princ));
+	memset(&params, 0, sizeof(params));
+	princ.principal = NULL;
+
+	/* Find the uid of the user - this is used to generate the kerberos
+	 * principal for the user */
+
+	/* XXX add user information to all error messages */
+
+	a_uid = attr_find(e->e_attrs, ad_uid);
+	if (!a_uid) {
+		Log(LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
+		      "smbkrb5pwd %s : could not find uid in entry: %s\n",
+		      op->o_log_prefix,
+		      ldap_err2string(LDAP_NO_SUCH_ATTRIBUTE));
+		rc = LDAP_NO_SUCH_ATTRIBUTE;
+		goto finish;
+	}
+
+	user_uid = calloc(a_uid->a_vals[0].bv_len + 1, 1);
+        user_password = calloc(qpw->rs_new.bv_len + 1, 1);
+
+        memcpy(user_uid, a_uid->a_vals[0].bv_val, a_uid->a_vals[0].bv_len);
+        memcpy(user_password, qpw->rs_new.bv_val, qpw->rs_new.bv_len);
+
+	retval = kadm5_init_krb5_context(&context);
+	if (retval) {
+		Log(LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
+		     "smbkrb5pwd %s : kadm5_init_krb5_context() failed"
+		     " for user %s: %s\n",
+		     op->o_log_prefix, user_uid, error_message(retval));
+		rc = LDAP_CONNECT_ERROR;
+		goto finish;
+	}
+
+	params.mask |= KADM5_CONFIG_REALM;
+	params.realm = pi->kerberos_realm;
+
+#ifdef SMBKRB5PWD_KADM5_SRV
+	retval = kadm5_init_with_password(context, pi->admin_princstr, NULL,
+					  NULL, &params,
+					  KADM5_STRUCT_VERSION,
+					  KADM5_API_VERSION_3, NULL,
+					  &kadm5_handle);
+#endif
+
+#ifdef SMBKRB5PWD_KADM5_CLNT
+        retval = kadm5_init_with_skey(context, pi->admin_princstr, KRB5_KEYTAB,
+                                 KADM5_ADMIN_SERVICE, &params,
+                                 KADM5_STRUCT_VERSION,
+                                 KADM5_API_VERSION_3, NULL,
+                                 &kadm5_handle);
+#endif
+
+	if (retval) {
+		Log(LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
+		      "smbkrb5pwd %s : kadm5_init_with_password() failed"
+		      " for user %s (%s): %s\n",
+  		      op->o_log_prefix, user_uid, pi->admin_princstr, error_message(retval));
+		rc = LDAP_CONNECT_ERROR;
+		goto mitkrb_error_with_context;
+	}
+
+	user_princstr_size = strlen(user_uid)
+			     + sizeof("@")
+			     + strlen(pi->kerberos_realm)
+	                     + 1;
+	if ((user_princstr = calloc(user_princstr_size, 1)) == NULL) {
+		rc = LDAP_CONNECT_ERROR;
+		goto mitkrb_error_with_kadm5_handle;
+	}
+	snprintf(user_princstr, user_princstr_size, "%s@%s", user_uid,
+		 pi->kerberos_realm);
+
+	retval = krb5_parse_name(context, user_princstr, &princ.principal);
+	if (retval) {
+		Log(LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
+		     "smbkrb5pwd %s : krb5_parse_name() failed"
+		     " for user %s: %s\n",
+		     op->o_log_prefix, user_princstr, error_message(retval));
+		rc = LDAP_CONNECT_ERROR;
+		goto mitkrb_error_with_user_princstr;
+	}
+
+	long create_mask = KADM5_PRINCIPAL|KADM5_MAX_LIFE|KADM5_ATTRIBUTES;
+	princ.attributes |= KRB5_KDB_REQUIRES_PRE_AUTH;
+	retval = kadm5_create_principal(kadm5_handle, &princ, create_mask,
+					user_password);
+	if (retval == KADM5_OK) {
+		Log(LDAP_DEBUG_ANY, LDAP_LEVEL_NOTICE,
+		     "smbkrb5pwd %s : created principal for user %s\n",
+		     op->o_log_prefix, user_princstr);
+		rc = LDAP_SUCCESS;
+	} else if (retval == KADM5_DUP) {
+		/* principal exists, only change password */
+		retval = kadm5_chpass_principal(kadm5_handle, princ.principal,
+						user_password);
+		if (retval) {
+			Log(LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
+			     "smbkrb5pwd %s : kadm5_chpass_principal() failed "
+			     "for user %s: %s\n",
+			     op->o_log_prefix, user_princstr,
+			     error_message(retval));
+			rc = LDAP_CONNECT_ERROR;
+			goto mitkrb_error_with_princ;
+		} else {
+			Log(LDAP_DEBUG_ANY, LDAP_LEVEL_NOTICE,
+			     "smbkrb5pwd %s : changed password for user %s\n",
+			     op->o_log_prefix, user_princstr);
+			rc = LDAP_SUCCESS;
+		}
+	} else {
+		Log(LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
+		     "smbkrb5pwd %s : Problem creating principal for user %s: "
+		     "%s\n", op->o_log_prefix, user_princstr,
+		     error_message(retval));
+		rc = LDAP_CONNECT_ERROR;
+		goto mitkrb_error_with_princ;
+	}
+
+mitkrb_error_with_princ:
+	krb5_free_principal(context, princ.principal);
+mitkrb_error_with_kadm5_handle:
+	kadm5_destroy(kadm5_handle);
+mitkrb_error_with_user_princstr:
+	free(user_princstr);
+mitkrb_error_with_context:
+	krb5_free_context(context);
+finish:
+	if (user_uid)
+	  free(user_uid);
+
+	if (user_password)
+	  free(user_password);
+
+	_exit(rc);
+}
+
+static int smbkrb5pwd_exop_passwd(
+	Operation *op,
+	SlapReply *rs)
+{
+	int rc, rc_krb5;
+	req_pwdexop_s *qpw = &op->oq_pwdexop;
+	Entry *e;
+	Modifications *ml;
+	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+	smbkrb5pwd_t *pi = on->on_bi.bi_private;
+	char term;
+
+	/* Not the operation we expected, pass it on... */
+	if ( ber_bvcmp( &slap_EXOP_MODIFY_PASSWD, &op->ore_reqoid ) ) {
+		return SLAP_CB_CONTINUE;
+	}
+
+	op->o_bd->bd_info = (BackendInfo *)on->on_info;
+	rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &e );
+	if ( rc != LDAP_SUCCESS ) return rc;
+
+	term = qpw->rs_new.bv_val[qpw->rs_new.bv_len];
+	qpw->rs_new.bv_val[qpw->rs_new.bv_len] = '\0';
+
+	rc = SLAP_CB_CONTINUE;
+	if (pi->oc_requiredObjectclass &&
+	    !is_entry_objectclass(e, pi->oc_requiredObjectclass, 0)) {
+		Log(LDAP_DEBUG_ANY, LDAP_LEVEL_NOTICE,
+	     	     "smbkrb5pwd %s : an entry is not of required"
+		     " objectClass\n",
+	     	     op->o_log_prefix);
+		rc = LDAP_PARAM_ERROR;
+		goto finish;
+	}
+
+	if (SMBKRB5PWD_DO_KRB5(pi)) {
+		/* if this fails, do not bother with samba,
+		   because passwords should be kept in sync */
+		rc_krb5 = krb5_set_passwd(op, qpw, e, pi);
+		if (rc_krb5 != LDAP_SUCCESS) {
+			rc = rc_krb5;
+			goto finish;
+		}
+	}
+
+	/* Samba stuff */
+	if ( SMBKRB5PWD_DO_SAMBA( pi ) && is_entry_objectclass(e, oc_sambaSamAccount, 0 ) ) {
+		struct berval *keys;
+		ber_len_t j,l;
+		wchar_t *wcs, wc;
+		char *c, *d;
+		struct berval pwd;
+		
+		/* Expand incoming UTF8 string to UCS4 */
+		l = ldap_utf8_chars(qpw->rs_new.bv_val);
+		wcs = ch_malloc((l+1) * sizeof(wchar_t));
+
+		ldap_x_utf8s_to_wcs( wcs, qpw->rs_new.bv_val, l );
+		
+		/* Truncate UCS4 to UCS2 */
+		c = (char *)wcs;
+		for (j=0; j<l; j++) {
+			wc = wcs[j];
+			*c++ = wc & 0xff;
+			*c++ = (wc >> 8) & 0xff;
+		}
+		*c++ = 0;
+		pwd.bv_val = (char *)wcs;
+		pwd.bv_len = l * 2;
+
+		ml = ch_malloc(sizeof(Modifications));
+		if (!qpw->rs_modtail) qpw->rs_modtail = &ml->sml_next;
+		ml->sml_next = qpw->rs_mods;
+		qpw->rs_mods = ml;
+
+		keys = ch_malloc( 2 * sizeof(struct berval) );
+		BER_BVZERO( &keys[1] );
+		nthash( &pwd, keys );
+		
+		ml->sml_desc = ad_sambaNTPassword;
+		ml->sml_op = LDAP_MOD_REPLACE;
+#ifdef SLAP_MOD_INTERNAL
+		ml->sml_flags = SLAP_MOD_INTERNAL;
+#endif
+		ml->sml_numvals = 1;
+		ml->sml_values = keys;
+		ml->sml_nvalues = NULL;
+
+		ch_free(wcs);
+
+		ml = ch_malloc(sizeof(Modifications));
+		ml->sml_next = qpw->rs_mods;
+		qpw->rs_mods = ml;
+
+		keys = ch_malloc( 2 * sizeof(struct berval) );
+		keys[0].bv_val = ch_malloc( LDAP_PVT_INTTYPE_CHARS(long) );
+		keys[0].bv_len = snprintf(keys[0].bv_val,
+			LDAP_PVT_INTTYPE_CHARS(long),
+			"%ld", slap_get_time());
+		BER_BVZERO( &keys[1] );
+		
+		ml->sml_desc = ad_sambaPwdLastSet;
+		ml->sml_op = LDAP_MOD_REPLACE;
+#ifdef SLAP_MOD_INTERNAL
+		ml->sml_flags = SLAP_MOD_INTERNAL;
+#endif
+		ml->sml_numvals = 1;
+		ml->sml_values = keys;
+		ml->sml_nvalues = NULL;
+
+		if (pi->smb_must_change)
+		{
+			ml = ch_malloc(sizeof(Modifications));
+			ml->sml_next = qpw->rs_mods;
+			qpw->rs_mods = ml;
+
+			keys = ch_malloc( 2 * sizeof(struct berval) );
+			keys[0].bv_val = ch_malloc( LDAP_PVT_INTTYPE_CHARS(long) );
+			keys[0].bv_len = snprintf(keys[0].bv_val,
+					LDAP_PVT_INTTYPE_CHARS(long),
+					"%ld", slap_get_time() + pi->smb_must_change);
+			BER_BVZERO( &keys[1] );
+
+			ml->sml_desc = ad_sambaPwdMustChange;
+			ml->sml_op = LDAP_MOD_REPLACE;
+#ifdef SLAP_MOD_INTERNAL
+			ml->sml_flags = SLAP_MOD_INTERNAL;
+#endif
+			ml->sml_numvals = 1;
+			ml->sml_values = keys;
+			ml->sml_nvalues = NULL;
+		}
+
+		if (pi->smb_can_change)
+		{
+			ml = ch_malloc(sizeof(Modifications));
+			ml->sml_next = qpw->rs_mods;
+			qpw->rs_mods = ml;
+
+			keys = ch_malloc( 2 * sizeof(struct berval) );
+			keys[0].bv_val = ch_malloc( LDAP_PVT_INTTYPE_CHARS(long) );
+			keys[0].bv_len = snprintf(keys[0].bv_val,
+					LDAP_PVT_INTTYPE_CHARS(long),
+					"%ld", slap_get_time() + pi->smb_can_change);
+			BER_BVZERO( &keys[1] );
+
+			ml->sml_desc = ad_sambaPwdCanChange;
+			ml->sml_op = LDAP_MOD_REPLACE;
+#ifdef SLAP_MOD_INTERNAL
+			ml->sml_flags = SLAP_MOD_INTERNAL;
+#endif
+			ml->sml_numvals = 1;
+			ml->sml_values = keys;
+			ml->sml_nvalues = NULL;
+		}
+	}
+finish:
+	be_entry_release_r( op, e );
+	qpw->rs_new.bv_val[qpw->rs_new.bv_len] = term;
+
+	return rc;
+}
+
+static slap_overinst smbkrb5pwd;
+
+/* back-config stuff */
+enum {
+	PC_SMB_MUST_CHANGE = 1,
+	PC_SMB_CAN_CHANGE,
+	PC_SMB_ENABLE,
+	PC_SMB_KRB5REALM,
+	PC_SMB_REQUIREDCLASS,
+};
+
+static ConfigDriver smbkrb5pwd_cf_func;
+
+/*
+ * NOTE: uses OID arcs OLcfgCtAt:1 and OLcfgCtOc:1
+ */
+
+static ConfigTable smbkrb5pwd_cfats[] = {
+	{ "smbkrb5pwd-enable", "arg",
+		2, 0, 0, ARG_MAGIC|PC_SMB_ENABLE, smbkrb5pwd_cf_func,
+		"( OLcfgCtAt:1.1 NAME 'olcSmbKrb5PwdEnable' "
+		"DESC 'Modules to be enabled' "
+		"SYNTAX OMsDirectoryString )", NULL, NULL },
+	{ "smbkrb5pwd-must-change", "time",
+		2, 2, 0, ARG_MAGIC|ARG_INT|PC_SMB_MUST_CHANGE, smbkrb5pwd_cf_func,
+		"( OLcfgCtAt:1.2 NAME 'olcSmbKrb5PwdMustChange' "
+		"DESC 'Credentials validity interval' "
+		"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
+	{ "smbkrb5pwd-can-change", "time",
+		2, 2, 0, ARG_MAGIC|ARG_INT|PC_SMB_CAN_CHANGE, smbkrb5pwd_cf_func,
+		"( OLcfgCtAt:1.3 NAME 'olcSmbKrb5PwdCanChange' "
+		"DESC 'Credentials minimum validity interval' "
+		"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
+	{ "smbkrb5pwd-krb5realm", "arg",
+		2, 2, 0, ARG_MAGIC|ARG_STRING|PC_SMB_KRB5REALM, smbkrb5pwd_cf_func,
+		"( OLcfgCtAt:1.4 NAME 'olcSmbKrb5PwdKrb5Realm' "
+		"DESC 'Kerberos5 realm' "
+		"SYNTAX OMsDirectoryString )", NULL, NULL },
+	{ "smbkrb5pwd-requiredclass", "arg",
+		2, 2, 0, ARG_MAGIC|ARG_STRING|PC_SMB_REQUIREDCLASS,
+		smbkrb5pwd_cf_func,
+		"( OLcfgCtAt:1.5 NAME 'olcSmbKrb5PwdRequiredClass' "
+		"DESC 'Required objectClass' "
+		"SYNTAX OMsDirectoryString )", NULL, NULL },
+
+	{ NULL, NULL, 0, 0, 0, ARG_IGNORED }
+};
+
+static ConfigOCs smbkrb5pwd_cfocs[] = {
+	{ "( OLcfgCtOc:1.1 "
+		"NAME 'olcSmbKrb5PwdConfig' "
+		"DESC 'smbkrb5pwd overlay configuration' "
+		"SUP olcOverlayConfig "
+		"MAY ( "
+			"olcSmbKrb5PwdEnable "
+			"$ olcSmbKrb5PwdMustChange "
+			"$ olcSmbKrb5PwdCanChange "
+			"$ olcSmbKrb5PwdKrb5Realm "
+			"$ olcSmbKrb5PwdRequiredClass "
+		") )", Cft_Overlay, smbkrb5pwd_cfats },
+
+	{ NULL, 0, NULL }
+};
+
+/*
+ * add here other functionalities; handle their initialization
+ * as appropriate in smbkrb5pwd_modules_init().
+ */
+static slap_verbmasks smbkrb5pwd_modules[] = {
+	{ BER_BVC( "krb5" ),		SMBKRB5PWD_F_KRB5  },
+	{ BER_BVC( "samba" ),		SMBKRB5PWD_F_SAMBA },
+	{ BER_BVNULL,			-1 }
+};
+
+static int
+smbkrb5pwd_cf_func( ConfigArgs *c )
+{
+	slap_overinst	*on = (slap_overinst *)c->bi;
+
+	int		rc = 0;
+	smbkrb5pwd_t	*pi = on->on_bi.bi_private;
+
+	if ( c->op == SLAP_CONFIG_EMIT ) {
+		switch( c->type ) {
+		case PC_SMB_MUST_CHANGE:
+			c->value_int = pi->smb_must_change;
+			break;
+
+		case PC_SMB_CAN_CHANGE:
+			c->value_int = pi->smb_can_change;
+			break;
+
+		case PC_SMB_ENABLE:
+			c->rvalue_vals = NULL;
+			if ( pi->mode ) {
+				mask_to_verbs( smbkrb5pwd_modules, pi->mode, &c->rvalue_vals );
+				if ( c->rvalue_vals == NULL ) {
+					rc = 1;
+				}
+			}
+			break;
+
+		default:
+			assert( 0 );
+			rc = 1;
+		}
+		return rc;
+
+	} else if ( c->op == LDAP_MOD_DELETE ) {
+		switch( c->type ) {
+		case PC_SMB_MUST_CHANGE:
+			break;
+
+                case PC_SMB_CAN_CHANGE:
+                        break;
+
+		case PC_SMB_ENABLE:
+			if ( !c->line ) {
+				pi->mode = 0;
+
+			} else {
+				slap_mask_t	m;
+
+				m = verb_to_mask( c->line, smbkrb5pwd_modules );
+				pi->mode &= ~m;
+			}
+			break;
+
+		default:
+			assert( 0 );
+			rc = 1;
+		}
+		return rc;
+	}
+
+	switch( c->type ) {
+	case PC_SMB_MUST_CHANGE:
+		if ( c->value_int < 0 ) {
+			Debug( LDAP_DEBUG_ANY, "%s: smbkrb5pwd: "
+				"<%s> invalid negative value \"%d\".",
+				c->log, c->argv[ 0 ], 0 );
+			return 1;
+		}
+		pi->smb_must_change = c->value_int;
+		break;
+
+        case PC_SMB_CAN_CHANGE:
+                if ( c->value_int < 0 ) {
+                        Debug( LDAP_DEBUG_ANY, "%s: smbkrb5pwd: "
+                                "<%s> invalid negative value \"%d\".",
+                                c->log, c->argv[ 0 ], 0 );
+                        return 1;
+                }
+                pi->smb_can_change = c->value_int;
+                break;
+
+	case PC_SMB_ENABLE: {
+		slap_mask_t	mode = pi->mode, m;
+
+		rc = verbs_to_mask( c->argc, c->argv, smbkrb5pwd_modules, &m );
+		if ( rc > 0 ) {
+			Debug( LDAP_DEBUG_ANY, "%s: smbkrb5pwd: "
+				"<%s> unknown module \"%s\".\n",
+				c->log, c->argv[ 0 ], c->argv[ rc ] );
+			return 1;
+		}
+
+		/* we can hijack the smbkrb5pwd_t structure because
+		 * from within the configuration, this is the only
+		 * active thread. */
+		pi->mode |= m;
+
+		{
+			BackendDB	db = *c->be;
+
+			/* Re-initialize the module, because
+			 * the configuration might have changed */
+			db.bd_info = (BackendInfo *)on;
+			rc = smbkrb5pwd_modules_init( pi );
+			if ( rc ) {
+				pi->mode = mode;
+				return 1;
+			}
+		}
+
+		} break;
+
+	case PC_SMB_KRB5REALM: {
+		if (pi->kerberos_realm)
+			free(pi->kerberos_realm);
+		if ((pi->kerberos_realm = strdup(c->value_string)) == NULL)
+			return 1;
+		rc = lookup_admin_princstr(pi->kerberos_realm,
+					   &pi->admin_princstr);
+		if (rc)
+			return rc;
+		Log(LDAP_DEBUG_ANY, LDAP_LEVEL_INFO,
+		     "smbkrb5pwd : using admin principal %s\n",
+		      pi->admin_princstr);
+		break;
+	}
+
+	case PC_SMB_REQUIREDCLASS: {
+		if (!(pi->oc_requiredObjectclass = oc_find(c->value_string))) {
+			Log(LDAP_DEBUG_ANY, LDAP_LEVEL_INFO,
+			     "smbkrb5pwd : could not find required "
+			     "objectclass %s\n",
+			     c->value_string);
+			return 1;
+		}
+		break;
+	}
+	default:
+		assert( 0 );
+		return 1;
+	}
+	return rc;
+}
+
+static int
+smbkrb5pwd_modules_init( smbkrb5pwd_t *pi )
+{
+	static struct {
+		const char		*name;
+		AttributeDescription	**adp;
+	}
+        krb5_ad[] = {
+		{ "uid",			&ad_uid },
+		{ NULL }
+	},
+	samba_ad[] = {
+		{ "sambaNTPassword",		&ad_sambaNTPassword },
+		{ "sambaPwdLastSet",		&ad_sambaPwdLastSet },
+		{ "sambaPwdMustChange",		&ad_sambaPwdMustChange },
+		{ "sambaPwdCanChange",		&ad_sambaPwdCanChange },
+		{ NULL }
+	},
+	dummy_ad;
+
+	/* this is to silence the unused var warning */
+	dummy_ad.name = NULL;
+
+	if ( SMBKRB5PWD_DO_KRB5( pi ) ) {
+		int i, rc;
+		for ( i = 0; krb5_ad[ i ].name != NULL; i++ ) {
+			const char      *text;
+
+			*(krb5_ad[ i ].adp) = NULL;
+
+			rc = slap_str2ad( krb5_ad[ i ].name, krb5_ad[ i ].adp, &text );
+			if ( rc != LDAP_SUCCESS ) {
+				Debug( LDAP_DEBUG_ANY, "smbk5pwd: "
+					"unable to find \"%s\" attributeType: %s (%d).\n",
+					krb5_ad[ i ].name, text, rc );
+				return rc;
+			}
+		}
+	}
+
+	if ( SMBKRB5PWD_DO_SAMBA( pi ) && oc_sambaSamAccount == NULL ) {
+		int		i, rc;
+
+		oc_sambaSamAccount = oc_find( "sambaSamAccount" );
+		if ( !oc_sambaSamAccount ) {
+			Debug( LDAP_DEBUG_ANY, "smbkrb5pwd: "
+				"unable to find \"sambaSamAccount\" objectClass.\n",
+				0, 0, 0 );
+			return -1;
+		}
+
+		for ( i = 0; samba_ad[ i ].name != NULL; i++ ) {
+			const char	*text;
+
+			*(samba_ad[ i ].adp) = NULL;
+
+			rc = slap_str2ad( samba_ad[ i ].name, samba_ad[ i ].adp, &text );
+			if ( rc != LDAP_SUCCESS ) {
+				Debug( LDAP_DEBUG_ANY, "smbkrb5pwd: "
+					"unable to find \"%s\" attributeType: %s (%d).\n",
+					samba_ad[ i ].name, text, rc );
+				oc_sambaSamAccount = NULL;
+				return rc;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int
+smbkrb5pwd_db_init(BackendDB *be, ConfigReply *cr)
+{
+	slap_overinst	*on = (slap_overinst *)be->bd_info;
+	smbkrb5pwd_t	*pi;
+
+	pi = ch_calloc( 1, sizeof( smbkrb5pwd_t ) );
+	if ( pi == NULL ) {
+		return 1;
+	}
+	pi->admin_princstr = NULL;
+	pi->kerberos_realm = NULL;
+	pi->oc_requiredObjectclass = NULL;
+	ldap_pvt_thread_mutex_init(&pi->krb5_mutex);
+
+	on->on_bi.bi_private = (void *)pi;
+
+	return 0;
+}
+
+static int
+smbkrb5pwd_db_open(BackendDB *be, ConfigReply *cr)
+{
+	slap_overinst	*on = (slap_overinst *)be->bd_info;
+	smbkrb5pwd_t	*pi = (smbkrb5pwd_t *)on->on_bi.bi_private;
+
+	int	rc;
+
+	if ( pi->mode == 0 ) {
+		pi->mode = SMBKRB5PWD_F_ALL;
+	}
+
+	rc = smbkrb5pwd_modules_init( pi );
+	if ( rc ) {
+		return rc;
+	}
+
+	return 0;
+}
+
+static int
+smbkrb5pwd_db_destroy(BackendDB *be, ConfigReply *cr)
+{
+	slap_overinst	*on = (slap_overinst *)be->bd_info;
+	smbkrb5pwd_t	*pi = (smbkrb5pwd_t *)on->on_bi.bi_private;
+
+	if ( pi ) {
+		ch_free( pi );
+	}
+
+	return 0;
+}
+
+int
+smbkrb5pwd_initialize(void)
+{
+	int		rc;
+
+	smbkrb5pwd.on_bi.bi_type = "smbkrb5pwd";
+
+	smbkrb5pwd.on_bi.bi_db_init = smbkrb5pwd_db_init;
+	smbkrb5pwd.on_bi.bi_db_open = smbkrb5pwd_db_open;
+	smbkrb5pwd.on_bi.bi_db_destroy = smbkrb5pwd_db_destroy;
+
+	smbkrb5pwd.on_bi.bi_extended = smbkrb5pwd_exop_passwd;
+    
+	smbkrb5pwd.on_bi.bi_cf_ocs = smbkrb5pwd_cfocs;
+
+	rc = config_register_schema( smbkrb5pwd_cfats, smbkrb5pwd_cfocs );
+	if ( rc ) {
+		return rc;
+	}
+
+	return overlay_register( &smbkrb5pwd );
+}
+
+#if SLAPD_OVER_SMBKRB5PWD == SLAPD_MOD_DYNAMIC
+int init_module(int argc, char *argv[]) {
+	return smbkrb5pwd_initialize();
+}
+#endif
+
+#endif /* defined(SLAPD_OVER_SMBKRB5PWD) */
