diff --git a/clients/tools/ldappasswd.c b/clients/tools/ldappasswd.c
index 5e9737347976ea81bb7e03cbe0fd4aa90e5e129e..0deb9f95d9c07a1c6c2c586fcd8d974b1f23eac7 100644
--- a/clients/tools/ldappasswd.c
+++ b/clients/tools/ldappasswd.c
@@ -34,6 +34,7 @@ usage(const char *s)
 		"  -n\t\tmake no modifications\n"
 		"  -p port\tldap port\n"
 		"  -s secret\tnew password\n"
+		"  -S\t\tprompt for new password\n"
 		"  -v\t\tincrease verbosity\n"
 		"  -W\t\tprompt for bind password\n"
 		"  -w passwd\tbind password (for simple authentication)\n"
@@ -46,20 +47,26 @@ int
 main( int argc, char *argv[] )
 {
 	int rc;
+	char	*ldaphost = NULL;
+
 	char	*dn = NULL;
 	char	*binddn = NULL;
+
 	char	*bindpw = NULL;
-	char	*ldaphost = NULL;
 	char	*newpw = NULL;
+	char	*oldpw = NULL;
+
+	int		want_bindpw = 0;
+	int		want_newpw = 0;
+	int		want_oldpw = 0;
+
 	int		noupdates = 0;
 	int		i;
 	int		ldapport = 0;
 	int		debug = 0;
 	int		version = -1;
-	int		want_bindpw = 0;
 	LDAP	       *ld;
 	struct berval *bv = NULL;
-	BerElement *ber;
 
 	char	*retoid;
 	struct berval *retdata;
@@ -68,9 +75,23 @@ main( int argc, char *argv[] )
 		usage (argv[0]);
 
 	while( (i = getopt( argc, argv,
-		"D:d:h:np:s:vWw:" )) != EOF )
+		"Aa:D:d:h:np:Ss:vWw:" )) != EOF )
 	{
 		switch (i) {
+		case 'A':	/* prompt for oldr password */
+			want_oldpw++;
+			break;
+		case 'a':	/* old password (secret) */
+			oldpw = strdup (optarg);
+
+			{
+				char* p;
+
+				for( p = optarg; *p == '\0'; p++ ) {
+					*p = '*';
+				}
+			}
+			break;
 		case 'D':	/* bind distinguished name */
 			binddn = strdup (optarg);
 			break;
@@ -91,8 +112,20 @@ main( int argc, char *argv[] )
 			ldapport = strtol( optarg, NULL, 10 );
 			break;
 
+		case 'S':	/* prompt for user password */
+			want_newpw++;
+			break;
+
 		case 's':	/* new password (secret) */
 			newpw = strdup (optarg);
+
+			{
+				char* p;
+
+				for( p = optarg; *p == '\0'; p++ ) {
+					*p = '*';
+				}
+			}
 			break;
 
 		case 'v':	/* verbose */
@@ -105,6 +138,7 @@ main( int argc, char *argv[] )
 
 		case 'w':	/* bind password */
 			bindpw = strdup (optarg);
+
 			{
 				char* p;
 
@@ -126,7 +160,19 @@ main( int argc, char *argv[] )
 
 	dn = strdup( argv[optind] );
 
-	if( newpw == NULL ) {
+	if( want_oldpw && oldpw == NULL ) {
+		/* prompt for old password */
+		char *ckoldpw;
+		newpw = strdup(getpass("Old password: "));
+		ckoldpw = getpass("Re-enter old password: ");
+
+		if( strncmp( oldpw, ckoldpw, strlen(oldpw) )) {
+			fprintf( stderr, "passwords do not match\n" );
+			return EXIT_FAILURE;
+		}
+	}
+
+	if( want_newpw && newpw == NULL ) {
 		/* prompt for new password */
 		char *cknewpw;
 		newpw = strdup(getpass("New password: "));
@@ -138,13 +184,15 @@ main( int argc, char *argv[] )
 		}
 	}
 
-	if( binddn == NULL ) {
+	if( binddn == NULL && dn != NULL ) {
 		binddn = dn;
 		dn = NULL;
+
+		if( bindpw == NULL ) bindpw = oldpw;
 	}
 
-	/* handle bind password */
-	if (want_bindpw) {
+	if (want_bindpw && bindpw == NULL ) {
+		/* handle bind password */
 		fprintf( stderr, "Bind DN: %s\n", binddn );
 		bindpw = strdup( getpass("Enter bind password: "));
 	}
@@ -186,39 +234,45 @@ main( int argc, char *argv[] )
 		return EXIT_FAILURE;
 	}
 
-	/* build change password control */
-	ber = ber_alloc_t( LBER_USE_DER );
+	if( dn != NULL || oldpw != NULL || newpw != NULL ) {
+		/* build change password control */
+		BerElement *ber = ber_alloc_t( LBER_USE_DER );
 
-	if( ber == NULL ) {
-		perror( "ber_alloc_t" );
-		ldap_unbind( ld );
-		return EXIT_FAILURE;
-	}
+		if( ber == NULL ) {
+			perror( "ber_alloc_t" );
+			ldap_unbind( ld );
+			return EXIT_FAILURE;
+		}
 
-	if( dn != NULL ) {
-		ber_printf( ber, "{tsts}",
-			LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID, dn,
-			LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, newpw );
+		if( dn != NULL ) {
+			ber_printf( ber, "ts",
+				LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID, dn );
+			free(dn);
+		}
 
-		free(dn);
+		if( oldpw != NULL ) {
+			ber_printf( ber, "ts",
+				LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, oldpw );
+			free(oldpw);
+		}
 
-	} else {
-		ber_printf( ber, "{ts}",
-			LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, newpw );
-	}
+		if( newpw != NULL ) {
+			ber_printf( ber, "ts",
+				LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, newpw );
+			free(newpw);
+		}
 
-	free(newpw);
+		rc = ber_flatten( ber, &bv );
 
-	rc = ber_flatten( ber, &bv );
+		if( rc < 0 ) {
+			perror( "ber_flatten" );
+			ldap_unbind( ld );
+			return EXIT_FAILURE;
+		}
 
-	if( rc < 0 ) {
-		perror( "ber_flatten" );
-		ldap_unbind( ld );
-		return EXIT_FAILURE;
+		ber_free( ber, 1 );
 	}
 
-	ber_free( ber, 1 );
-
 	rc = ldap_extended_operation_s( ld,
 		LDAP_EXOP_X_MODIFY_PASSWD, bv, 
 		NULL, NULL,
@@ -226,6 +280,30 @@ main( int argc, char *argv[] )
 
 	ber_bvfree( bv );
 
+	if( retdata != NULL ) {
+		ber_tag_t tag;
+		char *s;
+		BerElement *ber = ber_init( retdata );
+
+		if( ber == NULL ) {
+			perror( "ber_init" );
+			ldap_unbind( ld );
+			return EXIT_FAILURE;
+		}
+
+		/* we should check the tag */
+		tag = ber_scanf( ber, "a", &s);
+
+		if( tag == LBER_ERROR ) {
+			perror( "ber_scanf" );
+		} else {
+			printf("New password: %s\n", s);
+			free( s );
+		}
+
+		ber_free( ber, 1 );
+	}
+
 	if ( rc != LDAP_SUCCESS ) {
 		ldap_perror( ld, "ldap_extended_operation" );
 		ldap_unbind( ld );
diff --git a/include/lutil.h b/include/lutil.h
index 9a385aca3dc36e4d1efae59ea3f4f862b5c06aa4..9e6336d840914325cf834f9f1df182b716ec7778 100644
--- a/include/lutil.h
+++ b/include/lutil.h
@@ -65,7 +65,10 @@ lutil_passwd LDAP_P((
 	const char **methods ));
 
 LIBLUTIL_F( struct berval * )
-lutil_passwd_generate LDAP_P((
+lutil_passwd_generate LDAP_P(( int ));
+
+LIBLUTIL_F( struct berval * )
+lutil_passwd_hash LDAP_P((
 	const struct berval *passwd,
 	const char *method ));
 
diff --git a/libraries/libldap/extended.c b/libraries/libldap/extended.c
index c3b382d18d9dfd45d5a8f9ebb2e75e16ed2764a7..fe6f549f220d84623627d66d0c50f0b44e6278a8 100644
--- a/libraries/libldap/extended.c
+++ b/libraries/libldap/extended.c
@@ -202,7 +202,7 @@ ldap_parse_extended_result (
 	}
 
 	rc = ber_scanf( ber, "{iaa" /*}*/, &errcode,
-		&ld->ld_matched, &ld->ld_matched );
+		&ld->ld_matched, &ld->ld_error );
 
 	if( rc == LBER_ERROR ) {
 		ld->ld_errno = LDAP_DECODING_ERROR;
@@ -237,7 +237,7 @@ ldap_parse_extended_result (
 
 	if( tag == LDAP_TAG_EXOP_RES_VALUE ) {
 		/* we have a resdata */
-		if( ber_scanf( ber, "O", &resoid ) == LBER_ERROR ) {
+		if( ber_scanf( ber, "O", &resdata ) == LBER_ERROR ) {
 			ld->ld_errno = LDAP_DECODING_ERROR;
 			ber_free( ber, 0 );
 			if( resoid != NULL ) LDAP_FREE( resoid );
diff --git a/libraries/liblutil/passwd.c b/libraries/liblutil/passwd.c
index efab836b8742cb0bf43d16ecd1617cca248aaa9e..c610c2bd101a8d95dcb79cbe6c6fb1cc5fbe9cf6 100644
--- a/libraries/liblutil/passwd.c
+++ b/libraries/liblutil/passwd.c
@@ -35,6 +35,9 @@
 #	include <pwd.h>
 #endif
 
+static const unsigned char crypt64[] =
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./";
+
 struct pw_scheme;
 
 typedef int (*PASSWD_CHK_FUNC)(
@@ -42,14 +45,14 @@ typedef int (*PASSWD_CHK_FUNC)(
 	const struct berval *passwd,
 	const struct berval *cred );
 
-typedef struct berval * (*PASSWD_GEN_FUNC) (
+typedef struct berval * (*PASSWD_HASH_FUNC) (
 	const struct pw_scheme *scheme,
 	const struct berval *passwd );
 
 struct pw_scheme {
 	struct berval name;
 	PASSWD_CHK_FUNC chk_fn;
-	PASSWD_GEN_FUNC gen_fn;
+	PASSWD_HASH_FUNC hash_fn;
 };
 
 /* password check routines */
@@ -84,38 +87,38 @@ static int chk_unix(
 	const struct berval *cred );
 
 
-/* password generation routines */
-static struct berval *gen_sha1(
+/* password hash routines */
+static struct berval *hash_sha1(
 	const struct pw_scheme *scheme,
 	const struct berval *passwd );
 
-static struct berval *gen_ssha1(
+static struct berval *hash_ssha1(
 	const struct pw_scheme *scheme,
 	const struct berval *passwd );
 
-static struct berval *gen_smd5(
+static struct berval *hash_smd5(
 	const struct pw_scheme *scheme,
 	const struct berval *passwd );
 
-static struct berval *gen_md5(
+static struct berval *hash_md5(
 	const struct pw_scheme *scheme,
 	const struct berval *passwd );
 
-static struct berval *gen_crypt(
+static struct berval *hash_crypt(
 	const struct pw_scheme *scheme,
 	const struct berval *passwd );
 
 
 static const struct pw_scheme pw_schemes[] =
 {
-	{ {sizeof("{SSHA}")-1, "{SSHA}"},	chk_ssha1, gen_ssha1 },
-	{ {sizeof("{SHA}")-1, "{SHA}"},		chk_sha1, gen_sha1 },
+	{ {sizeof("{SSHA}")-1, "{SSHA}"},	chk_ssha1, hash_ssha1 },
+	{ {sizeof("{SHA}")-1, "{SHA}"},		chk_sha1, hash_sha1 },
 
-	{ {sizeof("{SMD5}")-1, "{SMD5}"},	chk_smd5, gen_smd5 },
-	{ {sizeof("{MD5}")-1, "{MD5}"},		chk_md5, gen_md5 },
+	{ {sizeof("{SMD5}")-1, "{SMD5}"},	chk_smd5, hash_smd5 },
+	{ {sizeof("{MD5}")-1, "{MD5}"},		chk_md5, hash_md5 },
 
 #ifdef SLAPD_CRYPT
-	{ {sizeof("{CRYPT}")-1, "{CRYPT}"},	chk_crypt, gen_crypt },
+	{ {sizeof("{CRYPT}")-1, "{CRYPT}"},	chk_crypt, hash_crypt },
 #endif
 # if defined( HAVE_GETSPNAM ) \
   || ( defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) )
@@ -247,16 +250,48 @@ lutil_passwd(
 
 }
 
-struct berval * lutil_passwd_generate(
+struct berval * lutil_passwd_generate( int len )
+{
+	struct berval *pw;
+
+	if( len < 1 ) return NULL;
+
+	pw = ber_memalloc( sizeof( struct berval ) );
+	if( pw == NULL ) return NULL;
+
+	pw->bv_len = len;
+	pw->bv_val = ber_memalloc( len + 1 );
+
+	if( pw->bv_val == NULL ) {
+		ber_memfree( pw );
+		return NULL;
+	}
+
+	if( lutil_entropy( pw->bv_val, pw->bv_len) < 0 ) {
+		ber_bvfree( pw );
+		return NULL; 
+	}
+
+	for( len = 0; len < pw->bv_len; len++ ) {
+		pw->bv_val[len] = crypt64[
+			pw->bv_val[len] % (sizeof(crypt64)-1) ];
+	}
+
+	pw->bv_val[len] = '\0';
+	
+	return pw;
+}
+
+struct berval * lutil_passwd_hash(
 	const struct berval * passwd,
 	const char * method )
 {
 	const struct pw_scheme *sc = get_scheme( method );
 
 	if( sc == NULL ) return NULL;
-	if( ! sc->gen_fn ) return NULL;
+	if( ! sc->hash_fn ) return NULL;
 
-	return (sc->gen_fn)( sc, passwd );
+	return (sc->hash_fn)( sc, passwd );
 }
 
 static struct berval * pw_string(
@@ -579,7 +614,7 @@ static int chk_unix(
 #endif
 
 /* PASSWORD CHECK ROUTINES */
-static struct berval *gen_ssha1(
+static struct berval *hash_ssha1(
 	const struct pw_scheme *scheme,
 	const struct berval  *passwd )
 {
@@ -608,7 +643,7 @@ static struct berval *gen_ssha1(
 	return pw_string64( scheme, &digest, &salt);
 }
 
-static struct berval *gen_sha1(
+static struct berval *hash_sha1(
 	const struct pw_scheme *scheme,
 	const struct berval  *passwd )
 {
@@ -626,7 +661,7 @@ static struct berval *gen_sha1(
 	return pw_string64( scheme, &digest, NULL);
 }
 
-static struct berval *gen_smd5(
+static struct berval *hash_smd5(
 	const struct pw_scheme *scheme,
 	const struct berval  *passwd )
 {
@@ -655,7 +690,7 @@ static struct berval *gen_smd5(
 	return pw_string64( scheme, &digest, &salt );
 }
 
-static struct berval *gen_md5(
+static struct berval *hash_md5(
 	const struct pw_scheme *scheme,
 	const struct berval  *passwd )
 {
@@ -677,13 +712,10 @@ static struct berval *gen_md5(
 }
 
 #ifdef SLAPD_CRYPT
-static struct berval *gen_crypt(
+static struct berval *hash_crypt(
 	const struct pw_scheme *scheme,
 	const struct berval *passwd )
 {
-	static const unsigned char crypt64[] =
-		"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./";
-
 	struct berval hash;
 	unsigned char salt[3];
 	int i;
diff --git a/servers/slapd/back-ldbm/extended.c b/servers/slapd/back-ldbm/extended.c
index eb55797d8fee8c87bb85d941e734f04450f94736..bc172df0d83045833137e26447cfbd422d7dab05 100644
--- a/servers/slapd/back-ldbm/extended.c
+++ b/servers/slapd/back-ldbm/extended.c
@@ -32,6 +32,7 @@ ldbm_back_extended(
 	char		*oid,
     struct berval	*reqdata,
     struct berval	**rspdata,
+	LDAPControl *** rspctrls,
 	char**	text
 )
 {
@@ -40,8 +41,8 @@ ldbm_back_extended(
 	for( i=0; exop_table[i].oid != NULL; i++ ) {
 		if( strcmp( exop_table[i].oid, oid ) == 0 ) {
 			return (exop_table[i].extended)(
-				be, conn, op,
-				oid, reqdata, rspdata, text );
+				be, conn, op, oid,
+				reqdata, rspdata, rspctrls, text );
 		}
 	}
 
diff --git a/servers/slapd/back-ldbm/external.h b/servers/slapd/back-ldbm/external.h
index 24ca3560a84ad6aa1a6fb63e3eafff14e2b82f7a..aeac346579d5a38bac021b2013f1339986e83081 100644
--- a/servers/slapd/back-ldbm/external.h
+++ b/servers/slapd/back-ldbm/external.h
@@ -27,6 +27,7 @@ extern int ldbm_back_extended LDAP_P(( BackendDB *bd,
 	char *reqoid,
 	struct berval *reqdata,
 	struct berval **rspdata,
+	LDAPControl *** rspctrls,
 	char **text ));
 
 extern int ldbm_back_bind LDAP_P(( BackendDB *bd,
diff --git a/servers/slapd/back-ldbm/passwd.c b/servers/slapd/back-ldbm/passwd.c
index c8980768b63ac50ab231a7bc87e3d9ee77ac47d8..7ab5e1876687f91f3efb5ef266d784c236d38b80 100644
--- a/servers/slapd/back-ldbm/passwd.c
+++ b/servers/slapd/back-ldbm/passwd.c
@@ -24,6 +24,7 @@ ldbm_back_exop_passwd(
 	char		*oid,
     struct berval	*reqdata,
     struct berval	**rspdata,
+	LDAPControl *** rspctrls,
 	char**	text
 )
 {
@@ -51,15 +52,21 @@ ldbm_back_exop_passwd(
 	}
 
 	if( new == NULL || new->bv_len == 0 ) {
-		*text = ch_strdup("no password provided");
-		rc = LDAP_OPERATIONS_ERROR;
-		goto done;
+		new = slap_passwd_generate();
+
+		if( new == NULL || new->bv_len == 0 ) {
+			*text = ch_strdup("password generation failed.");
+			rc = LDAP_OPERATIONS_ERROR;
+			goto done;
+		}
+		
+		*rspdata = slap_passwd_return( new );
 	}
 
-	hash = slap_passwd_generate( new );
+	hash = slap_passwd_hash( new );
 
 	if( hash == NULL || hash->bv_len == 0 ) {
-		*text = ch_strdup("password generation failed");
+		*text = ch_strdup("password hash failed");
 		rc = LDAP_OPERATIONS_ERROR;
 		goto done;
 	}
@@ -75,9 +82,7 @@ ldbm_back_exop_passwd(
 		goto done;
 	}
 
-	e = dn2entry_w( be,
-		id ? id->bv_val : op->o_dn,
-		NULL );
+	e = dn2entry_w( be, dn, NULL );
 
 	if( e == NULL ) {
 		*text = ch_strdup("could not locate authorization entry");
diff --git a/servers/slapd/back-ldbm/proto-back-ldbm.h b/servers/slapd/back-ldbm/proto-back-ldbm.h
index c6aeaa519f05cec0b87bb364b4d71a26c7182da2..89aae2a4325dfd57f6de790381202c8788d52b83 100644
--- a/servers/slapd/back-ldbm/proto-back-ldbm.h
+++ b/servers/slapd/back-ldbm/proto-back-ldbm.h
@@ -151,6 +151,7 @@ extern int ldbm_back_exop_passwd LDAP_P(( BackendDB *bd,
 	char *oid,
 	struct berval *reqdata,
 	struct berval **rspdata,
+	LDAPControl ***rspctrls,
 	char **text ));
  
 
diff --git a/servers/slapd/extended.c b/servers/slapd/extended.c
index 55620e6109fa68fbc1af76f5e266a03ad1041054..f907dc808d677deb2804d02e0dd383d9996eb845 100644
--- a/servers/slapd/extended.c
+++ b/servers/slapd/extended.c
@@ -93,6 +93,7 @@ do_extended(
 	extop_list_t *ext;
 	char *text;
 	struct berval *rspdata;
+	LDAPControl **rspctrls;
 
 	Debug( LDAP_DEBUG_TRACE, "do_extended\n", 0, 0, 0 );
 
@@ -144,14 +145,15 @@ do_extended(
 	Debug( LDAP_DEBUG_ARGS, "do_extended: oid=%s\n", oid, 0 ,0 );
 
 	rspdata = NULL;
+	rspctrls = NULL;
 	text = NULL;
 
 	rc = (ext->ext_main)( extop_callback, conn, op,
-		oid, reqdata, &rspdata, &text );
+		oid, reqdata, &rspdata, &rspctrls, &text );
 
 	if( rc != SLAPD_ABANDON ) {
 		send_ldap_extended( conn, op, rc, NULL, text,
-			oid, rspdata );
+			oid, rspdata, rspctrls );
 	}
 
 	if ( rspdata != NULL )
diff --git a/servers/slapd/passwd.c b/servers/slapd/passwd.c
index 875bdf6fd0ac6454308234fb2d7d5ec5c061af9d..7a57bce12927cf3bd3a9a6d538bc80c554cd863c 100644
--- a/servers/slapd/passwd.c
+++ b/servers/slapd/passwd.c
@@ -21,7 +21,10 @@
 int passwd_extop(
 	SLAP_EXTOP_CALLBACK_FN ext_callback,
 	Connection *conn, Operation *op, char *oid,
-	struct berval *reqdata, struct berval **rspdata, char **text )
+	struct berval *reqdata,
+	struct berval **rspdata,
+	LDAPControl ***rspctrls,
+	char **text )
 {
 	int rc;
 
@@ -33,17 +36,12 @@ int passwd_extop(
 		return LDAP_STRONG_AUTH_REQUIRED;
 	}
 
-	if( reqdata == NULL || reqdata->bv_len == 0 ) {
-		*text = ch_strdup("request data missing");
-		return LDAP_PROTOCOL_ERROR;
-	}
-
 	if( conn->c_authz_backend != NULL &&
 		conn->c_authz_backend->be_extended )
 	{
 		rc = conn->c_authz_backend->be_extended(
 			conn->c_authz_backend,
-			conn, op, oid, reqdata, rspdata, text );
+			conn, op, oid, reqdata, rspdata, rspctrls, text );
 
 	} else {
 		*text = ch_strdup("operation not supported for current user");
@@ -64,7 +62,9 @@ int slap_passwd_parse( struct berval *reqdata,
 	ber_len_t len;
 	BerElement *ber;
 
-	assert( reqdata != NULL );
+	if( reqdata == NULL ) {
+		return LDAP_SUCCESS;
+	}
 
 	ber = ber_init( reqdata );
 
@@ -75,12 +75,6 @@ int slap_passwd_parse( struct berval *reqdata,
 		return LDAP_PROTOCOL_ERROR;
 	}
 
-	tag = ber_scanf(ber, "{" /*}*/);
-
-	if( tag == LBER_ERROR ) {
-		goto decoding_error;
-	}
-
 	tag = ber_peek_tag( ber, &len );
 
 	if( tag == LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID ) {
@@ -175,6 +169,35 @@ done:
 	return rc;
 }
 
+struct berval * slap_passwd_return(
+	struct berval		*cred )
+{
+	int rc;
+	struct berval *bv;
+	BerElement *ber = ber_alloc_t(LBER_USE_DER);
+
+	assert( cred != NULL );
+
+	Debug( LDAP_DEBUG_TRACE, "slap_passwd_return: %ld\n",
+		(long) cred->bv_len, 0, 0 );
+
+	if( ber == NULL ) return NULL;
+	
+	rc = ber_printf( ber, "tO",
+		LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, cred );
+
+	if( rc == -1 ) {
+		ber_free( ber, 1 );
+		return NULL;
+	}
+
+	(void) ber_flatten( ber, &bv );
+
+	ber_free( ber, 1 );
+
+	return bv;
+}
+
 int
 slap_passwd_check(
 	Attribute *a,
@@ -200,7 +223,13 @@ slap_passwd_check(
 	return( 1 );
 }
 
-struct berval * slap_passwd_generate(
+struct berval * slap_passwd_generate( void )
+{
+	Debug( LDAP_DEBUG_TRACE, "slap_passwd_generate\n", 0, 0, 0 );
+	return lutil_passwd_generate( 8 );
+}
+
+struct berval * slap_passwd_hash(
 	struct berval * cred )
 {
 	char* hash = default_passwd_hash ? default_passwd_hash : "{SSHA}";
@@ -211,7 +240,7 @@ struct berval * slap_passwd_generate(
 	ldap_pvt_thread_mutex_lock( &crypt_mutex );
 #endif
 
-	new = lutil_passwd_generate( cred , hash );
+	new = lutil_passwd_hash( cred , hash );
 	
 #ifdef SLAPD_CRYPT
 	ldap_pvt_thread_mutex_unlock( &crypt_mutex );
diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h
index 33d608892fb7a9957e22b2b27c7bec6f42121e7e..fe4dc39f5dd92870c7525064d9d73cf93c4b35ab 100644
--- a/servers/slapd/proto-slap.h
+++ b/servers/slapd/proto-slap.h
@@ -259,6 +259,7 @@ typedef int (*SLAP_EXTOP_MAIN_FN) LDAP_P((
 	char * oid,
 	struct berval * reqdata,
 	struct berval ** rspdata,
+	LDAPControl *** rspctrls,
 	char ** text ));
 
 typedef int (*SLAP_EXTOP_GETOID_FN) LDAP_P((
@@ -376,6 +377,7 @@ LIBSLAPD_F (void) send_ldap_sasl LDAP_P((
 	Connection *conn, Operation *op,
 	ber_int_t err, const char *matched,
 	const char *text,
+	LDAPControl **ctrls,
 	struct berval *cred ));
 
 LIBSLAPD_F (void) send_ldap_disconnect LDAP_P((
@@ -386,7 +388,8 @@ LIBSLAPD_F (void) send_ldap_extended LDAP_P((
 	Connection *conn, Operation *op,
 	ber_int_t err, const char *matched,
 	const char *text,
-	char *rspoid, struct berval *rspdata ));
+	char *rspoid, struct berval *rspdata,
+	LDAPControl **ctrls ));
 
 LIBSLAPD_F (void) send_search_result LDAP_P((
 	Connection *conn, Operation *op,
@@ -465,6 +468,7 @@ LIBSLAPD_F (int) starttls_extop LDAP_P((
 	char * oid,
 	struct berval * reqdata,
 	struct berval ** rspdata,
+	LDAPControl ***rspctrls,
 	char ** text ));
 
 
@@ -505,13 +509,19 @@ LIBSLAPD_F (int) passwd_extop LDAP_P((
 	char * oid,
 	struct berval * reqdata,
 	struct berval ** rspdata,
+	LDAPControl *** rspctrls,
 	char ** text ));
 
 LIBSLAPD_F (int) slap_passwd_check(
 	Attribute			*attr,
 	struct berval		*cred );
 
-LIBSLAPD_F (struct berval *) slap_passwd_generate(
+LIBSLAPD_F (struct berval *) slap_passwd_generate( void );
+
+LIBSLAPD_F (struct berval *) slap_passwd_hash(
+	struct berval		*cred );
+
+LIBSLAPD_F (struct berval *) slap_passwd_return(
 	struct berval		*cred );
 
 LIBSLAPD_F (int) slap_passwd_parse(
diff --git a/servers/slapd/result.c b/servers/slapd/result.c
index bc8dc7aa6114f722f2aa0549c9e56176e899bdd2..204ba41db1e7035e1a11a10db77c11a4a123e64c 100644
--- a/servers/slapd/result.c
+++ b/servers/slapd/result.c
@@ -243,7 +243,8 @@ send_ldap_response(
     const char	*text,
 	struct berval	**ref,
 	const char	*resoid,
-	struct berval	*data,
+	struct berval	*resdata,
+	struct berval	*sasldata,
 	LDAPControl **ctrls
 )
 {
@@ -279,12 +280,19 @@ send_ldap_response(
 			rc = ber_printf( ber, "{V}", ref );
 		}
 
+		if( rc != -1 && sasldata != NULL ) {
+			rc = ber_printf( ber, "tO",
+				LDAP_TAG_SASL_RES_CREDS, sasldata );
+		}
+
 		if( rc != -1 && resoid != NULL ) {
-			rc = ber_printf( ber, "s", resoid );
+			rc = ber_printf( ber, "ts",
+				LDAP_TAG_EXOP_RES_OID, resoid );
 		}
 
-		if( rc != -1 && data != NULL ) {
-			rc = ber_printf( ber, "O", data );
+		if( rc != -1 && resdata != NULL ) {
+			rc = ber_printf( ber, "tO",
+				LDAP_TAG_EXOP_RES_VALUE, resdata );
 		}
 
 		if( rc != -1 ) {
@@ -361,9 +369,10 @@ send_ldap_disconnect(
 		    0 );
 	}
 #endif
+
 	send_ldap_response( conn, op, tag, msgid,
 		err, NULL, text, NULL,
-		reqoid, NULL, NULL );
+		reqoid, NULL, NULL, NULL );
 
 	Statslog( LDAP_DEBUG_STATS,
 	    "conn=%ld op=%ld DISCONNECT err=%ld tag=%lu text=%s\n",
@@ -429,7 +438,7 @@ send_ldap_result(
 
 	send_ldap_response( conn, op, tag, msgid,
 		err, matched, text, ref,
-		NULL, NULL, ctrls );
+		NULL, NULL, NULL, ctrls );
 
 	Statslog( LDAP_DEBUG_STATS,
 	    "conn=%ld op=%ld RESULT tag=%lu err=%ld text=%s\n",
@@ -448,6 +457,7 @@ send_ldap_sasl(
     ber_int_t	err,
     const char	*matched,
     const char	*text,
+	LDAPControl **ctrls,
 	struct berval *cred
 )
 {
@@ -473,7 +483,7 @@ send_ldap_sasl(
 
 	send_ldap_response( conn, op, tag, msgid,
 		err, matched, text, NULL,
-		NULL, cred, NULL );
+		NULL, NULL, cred, ctrls  );
 }
 
 void
@@ -484,15 +494,18 @@ send_ldap_extended(
     const char	*matched,
     const char	*text,
     char		*rspoid,
-	struct berval *rspdata
+	struct berval *rspdata,
+	LDAPControl **ctrls
 )
 {
 	ber_tag_t tag;
 	ber_int_t msgid;
 
 	Debug( LDAP_DEBUG_TRACE,
-		"send_ldap_extended %ld:%s\n",
-		(long) err, rspoid ? rspoid : "", NULL );
+		"send_ldap_extended %ld:%s (%ld)\n",
+		(long) err,
+		rspoid ? rspoid : "",
+		rspdata != NULL ? (long) rspdata->bv_len : (long) 0 );
 
 	tag = req2res( op->o_tag );
 	msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
@@ -507,9 +520,10 @@ send_ldap_extended(
 		    0 );
 	}
 #endif
+
 	send_ldap_response( conn, op, tag, msgid,
 		err, matched, text, NULL,
-		rspoid, rspdata, NULL );
+		rspoid, rspdata, NULL, ctrls );
 }
 
 
@@ -572,7 +586,7 @@ send_search_result(
 
 	send_ldap_response( conn, op, tag, msgid,
 		err, matched, text, refs,
-		NULL, NULL, ctrls );
+		NULL, NULL, NULL, ctrls );
 
 	Statslog( LDAP_DEBUG_STATS,
 	    "conn=%ld op=%ld SEARCH RESULT tag=%lu err=%ld text=%s\n",
diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h
index de59ee406117700bb5cf82eb6bca2433175dd5d4..88a0b6418e9da42a03db273e57bc0b6792db582e 100644
--- a/servers/slapd/slap.h
+++ b/servers/slapd/slap.h
@@ -538,6 +538,7 @@ typedef int (*SLAP_EXTENDED_FN) LDAP_P((
 	char		*oid,
     struct berval * reqdata,
     struct berval ** rspdata,
+	LDAPControl ***rspctrls,
 	char**	text ));
 
 struct slap_backend_info {
diff --git a/servers/slapd/starttls.c b/servers/slapd/starttls.c
index 6cee1c2964527616f365aba3453c3f1e290d4d7f..410e450733ce0e3473d42cf0de0fe5e6fe309a82 100644
--- a/servers/slapd/starttls.c
+++ b/servers/slapd/starttls.c
@@ -26,6 +26,7 @@ starttls_extop (
 	char * oid,
 	struct berval * reqdata,
 	struct berval ** rspdata,
+	LDAPControl ***rspctrls,
 	char ** text )
 {
 	if ( reqdata != NULL ) {
@@ -62,6 +63,7 @@ starttls_extop (
 
     conn->c_is_tls = 1;
     conn->c_needs_tls_accept = 1;
+
     return(LDAP_SUCCESS);
 }
 
diff --git a/servers/slapd/tools/mimic.c b/servers/slapd/tools/mimic.c
index caea1a513558f0078172f65716d901a8304cb288..a3a7d603090e793b38d15b9310adff232f71308d 100644
--- a/servers/slapd/tools/mimic.c
+++ b/servers/slapd/tools/mimic.c
@@ -47,7 +47,8 @@ send_ldap_extended(
     const char	*matched,
     const char	*text,
     char	*rspoid,
-	struct berval *rspdata
+	struct berval *rspdata,
+	LDAPControl **ctrls
 )
 {
 	assert(0);
@@ -60,6 +61,7 @@ send_ldap_sasl(
     ber_int_t	err,
     const char	*matched,
     const char	*text,
+	LDAPControl **ctrls,
 	struct berval *cred
 )
 {