diff --git a/servers/slapd/back-ldap/back-ldap.h b/servers/slapd/back-ldap/back-ldap.h
index 96e8ef5af452b290d1f9434703c804c14c9aa1fd..2697340a1ea0525b16ec912024a957cbfedf9753 100644
--- a/servers/slapd/back-ldap/back-ldap.h
+++ b/servers/slapd/back-ldap/back-ldap.h
@@ -89,9 +89,6 @@ struct ldapinfo {
 	struct berval binddn;
 	struct berval bindpw;
 #ifdef LDAP_BACK_PROXY_AUTHZ
-	struct berval proxyauthzdn;
-	struct berval proxyauthzpw;
-
 	/* ID assert stuff */
 	int		idassert_mode;
 #define	LDAP_BACK_IDASSERT_LEGACY	0
@@ -100,8 +97,20 @@ struct ldapinfo {
 #define	LDAP_BACK_IDASSERT_SELF		3
 #define	LDAP_BACK_IDASSERT_OTHERDN	4
 #define	LDAP_BACK_IDASSERT_OTHERID	5
-	struct berval	idassert_id;
+
+	struct berval idassert_authcID;
+	struct berval idassert_authcDN;
+	struct berval idassert_passwd;
+
+	struct berval	idassert_authzID;
 	BerVarray	idassert_authz;
+	
+	int		idassert_authmethod;
+	int		idassert_sasl_flags;
+	struct berval	idassert_sasl_mech;
+	struct berval	idassert_sasl_realm;
+
+	int		idassert_ppolicy;
 	/* end of ID assert stuff */
 #endif /* LDAP_BACK_PROXY_AUTHZ */
 
diff --git a/servers/slapd/back-ldap/bind.c b/servers/slapd/back-ldap/bind.c
index 26e94c62c04638c2aed4bc36e2c03c1a0d0b10f0..4d91afe8b68602c2911eed8c4168a605b4940806 100644
--- a/servers/slapd/back-ldap/bind.c
+++ b/servers/slapd/back-ldap/bind.c
@@ -28,11 +28,12 @@
 #include <ac/socket.h>
 #include <ac/string.h>
 
-
 #define AVL_INTERNAL
 #include "slap.h"
 #include "back-ldap.h"
 
+#include <lutil_ldap.h>
+
 #define PRINT_CONNTREE 0
 
 static LDAP_REBIND_PROC	ldap_back_rebind;
@@ -408,11 +409,13 @@ ldap_back_dobind( struct ldapconn *lc, Operation *op, SlapReply *rs )
 			 * or if the client's identity is authorized */
 			switch ( li->idassert_mode ) {
 			case LDAP_BACK_IDASSERT_LEGACY:
-	      			if ( !BER_BVISNULL( &op->o_conn->c_dn ) && !BER_BVISEMPTY( &op->o_conn->c_dn )
-	      					&& !BER_BVISNULL( &li->proxyauthzdn ) && !BER_BVISEMPTY( &li->proxyauthzdn ) )
-				{
-					binddn = li->proxyauthzdn;
-					bindcred = li->proxyauthzpw;
+				if ( !BER_BVISNULL( &op->o_conn->c_dn ) && !BER_BVISEMPTY( &op->o_conn->c_dn ) ) {
+					if ( li->idassert_authmethod != LDAP_AUTH_SASL
+							&& !BER_BVISNULL( &li->idassert_authcDN ) && !BER_BVISEMPTY( &li->idassert_authcDN ) )
+					{
+						binddn = li->idassert_authcDN;
+						bindcred = li->idassert_passwd;
+					}
 				}
 				break;
 
@@ -428,13 +431,85 @@ ldap_back_dobind( struct ldapconn *lc, Operation *op, SlapReply *rs )
 						goto done;
 					}
 				}
-				binddn = li->proxyauthzdn;
-				bindcred = li->proxyauthzpw;
+
+				if ( li->idassert_authmethod != LDAP_AUTH_SASL ) {
+					binddn = li->idassert_authcDN;
+				}
+				bindcred = li->idassert_passwd;
 				break;
 			}
 
-			rs->sr_err = ldap_sasl_bind(lc->ld, binddn.bv_val,
-				LDAP_SASL_SIMPLE, &bindcred, NULL, NULL, &msgid);
+			/* NOTE: essentially copied from clients/tools/common.c :) */
+			switch ( li->idassert_authmethod ) {
+#ifdef HAVE_CYRUS_SASL
+			case LDAP_AUTH_SASL:
+				{
+				void		*defaults = NULL;
+				struct berval	authzID = BER_BVNULL;
+
+#if 0	/* will deal with this later... */
+				if ( sasl_secprops != NULL ) {
+					rs->sr_err = ldap_set_option( lc->ld, LDAP_OPT_X_SASL_SECPROPS,
+						(void *) sasl_secprops );
+
+					if ( rs->sr_err != LDAP_OPT_SUCCESS ) {
+						send_ldap_result( op, rs );
+						lc->bound = 0;
+						goto done;
+						
+					}
+				}
+#endif
+
+				switch ( li->idassert_mode ) {
+				case LDAP_BACK_IDASSERT_OTHERID:
+				case LDAP_BACK_IDASSERT_OTHERDN:
+					authzID = li->idassert_authzID;
+				}
+
+				defaults = lutil_sasl_defaults( lc->ld,
+						li->idassert_sasl_mech.bv_val,
+						li->idassert_sasl_realm.bv_val,
+						li->idassert_authcID.bv_val,
+						li->idassert_passwd.bv_val,
+						authzID.bv_val );
+
+				rs->sr_err = ldap_sasl_interactive_bind_s( lc->ld, NULL,
+						li->idassert_sasl_mech.bv_val, NULL, NULL,
+						li->idassert_sasl_flags, lutil_sasl_interact,
+						defaults );
+
+				lutil_sasl_freedefs( defaults );
+
+				rs->sr_err = slap_map_api2result( rs );
+				if ( rs->sr_err != LDAP_SUCCESS ) {
+					lc->bound = 0;
+					send_ldap_result( op, rs );
+
+				} else {
+					lc->bound = 1;
+				}
+				goto done;
+				}
+#endif /* HAVE_CYRUS_SASL */
+
+			case LDAP_AUTH_SIMPLE:
+				rs->sr_err = ldap_sasl_bind(lc->ld,
+						binddn.bv_val, LDAP_SASL_SIMPLE,
+						&bindcred, NULL, NULL, &msgid);
+				break;
+
+			case LDAP_AUTH_NONE:
+				lc->bound = 1;
+				goto done;
+
+			default:
+				/* unsupported! */
+				lc->bound = 0;
+				rs->sr_err = LDAP_AUTH_METHOD_NOT_SUPPORTED;
+				send_ldap_result( op, rs );
+				goto done;
+			}
 
 		} else
 #endif /* LDAP_BACK_PROXY_AUTHZ */
@@ -639,7 +714,7 @@ ldap_back_proxy_authz_ctrl(
 
 	*pctrls = NULL;
 
-	if ( BER_BVISNULL( &li->proxyauthzdn ) ) {
+	if ( BER_BVISNULL( &li->idassert_authcID ) ) {
 		goto done;
 	}
 
@@ -674,10 +749,14 @@ ldap_back_proxy_authz_ctrl(
 			goto done;
 		}
 
-		if ( BER_BVISEMPTY( &li->proxyauthzdn ) ) {
+		if ( BER_BVISEMPTY( &li->idassert_authcID ) ) {
 			goto done;
 		}
 
+	} else if ( li->idassert_mode == LDAP_BACK_IDASSERT_OTHERID && li->idassert_authmethod == LDAP_AUTH_SASL ) {
+		/* already asserted in SASL */
+		goto done;
+
 	} else if ( li->idassert_authz ) {
 		int		rc;
 		struct berval	authcDN = BER_BVISNULL( &op->o_conn->c_dn ) ? slap_empty_bv : op->o_conn->c_dn;
@@ -712,7 +791,7 @@ ldap_back_proxy_authz_ctrl(
 	case LDAP_BACK_IDASSERT_OTHERID:
 	case LDAP_BACK_IDASSERT_OTHERDN:
 		/* assert idassert DN */
-		assertedID = li->idassert_id;
+		assertedID = li->idassert_authzID;
 		break;
 
 	default:
@@ -729,17 +808,21 @@ ldap_back_proxy_authz_ctrl(
 	ctrls[ 0 ]->ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
 	ctrls[ 0 ]->ldctl_iscritical = 1;
 
-	/* already in u:ID form */
-	if ( li->idassert_mode == LDAP_BACK_IDASSERT_OTHERID ) {
+	switch ( li->idassert_mode ) {
+	/* already in u:ID or dn:DN form */
+	case LDAP_BACK_IDASSERT_OTHERID:
+	case LDAP_BACK_IDASSERT_OTHERDN:
 		ber_dupbv( &ctrls[ 0 ]->ldctl_value, &assertedID );
+		break;
 
 	/* needs the dn: prefix */
-	} else {
+	default:
 		ctrls[ 0 ]->ldctl_value.bv_len = assertedID.bv_len + STRLENOF( "dn:" );
 		ctrls[ 0 ]->ldctl_value.bv_val = ch_malloc( ctrls[ 0 ]->ldctl_value.bv_len + 1 );
 		AC_MEMCPY( ctrls[ 0 ]->ldctl_value.bv_val, "dn:", STRLENOF( "dn:" ) );
 		AC_MEMCPY( ctrls[ 0 ]->ldctl_value.bv_val + STRLENOF( "dn:" ),
 				assertedID.bv_val, assertedID.bv_len + 1 );
+		break;
 	}
 
 	if ( op->o_ctrls ) {
diff --git a/servers/slapd/back-ldap/config.c b/servers/slapd/back-ldap/config.c
index b83405e244349977c8d387ff68eef914ec69f9e0..a98431fe79d7b0e3732a3c050bc0eabaa6503069 100644
--- a/servers/slapd/back-ldap/config.c
+++ b/servers/slapd/back-ldap/config.c
@@ -153,28 +153,9 @@ ldap_back_db_config(
 		ber_str2bv( argv[1], 0, 1, &li->bindpw );
 
 #ifdef LDAP_BACK_PROXY_AUTHZ
-	/* name to use for proxyAuthz propagation */
-	} else if ( strcasecmp( argv[0], "proxyauthzdn" ) == 0 ) {
-		if (argc != 2) {
-			fprintf( stderr,
-	"%s: line %d: missing name in \"proxyauthzdn <name>\" line\n",
-			    fname, lineno );
-			return( 1 );
-		}
-		ber_str2bv( argv[1], 0, 1, &li->proxyauthzdn );
-
-	/* password to use for proxyAuthz propagation */
-	} else if ( strcasecmp( argv[0], "proxyauthzpw" ) == 0 ) {
-		if (argc != 2) {
-			fprintf( stderr,
-	"%s: line %d: missing password in \"proxyauthzpw <password>\" line\n",
-			    fname, lineno );
-			return( 1 );
-		}
-		ber_str2bv( argv[1], 0, 1, &li->proxyauthzpw );
-
 	/* identity assertion stuff... */
-	} else if ( strncasecmp( argv[0], "idassert-", STRLENOF( "idassert-" ) ) == 0 ) {
+	} else if ( strncasecmp( argv[0], "idassert-", STRLENOF( "idassert-" ) ) == 0
+			|| strncasecmp( argv[0], "proxyauthz", STRLENOF( "proxyauthz" ) ) == 0 ) {
 		return parse_idassert( be, fname, lineno, argc, argv );
 #endif /* LDAP_BACK_PROXY_AUTHZ */
 
@@ -673,6 +654,7 @@ parse_idassert(
 {
 	struct ldapinfo	*li = (struct ldapinfo *) be->be_private;
 
+	/* identity assertion mode */
 	if ( strcasecmp( argv[0], "idassert-mode" ) == 0 ) {
 		if ( argc != 2 ) {
 #ifdef NEW_LOGGING
@@ -714,16 +696,18 @@ parse_idassert(
 				/* force lowercase... */
 				id.bv_val[0] = 'u';
 				li->idassert_mode = LDAP_BACK_IDASSERT_OTHERID;
-				ber_dupbv( &li->idassert_id, &id );
+				ber_dupbv( &li->idassert_authzID, &id );
 
 			} else {
+				struct berval	dn;
+
 				/* default is DN? */
 				if ( strncasecmp( id.bv_val, "dn:", STRLENOF( "dn:" ) ) == 0 ) {
 					id.bv_val += STRLENOF( "dn:" );
 					id.bv_len -= STRLENOF( "dn:" );
 				}
 
-				rc = dnNormalize( 0, NULL, NULL, &id, &li->idassert_id, NULL );
+				rc = dnNormalize( 0, NULL, NULL, &id, &dn, NULL );
 				if ( rc != LDAP_SUCCESS ) {
 #ifdef NEW_LOGGING
 					LDAP_LOG( CONFIG, CRIT, 
@@ -737,10 +721,61 @@ parse_idassert(
 					return 1;
 				}
 
+				li->idassert_authzID.bv_val = ch_malloc( STRLENOF( "dn:" ) + dn.bv_len + 1 );
+				AC_MEMCPY( li->idassert_authzID.bv_val, "dn:", STRLENOF( "dn:" ) );
+				AC_MEMCPY( &li->idassert_authzID.bv_val[ STRLENOF( "dn:" ) ], dn.bv_val, dn.bv_len + 1 );
+				ch_free( dn.bv_val );
+
 				li->idassert_mode = LDAP_BACK_IDASSERT_OTHERDN;
 			}
 		}
 
+	/* name to use for proxyAuthz propagation */
+	} else if ( strcasecmp( argv[0], "idassert-authcdn" ) == 0
+			|| strcasecmp( argv[0], "proxyauthzdn" ) == 0 ) {
+		if ( argc != 2 ) {
+			fprintf( stderr,
+	"%s: line %d: missing name in \"%s <name>\" line\n",
+			    fname, lineno, argv[0] );
+			return( 1 );
+		}
+
+		if ( !BER_BVISNULL( &li->idassert_authcID ) ) {
+			fprintf( stderr,
+	"%s: line %d: authcDN incompatible with previously defined authcID\n",
+			    fname, lineno );
+			return( 1 );
+		}
+
+		if ( !BER_BVISNULL( &li->idassert_authcDN ) ) {
+			fprintf( stderr, "%s: line %d: "
+					"authcDN already defined; replacing...\n",
+					fname, lineno );
+			ch_free( li->idassert_authcDN.bv_val );
+		}
+		
+		ber_str2bv( argv[1], 0, 1, &li->idassert_authcDN );
+
+	/* password to use for proxyAuthz propagation */
+	} else if ( strcasecmp( argv[0], "idassert-passwd" ) == 0
+			|| strcasecmp( argv[0], "proxyauthzpw" ) == 0 ) {
+		if ( argc != 2 ) {
+			fprintf( stderr,
+	"%s: line %d: missing password in \"%s <password>\" line\n",
+			    fname, lineno, argv[0] );
+			return( 1 );
+		}
+
+		if ( !BER_BVISNULL( &li->idassert_passwd ) ) {
+			fprintf( stderr, "%s: line %d: "
+					"passwd already defined; replacing...\n",
+					fname, lineno );
+			ch_free( li->idassert_passwd.bv_val );
+		}
+		
+		ber_str2bv( argv[1], 0, 1, &li->idassert_passwd );
+
+	/* rules to accept identity assertion... */
 	} else if ( strcasecmp( argv[0], "idassert-authz" ) == 0 ) {
 		struct berval	rule;
 
@@ -748,6 +783,116 @@ parse_idassert(
 
 		ber_bvarray_add( &li->idassert_authz, &rule );
 
+	} else if ( strcasecmp( argv[0], "idassert-method" ) == 0 ) {
+		if ( argc < 2 ) {
+			fprintf( stderr,
+	"%s: line %d: missing method in \"%s <method>\" line\n",
+			    fname, lineno, argv[0] );
+			return( 1 );
+		}
+
+		if ( strcasecmp( argv[1], "none" ) == 0 ) {
+			/* FIXME: is this useful? */
+			li->idassert_authmethod = LDAP_AUTH_NONE;
+
+			if ( argc != 2 ) {
+				fprintf( stderr,
+	"%s: line %d: trailing args in \"%s %s ...\" line ignored\"\n",
+					fname, lineno, argv[0], argv[1] );
+			}
+
+		} else if ( strcasecmp( argv[1], "simple" ) == 0 ) {
+			li->idassert_authmethod = LDAP_AUTH_SIMPLE;
+
+			if ( argc != 2 ) {
+				fprintf( stderr,
+	"%s: line %d: trailing args in \"%s %s ...\" line ignored\"\n",
+					fname, lineno, argv[0], argv[1] );
+			}
+
+		} else if ( strcasecmp( argv[1], "sasl" ) == 0 ) {
+#ifdef HAVE_CYRUS_SASL
+			int	arg;
+
+			for ( arg = 2; arg < argc; arg++ ) {
+				if ( strncasecmp( argv[arg], "mech=", STRLENOF( "mech=" ) ) == 0 ) {
+					char	*val = argv[arg] + STRLENOF( "mech=" );
+
+					if ( !BER_BVISNULL( &li->idassert_sasl_mech ) ) {
+						fprintf( stderr, "%s: line %d: "
+								"SASL mech already defined; replacing...\n",
+			    					fname, lineno );
+						ch_free( li->idassert_sasl_mech.bv_val );
+					}
+					ber_str2bv( val, 0, 1, &li->idassert_sasl_mech );
+
+				} else if ( strncasecmp( argv[arg], "realm=", STRLENOF( "realm=" ) ) == 0 ) {
+					char	*val = argv[arg] + STRLENOF( "realm=" );
+
+					if ( !BER_BVISNULL( &li->idassert_sasl_realm ) ) {
+						fprintf( stderr, "%s: line %d: "
+								"SASL realm already defined; replacing...\n",
+			    					fname, lineno );
+						ch_free( li->idassert_sasl_realm.bv_val );
+					}
+					ber_str2bv( val, 0, 1, &li->idassert_sasl_realm );
+
+				} else if ( strncasecmp( argv[arg], "authcid=", STRLENOF( "authcid=" ) ) == 0 ) {
+					char	*val = argv[arg] + STRLENOF( "authcid=" );
+
+					if ( !BER_BVISNULL( &li->idassert_authcDN ) ) {
+						fprintf( stderr,
+				"%s: line %d: SASL authcID incompatible with previously defined authcDN\n",
+								fname, lineno );
+						return( 1 );
+					}
+
+					if ( !BER_BVISNULL( &li->idassert_authcID ) ) {
+						fprintf( stderr, "%s: line %d: "
+								"SASL authcID already defined; replacing...\n",
+			    					fname, lineno );
+						ch_free( li->idassert_authcID.bv_val );
+					}
+					if ( strncasecmp( argv[arg], "u:", STRLENOF( "u:" ) ) == 0 ) {
+						val += STRLENOF( "u:" );
+					}
+					ber_str2bv( val, 0, 1, &li->idassert_authcID );
+
+				} else if ( strncasecmp( argv[arg], "cred=", STRLENOF( "cred=" ) ) == 0 ) {
+					char	*val = argv[arg] + STRLENOF( "cred=" );
+
+					if ( !BER_BVISNULL( &li->idassert_passwd ) ) {
+						fprintf( stderr, "%s: line %d: "
+								"SASL cred already defined; replacing...\n",
+			    					fname, lineno );
+						ch_free( li->idassert_passwd.bv_val );
+					}
+					ber_str2bv( val, 0, 1, &li->idassert_passwd );
+
+				} else {
+					fprintf( stderr, "%s: line %d: "
+							"unknown SASL parameter %s\n",
+		    					fname, lineno, argv[arg] );
+					return 1;
+				}
+			}
+
+			li->idassert_authmethod = LDAP_AUTH_SASL;
+
+#else /* !HAVE_CYRUS_SASL */
+			fprintf( stderr, "%s: line %d: "
+					"compile --with-cyrus-sasl to enable SASL auth\n",
+					fname, lineno );
+			return 1;
+#endif /* !HAVE_CYRUS_SASL */
+
+		} else {
+			fprintf( stderr, "%s: line %d: "
+					"unhandled auth method %s\n",
+					fname, lineno );
+			return 1;
+		}
+
 	} else {
 		return SLAP_CONF_UNKNOWN;
 	}
diff --git a/servers/slapd/back-ldap/init.c b/servers/slapd/back-ldap/init.c
index 4645b5195e461c4fc12026c2ba97fe2fe69ac31b..2a7ec514911e1ac98d0b594f66402d7f371c8a13 100644
--- a/servers/slapd/back-ldap/init.c
+++ b/servers/slapd/back-ldap/init.c
@@ -102,11 +102,21 @@ ldap_back_db_init(
 	BER_BVZERO( &li->bindpw );
 
 #ifdef LDAP_BACK_PROXY_AUTHZ
-	BER_BVZERO( &li->proxyauthzdn );
-	BER_BVZERO( &li->proxyauthzpw );
-
 	li->idassert_mode = LDAP_BACK_IDASSERT_LEGACY;
-	BER_BVZERO( &li->idassert_id );
+
+	BER_BVZERO( &li->idassert_authcID );
+	BER_BVZERO( &li->idassert_authcDN );
+	BER_BVZERO( &li->idassert_passwd );
+
+	BER_BVZERO( &li->idassert_authzID );
+	li->idassert_authz = NULL;
+
+	li->idassert_authmethod = LDAP_AUTH_SIMPLE;
+	li->idassert_sasl_flags = LDAP_SASL_QUIET;
+	BER_BVZERO( &li->idassert_sasl_mech );
+	BER_BVZERO( &li->idassert_sasl_realm );
+
+	li->idassert_ppolicy = 0;
 #endif /* LDAP_BACK_PROXY_AUTHZ */
 
 #ifdef ENABLE_REWRITE
@@ -209,17 +219,29 @@ ldap_back_db_destroy(
 			BER_BVZERO( &li->bindpw );
 		}
 #ifdef LDAP_BACK_PROXY_AUTHZ
-		if ( !BER_BVISNULL( &li->proxyauthzdn ) ) {
-			ch_free( li->proxyauthzdn.bv_val );
-			BER_BVZERO( &li->proxyauthzdn );
+		if ( !BER_BVISNULL( &li->idassert_authcID ) ) {
+			ch_free( li->idassert_authcID.bv_val );
+			BER_BVZERO( &li->idassert_authcID );
+		}
+		if ( !BER_BVISNULL( &li->idassert_authcDN ) ) {
+			ch_free( li->idassert_authcDN.bv_val );
+			BER_BVZERO( &li->idassert_authcDN );
+		}
+		if ( !BER_BVISNULL( &li->idassert_passwd ) ) {
+			ch_free( li->idassert_passwd.bv_val );
+			BER_BVZERO( &li->idassert_passwd );
+		}
+		if ( !BER_BVISNULL( &li->idassert_authzID ) ) {
+			ch_free( li->idassert_authzID.bv_val );
+			BER_BVZERO( &li->idassert_authzID );
 		}
-		if ( !BER_BVISNULL( &li->proxyauthzpw ) ) {
-			ch_free( li->proxyauthzpw.bv_val );
-			BER_BVZERO( &li->proxyauthzpw );
+		if ( !BER_BVISNULL( &li->idassert_sasl_mech ) ) {
+			ch_free( li->idassert_sasl_mech.bv_val );
+			BER_BVZERO( &li->idassert_sasl_mech );
 		}
-		if ( !BER_BVISNULL( &li->idassert_id ) ) {
-			ch_free( li->idassert_id.bv_val );
-			BER_BVZERO( &li->idassert_id );
+		if ( !BER_BVISNULL( &li->idassert_sasl_realm ) ) {
+			ch_free( li->idassert_sasl_realm.bv_val );
+			BER_BVZERO( &li->idassert_sasl_realm );
 		}
 #endif /* LDAP_BACK_PROXY_AUTHZ */
                 if (li->conntree) {