andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 5 months ago
Clone
dc8c34
From 9022d77690b7e932e7fddc9d4c354f52c9c8121f Mon Sep 17 00:00:00 2001
dc8c34
From: Noriko Hosoi <nhosoi@redhat.com>
dc8c34
Date: Thu, 2 Apr 2015 11:49:46 -0700
dc8c34
Subject: [PATCH 309/319] Ticket #561 - disable writing unhashed#user#password
dc8c34
 to changelog
dc8c34
dc8c34
Backported:
dc8c34
. commit c4bd52e2211c043087765f74df6cf6cd41b8f234
dc8c34
  Ticket #561 - disable writing unhashed#user#password to changelog
dc8c34
dc8c34
. commit da3be3fbf497775f608d1289f72cfe427850f950
dc8c34
  Fix optimization issue introduced with fix for ticket #561,
dc8c34
dc8c34
. commit 1d4f3ca2e931e6d930056aeb683256965503c5e1
dc8c34
  Fixing a compiler warning introduced by Ticket #561
dc8c34
dc8c34
. commit 84b8bfd7d18a0613920dce36f1d3775d75e45a3e
dc8c34
  Fix for CVE-2014-8112
dc8c34
dc8c34
Description:
dc8c34
Introducing a config parameter nsslapd-unhashed-pw-switch to cn=config.
dc8c34
The parameter takes 3 values:
dc8c34
  on    - unhashed password is stored in the entry extension
dc8c34
          and logged in the changelog.
dc8c34
  nolog - unhashed password is stored in the entry extension
dc8c34
          but not logged in the changelog.
dc8c34
  off   - unhashed password is not stored in the entry extension.
dc8c34
dc8c34
https://fedorahosted.org/389/ticket/561
dc8c34
dc8c34
(cherry picked from commit bb565bd8e664a22aed754af092121d293d2fee5d)
dc8c34
---
dc8c34
 ldap/servers/plugins/replication/cl5_api.c | 48 +++++++++++++----
dc8c34
 ldap/servers/plugins/retrocl/retrocl_po.c  |  6 +++
dc8c34
 ldap/servers/slapd/add.c                   | 13 ++---
dc8c34
 ldap/servers/slapd/libglobs.c              | 84 +++++++++++++++++++++++++++++-
dc8c34
 ldap/servers/slapd/modify.c                | 45 +++++++++-------
dc8c34
 ldap/servers/slapd/opshared.c              | 35 +++++--------
dc8c34
 ldap/servers/slapd/proto-slap.h            |  2 +
dc8c34
 ldap/servers/slapd/slap.h                  |  8 +--
dc8c34
 ldap/servers/slapd/slapi-plugin.h          |  8 +++
dc8c34
 ldap/servers/slapd/slapi-private.h         |  1 +
dc8c34
 ldap/servers/slapd/util.c                  | 11 ++--
dc8c34
 11 files changed, 194 insertions(+), 67 deletions(-)
dc8c34
dc8c34
diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c
dc8c34
index ae522a3..0618d9b 100644
dc8c34
--- a/ldap/servers/plugins/replication/cl5_api.c
dc8c34
+++ b/ldap/servers/plugins/replication/cl5_api.c
dc8c34
@@ -322,7 +322,7 @@ static int _cl5Str2OperationType (const char *str);
dc8c34
 static void _cl5WriteString (const char *str, char **buff);
dc8c34
 static void _cl5ReadString (char **str, char **buff);
dc8c34
 static void _cl5WriteMods (LDAPMod **mods, char **buff);
dc8c34
-static void _cl5WriteMod (LDAPMod *mod, char **buff);
dc8c34
+static int _cl5WriteMod (LDAPMod *mod, char **buff);
dc8c34
 static int _cl5ReadMods (LDAPMod ***mods, char **buff);
dc8c34
 static int _cl5ReadMod (Slapi_Mod *mod, char **buff);
dc8c34
 static int _cl5GetModsSize (LDAPMod **mods);
dc8c34
@@ -2474,7 +2474,7 @@ static void _cl5WriteMods (LDAPMod **mods, char **buff)
dc8c34
 {	
dc8c34
 	PRInt32 i;
dc8c34
 	char *mod_start;
dc8c34
-	PRInt32 count;
dc8c34
+	PRInt32 count = 0;
dc8c34
 
dc8c34
 	if (mods == NULL)
dc8c34
 		return;
dc8c34
@@ -2483,30 +2483,49 @@ static void _cl5WriteMods (LDAPMod **mods, char **buff)
dc8c34
 	mod_start = (*buff) + sizeof (count);
dc8c34
 
dc8c34
 	/* write mods*/
dc8c34
-	for (i=0; mods[i]; i++)
dc8c34
-	{
dc8c34
-		_cl5WriteMod (mods[i], &mod_start);
dc8c34
+	for (i = 0; mods[i]; i++) {
dc8c34
+		if (0 <= _cl5WriteMod (mods[i], &mod_start)) {
dc8c34
+			count++;
dc8c34
+		}
dc8c34
 	}
dc8c34
 
dc8c34
-	count = PR_htonl(i);
dc8c34
+	count = PR_htonl(count);
dc8c34
 	memcpy (*buff, &count, sizeof (count));	
dc8c34
 	
dc8c34
 	(*buff) = mod_start;
dc8c34
 }
dc8c34
 
dc8c34
-static void _cl5WriteMod (LDAPMod *mod, char **buff)
dc8c34
+/*
dc8c34
+ * return values:
dc8c34
+ *     positive: no need to encrypt && succeeded to write a mod
dc8c34
+ *            0: succeeded to encrypt && write a mod
dc8c34
+ *     netative: failed to encrypt && no write to the changelog
dc8c34
+ */
dc8c34
+static int
dc8c34
+_cl5WriteMod (LDAPMod *mod, char **buff)
dc8c34
 {
dc8c34
+	char *orig_pos;
dc8c34
 	char *pos;
dc8c34
 	PRInt32 count;
dc8c34
 	struct berval *bv;
dc8c34
 	struct berval *encbv;
dc8c34
 	struct berval *bv_to_use;
dc8c34
 	Slapi_Mod smod;
dc8c34
-	int rc = 0;
dc8c34
+	int rc = -1;
dc8c34
+
dc8c34
+	if (NULL == mod) {
dc8c34
+		return rc;
dc8c34
+	}
dc8c34
+	if (SLAPD_UNHASHED_PW_NOLOG == slapi_config_get_unhashed_pw_switch()) {
dc8c34
+		if (0 == strcasecmp(mod->mod_type, PSEUDO_ATTR_UNHASHEDUSERPASSWORD)) {
dc8c34
+			/* If nsslapd-unhashed-pw-switch == nolog, skip writing it to cl. */
dc8c34
+			return rc;
dc8c34
+		}
dc8c34
+	}
dc8c34
 
dc8c34
 	slapi_mod_init_byref(&smod, mod);
dc8c34
 
dc8c34
-	pos = *buff;
dc8c34
+	orig_pos = pos = *buff;
dc8c34
 	/* write mod op */
dc8c34
 	*pos = (PRUint8)slapi_mod_get_operation (&smod);
dc8c34
 	pos ++;
dc8c34
@@ -2516,7 +2535,7 @@ static void _cl5WriteMod (LDAPMod *mod, char **buff)
dc8c34
 	/* write value count */
dc8c34
 	count = PR_htonl(slapi_mod_get_num_values(&smod));
dc8c34
 	memcpy (pos, &count, sizeof (count));
dc8c34
-	pos += sizeof (PRInt32);	
dc8c34
+	pos += sizeof (PRInt32);
dc8c34
 
dc8c34
 	bv = slapi_mod_get_first_value (&smod);
dc8c34
 	while (bv)
dc8c34
@@ -2536,6 +2555,8 @@ static void _cl5WriteMod (LDAPMod *mod, char **buff)
dc8c34
 						"_cl5WriteMod: encrypting \"%s: %s\" failed\n",
dc8c34
 						slapi_mod_get_type(&smod), bv->bv_val);
dc8c34
 			bv_to_use = NULL;
dc8c34
+			rc = -1;
dc8c34
+			break;
dc8c34
 		}
dc8c34
 		if (bv_to_use) {
dc8c34
 			_cl5WriteBerval (bv_to_use, &pos;;
dc8c34
@@ -2544,9 +2565,14 @@ static void _cl5WriteMod (LDAPMod *mod, char **buff)
dc8c34
 		bv = slapi_mod_get_next_value (&smod);
dc8c34
 	}
dc8c34
 
dc8c34
-	(*buff) = pos;
dc8c34
+	if (rc < 0) {
dc8c34
+		(*buff) = orig_pos;
dc8c34
+	} else {
dc8c34
+		(*buff) = pos;
dc8c34
+	}
dc8c34
 
dc8c34
 	slapi_mod_done (&smod);
dc8c34
+	return rc;
dc8c34
 }
dc8c34
 
dc8c34
 /* mods format:
dc8c34
diff --git a/ldap/servers/plugins/retrocl/retrocl_po.c b/ldap/servers/plugins/retrocl/retrocl_po.c
dc8c34
index c3d1c41..3fdf887 100644
dc8c34
--- a/ldap/servers/plugins/retrocl/retrocl_po.c
dc8c34
+++ b/ldap/servers/plugins/retrocl/retrocl_po.c
dc8c34
@@ -101,6 +101,12 @@ static lenstr *make_changes_string(LDAPMod **ldm, const char **includeattrs)
dc8c34
 		continue;
dc8c34
 	    }
dc8c34
 	}
dc8c34
+	if (SLAPD_UNHASHED_PW_NOLOG == slapi_config_get_unhashed_pw_switch()) {
dc8c34
+		if (0 == strcasecmp(ldm[ i ]->mod_type, PSEUDO_ATTR_UNHASHEDUSERPASSWORD)) {
dc8c34
+			/* If nsslapd-unhashed-pw-switch == nolog, skip writing it to cl. */
dc8c34
+			continue;
dc8c34
+		}
dc8c34
+	}
dc8c34
 	switch ( ldm[ i ]->mod_op  & ~LDAP_MOD_BVALUES ) {
dc8c34
 	case LDAP_MOD_ADD:
dc8c34
 	    addlenstr( l, "add: " );
dc8c34
diff --git a/ldap/servers/slapd/add.c b/ldap/servers/slapd/add.c
dc8c34
index f52f766..37060df 100644
dc8c34
--- a/ldap/servers/slapd/add.c
dc8c34
+++ b/ldap/servers/slapd/add.c
dc8c34
@@ -447,7 +447,6 @@ static void op_shared_add (Slapi_PBlock *pb)
dc8c34
 	int	err;
dc8c34
 	int internal_op, repl_op, legacy_op, lastmod;
dc8c34
 	char *pwdtype = NULL;
dc8c34
-	Slapi_Value **unhashed_password_vals = NULL;
dc8c34
 	Slapi_Attr *attr = NULL;
dc8c34
 	Slapi_Entry *referral;
dc8c34
 	char errorbuf[BUFSIZ];
dc8c34
@@ -545,6 +544,7 @@ static void op_shared_add (Slapi_PBlock *pb)
dc8c34
 		{
dc8c34
 			Slapi_Value **present_values;
dc8c34
 			present_values= attr_get_present_values(attr);
dc8c34
+			Slapi_Value **unhashed_password_vals = NULL;
dc8c34
 
dc8c34
 			/* Set the backend in the pblock.  The slapi_access_allowed function
dc8c34
 			 * needs this set to work properly. */
dc8c34
@@ -576,11 +576,13 @@ static void op_shared_add (Slapi_PBlock *pb)
dc8c34
 				add_password_attrs(pb, operation, e);
dc8c34
 				slapi_entry_attr_replace_sv(e, SLAPI_USERPWD_ATTR, vals);
dc8c34
 				valuearray_free(&vals);
dc8c34
-				
dc8c34
-				/* Add the unhashed password pseudo-attribute to the entry */
dc8c34
-				pwdtype = slapi_attr_syntax_normalize(PSEUDO_ATTR_UNHASHEDUSERPASSWORD);
dc8c34
-				slapi_entry_add_values_sv(e, pwdtype, unhashed_password_vals);
dc8c34
+				if (SLAPD_UNHASHED_PW_OFF != config_get_unhashed_pw_switch()) {
dc8c34
+					/* Add the unhashed password pseudo-attribute to the entry */
dc8c34
+					pwdtype = slapi_attr_syntax_normalize(PSEUDO_ATTR_UNHASHEDUSERPASSWORD);
dc8c34
+					slapi_entry_add_values_sv(e, pwdtype, unhashed_password_vals);
dc8c34
+				}
dc8c34
 			}
dc8c34
+			valuearray_free(&unhashed_password_vals);
dc8c34
 		}
dc8c34
 
dc8c34
        /* look for multiple backend local credentials or replication local credentials */
dc8c34
@@ -751,7 +753,6 @@ done:
dc8c34
 	slapi_ch_free((void **)&operation->o_params.p.p_add.parentuniqueid);
dc8c34
 	slapi_entry_free(e);
dc8c34
 	slapi_pblock_set(pb, SLAPI_ADD_ENTRY, NULL);
dc8c34
-	valuearray_free(&unhashed_password_vals);
dc8c34
 	slapi_ch_free((void**)&pwdtype);
dc8c34
 	slapi_ch_free_string(&proxydn);
dc8c34
 	slapi_ch_free_string(&proxystr);
dc8c34
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
dc8c34
index 825dcee..dbb0fa8 100644
dc8c34
--- a/ldap/servers/slapd/libglobs.c
dc8c34
+++ b/ldap/servers/slapd/libglobs.c
dc8c34
@@ -121,7 +121,8 @@ typedef enum {
dc8c34
 	CONFIG_SPECIAL_ERRORLOGLEVEL, /* requires & with LDAP_DEBUG_ANY */
dc8c34
 	CONFIG_STRING_OR_EMPTY, /* use an empty string */
dc8c34
 	CONFIG_SPECIAL_ANON_ACCESS_SWITCH, /* maps strings to an enumeration */
dc8c34
-	CONFIG_SPECIAL_VALIDATE_CERT_SWITCH /* maps strings to an enumeration */
dc8c34
+	CONFIG_SPECIAL_VALIDATE_CERT_SWITCH, /* maps strings to an enumeration */
dc8c34
+	CONFIG_SPECIAL_UNHASHED_PW_SWITCH /* unhashed pw: on/off/nolog */
dc8c34
 } ConfigVarType;
dc8c34
 
dc8c34
 static int config_set_onoff( const char *attrname, char *value,
dc8c34
@@ -269,6 +270,7 @@ int init_mempool_switch;
dc8c34
 #define DEFAULT_SSLCLIENTAPTH "off"
dc8c34
 #define DEFAULT_ALLOW_ANON_ACCESS "on"
dc8c34
 #define DEFAULT_VALIDATE_CERT "warn"
dc8c34
+#define DEFAULT_UNHASHED_PW_SWITCH "on"
dc8c34
 
dc8c34
 static int
dc8c34
 isInt(ConfigVarType type)
dc8c34
@@ -1041,6 +1043,11 @@ static struct config_get_and_set {
dc8c34
 		NULL, 0,
dc8c34
 		(void**)&global_slapdFrontendConfig.ndn_cache_max_size,
dc8c34
 		CONFIG_INT, (ConfigGetFunc)config_get_ndn_cache_size},
dc8c34
+	{CONFIG_UNHASHED_PW_SWITCH_ATTRIBUTE, config_set_unhashed_pw_switch,
dc8c34
+		NULL, 0,
dc8c34
+		(void**)&global_slapdFrontendConfig.unhashed_pw_switch,
dc8c34
+		CONFIG_SPECIAL_UNHASHED_PW_SWITCH,
dc8c34
+		(ConfigGetFunc)config_get_unhashed_pw_switch}
dc8c34
 #ifdef MEMPOOL_EXPERIMENTAL
dc8c34
 	,{CONFIG_MEMPOOL_SWITCH_ATTRIBUTE, config_set_mempool_switch,
dc8c34
 		NULL, 0,
dc8c34
@@ -1459,6 +1466,7 @@ FrontendConfig_init () {
dc8c34
   cfg->disk_grace_period = 60; /* 1 hour */
dc8c34
   init_disk_logging_critical = cfg->disk_logging_critical = LDAP_OFF;
dc8c34
   cfg->sasl_max_bufsize = SLAPD_DEFAULT_SASL_MAXBUFSIZE;
dc8c34
+  cfg->unhashed_pw_switch = SLAPD_UNHASHED_PW_ON;
dc8c34
   init_listen_backlog_size = cfg->listen_backlog_size = DAEMON_LISTEN_SIZE;
dc8c34
   init_ignore_time_skew = cfg->ignore_time_skew = LDAP_OFF;
dc8c34
 
dc8c34
@@ -6552,7 +6560,6 @@ config_get_allowed_to_delete_attrs(void)
dc8c34
     return retVal;
dc8c34
 }
dc8c34
 
dc8c34
-
dc8c34
 int
dc8c34
 config_set_allowed_to_delete_attrs( const char *attrname, char *value,
dc8c34
                                     char *errorbuf, int apply )
dc8c34
@@ -6711,6 +6718,62 @@ config_initvalue_to_onoff(struct config_get_and_set *cgas, char *initvalbuf, siz
dc8c34
 	return retval;
dc8c34
 }
dc8c34
 
dc8c34
+int
dc8c34
+config_set_unhashed_pw_switch(const char *attrname, char *value,
dc8c34
+                              char *errorbuf, int apply)
dc8c34
+{
dc8c34
+    int retVal = LDAP_SUCCESS;
dc8c34
+    slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
dc8c34
+
dc8c34
+    if (config_value_is_null(attrname, value, errorbuf, 0)) {
dc8c34
+        return LDAP_OPERATIONS_ERROR;
dc8c34
+    }
dc8c34
+
dc8c34
+    if ((strcasecmp(value, "on") != 0) && (strcasecmp(value, "off") != 0) &&
dc8c34
+        (strcasecmp(value, "nolog") != 0)) {
dc8c34
+        PR_snprintf(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
dc8c34
+            "%s: invalid value \"%s\". Valid values are \"on\", "
dc8c34
+            "\"off\", or \"nolog\".", attrname, value);
dc8c34
+        retVal = LDAP_OPERATIONS_ERROR;
dc8c34
+    }
dc8c34
+
dc8c34
+    if (!apply) {
dc8c34
+        /* we can return now if we aren't applying the changes */
dc8c34
+        return retVal;
dc8c34
+    }
dc8c34
+
dc8c34
+    CFG_LOCK_WRITE(slapdFrontendConfig);
dc8c34
+
dc8c34
+    if (strcasecmp(value, "on") == 0 ) {
dc8c34
+        slapdFrontendConfig->unhashed_pw_switch = SLAPD_UNHASHED_PW_ON;
dc8c34
+    } else if (strcasecmp(value, "off") == 0 ) {
dc8c34
+        slapdFrontendConfig->unhashed_pw_switch = SLAPD_UNHASHED_PW_OFF;
dc8c34
+    } else if (strcasecmp(value, "nolog") == 0) {
dc8c34
+        slapdFrontendConfig->unhashed_pw_switch = SLAPD_UNHASHED_PW_NOLOG;
dc8c34
+    }
dc8c34
+
dc8c34
+    CFG_UNLOCK_WRITE(slapdFrontendConfig);
dc8c34
+    return retVal;
dc8c34
+}
dc8c34
+
dc8c34
+int
dc8c34
+slapi_config_get_unhashed_pw_switch()
dc8c34
+{
dc8c34
+    return config_get_unhashed_pw_switch();
dc8c34
+}
dc8c34
+
dc8c34
+int
dc8c34
+config_get_unhashed_pw_switch()
dc8c34
+{
dc8c34
+    int retVal = 0;
dc8c34
+    slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
dc8c34
+    CFG_LOCK_READ(slapdFrontendConfig);
dc8c34
+    retVal = slapdFrontendConfig->unhashed_pw_switch;
dc8c34
+    CFG_UNLOCK_READ(slapdFrontendConfig);
dc8c34
+
dc8c34
+    return retVal;
dc8c34
+}
dc8c34
+
dc8c34
 /*
dc8c34
  * This function is intended to be used from the dse code modify callback.  It
dc8c34
  * is "optimized" for that case because it takes a berval** of values, which is
dc8c34
@@ -6931,6 +6994,23 @@ config_set_value(
dc8c34
         slapi_entry_attr_set_charptr(e, cgas->attr_name, sval);
dc8c34
         break;
dc8c34
 
dc8c34
+    case CONFIG_SPECIAL_UNHASHED_PW_SWITCH:
dc8c34
+        if (!value) {
dc8c34
+            slapi_entry_attr_set_charptr(e, cgas->attr_name, "on");
dc8c34
+            break;
dc8c34
+        }
dc8c34
+
dc8c34
+        if (*((int *)value) == SLAPD_UNHASHED_PW_OFF) {
dc8c34
+            sval = "off";
dc8c34
+        } else if (*((int *)value) == SLAPD_UNHASHED_PW_NOLOG) {
dc8c34
+            sval = "nolog";
dc8c34
+        } else {
dc8c34
+            sval = "on";
dc8c34
+        }
dc8c34
+        slapi_entry_attr_set_charptr(e, cgas->attr_name, sval);
dc8c34
+
dc8c34
+        break;
dc8c34
+
dc8c34
     case CONFIG_SPECIAL_VALIDATE_CERT_SWITCH:
dc8c34
         if (!value) {
dc8c34
             slapi_entry_attr_set_charptr(e, cgas->attr_name, "off");
dc8c34
diff --git a/ldap/servers/slapd/modify.c b/ldap/servers/slapd/modify.c
dc8c34
index 9c6610f..c67ef14 100644
dc8c34
--- a/ldap/servers/slapd/modify.c
dc8c34
+++ b/ldap/servers/slapd/modify.c
dc8c34
@@ -894,13 +894,15 @@ static void op_shared_modify (Slapi_PBlock *pb, int pw_change, char *old_pw)
dc8c34
 						/*
dc8c34
 						 *  Finally, delete the unhashed userpassword
dc8c34
 						 */
dc8c34
-						bval.bv_val = password;
dc8c34
-						bval.bv_len = strlen(password);
dc8c34
-						bv[0] = &bval;
dc8c34
-						bv[1] = NULL;
dc8c34
-						valuearray_init_bervalarray(bv, &va);
dc8c34
-						slapi_mods_add_mod_values(&smods, pw_mod->mod_op, unhashed_pw_attr, va);
dc8c34
-						valuearray_free(&va);
dc8c34
+						if (SLAPD_UNHASHED_PW_OFF != config_get_unhashed_pw_switch()) {
dc8c34
+							bval.bv_val = password;
dc8c34
+							bval.bv_len = strlen(password);
dc8c34
+							bv[0] = &bval;
dc8c34
+							bv[1] = NULL;
dc8c34
+							valuearray_init_bervalarray(bv, &va);
dc8c34
+							slapi_mods_add_mod_values(&smods, pw_mod->mod_op, unhashed_pw_attr, va);
dc8c34
+							valuearray_free(&va);
dc8c34
+						}
dc8c34
 					} else {
dc8c34
 						/*
dc8c34
 						 *  Password is encoded, try and find a matching unhashed_password to delete
dc8c34
@@ -924,28 +926,31 @@ static void op_shared_modify (Slapi_PBlock *pb, int pw_change, char *old_pw)
dc8c34
 								bval.bv_len = strlen(unhashed_pwd);
dc8c34
 								bv[0] = &bval;
dc8c34
 								bv[1] = NULL;
dc8c34
-
dc8c34
 								/*
dc8c34
 								 *  Compare the clear text unhashed password, to the encoded password
dc8c34
 								 *  provided by the client.
dc8c34
 								 */
dc8c34
-								unhashed_pwsp = pw_val2scheme( unhashed_pwd, NULL, 1 );
dc8c34
+								unhashed_pwsp = pw_val2scheme( (char *)unhashed_pwd, NULL, 1 );
dc8c34
 								if(strcmp(unhashed_pwsp->pws_name, "CLEAR") == 0){
dc8c34
-									if((*(pwsp->pws_cmp))(unhashed_pwd , valpwd) == 0 ){
dc8c34
+									if((*(pwsp->pws_cmp))((char *)unhashed_pwd , valpwd) == 0 ){
dc8c34
 										/* match, add the delete mod for this particular unhashed userpassword */
dc8c34
-										valuearray_init_bervalarray(bv, &va);
dc8c34
-										slapi_mods_add_mod_values(&smods, pw_mod->mod_op, unhashed_pw_attr, va);
dc8c34
-										valuearray_free(&va);
dc8c34
-										free_pw_scheme( unhashed_pwsp );
dc8c34
+										if (SLAPD_UNHASHED_PW_OFF != config_get_unhashed_pw_switch()) {
dc8c34
+										    valuearray_init_bervalarray(bv, &va);
dc8c34
+										    slapi_mods_add_mod_values(&smods, pw_mod->mod_op, unhashed_pw_attr, va);
dc8c34
+										    valuearray_free(&va);
dc8c34
+										    free_pw_scheme( unhashed_pwsp );
dc8c34
+										}
dc8c34
 										break;
dc8c34
 									}
dc8c34
 								} else {
dc8c34
 									/*
dc8c34
 									 *  We have a hashed unhashed_userpassword!  We must delete it.
dc8c34
 									 */
dc8c34
-									valuearray_init_bervalarray(bv, &va);
dc8c34
-									slapi_mods_add_mod_values(&smods, pw_mod->mod_op, unhashed_pw_attr, va);
dc8c34
-									valuearray_free(&va);
dc8c34
+									if (SLAPD_UNHASHED_PW_OFF != config_get_unhashed_pw_switch()) {
dc8c34
+										valuearray_init_bervalarray(bv, &va);
dc8c34
+										slapi_mods_add_mod_values(&smods, pw_mod->mod_op, unhashed_pw_attr, va);
dc8c34
+										valuearray_free(&va);
dc8c34
+									}
dc8c34
 								}
dc8c34
 								free_pw_scheme( unhashed_pwsp );
dc8c34
 							}
dc8c34
@@ -958,13 +963,13 @@ static void op_shared_modify (Slapi_PBlock *pb, int pw_change, char *old_pw)
dc8c34
 				if (remove_unhashed_pw && !slapi_entry_attr_find(e, unhashed_pw_attr, &a)){
dc8c34
 					slapi_mods_add_mod_values(&smods, pw_mod->mod_op,unhashed_pw_attr, va);
dc8c34
 				}
dc8c34
-			} else {
dc8c34
-				/* add pseudo password attribute - only if it's value is clear text */
dc8c34
+			} else if (SLAPD_UNHASHED_PW_OFF != config_get_unhashed_pw_switch()) {
dc8c34
+				/* add pseudo password attribute */
dc8c34
 				valuearray_init_bervalarray_unhashed_only(pw_mod->mod_bvalues, &va);
dc8c34
 				if(va && va[0]){
dc8c34
 					slapi_mods_add_mod_values(&smods, pw_mod->mod_op, unhashed_pw_attr, va);
dc8c34
 				}
dc8c34
-                                valuearray_free(&va);
dc8c34
+				valuearray_free(&va);
dc8c34
 			}
dc8c34
 
dc8c34
 			/* Init new value array for hashed value */
dc8c34
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
dc8c34
index a7367a7..bef19d1 100644
dc8c34
--- a/ldap/servers/slapd/opshared.c
dc8c34
+++ b/ldap/servers/slapd/opshared.c
dc8c34
@@ -52,10 +52,7 @@
dc8c34
 static void compute_limits (Slapi_PBlock *pb);
dc8c34
 
dc8c34
 /* attributes that no clients are allowed to add or modify */
dc8c34
-/* PSEUDO_ATTR_UNHASHEDUSERPASSWORD used to be in protected_attrs_all. 
dc8c34
- * Now it's moved to back-ldbm/id2entry.c to share it among repl masters.
dc8c34
- * (bz 182507)*/
dc8c34
-static char *protected_attrs_all [] = { NULL };
dc8c34
+static char *protected_attrs_all [] = { PSEUDO_ATTR_UNHASHEDUSERPASSWORD, NULL };
dc8c34
 static char *pwpolicy_lock_attrs_all [] = { "passwordRetryCount",
dc8c34
                                             "retryCountResetTime",
dc8c34
                                             "accountUnlockTime",
dc8c34
@@ -70,30 +67,26 @@ int op_shared_is_allowed_attr (const char *attr_name, int replicated_op)
dc8c34
     int                 i;
dc8c34
     slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
dc8c34
 
dc8c34
-    /* check list of attributes that no client is allowed to specify */
dc8c34
-    for (i = 0; protected_attrs_all[i]; i ++)
dc8c34
-    {
dc8c34
-        if (strcasecmp (attr_name, protected_attrs_all[i]) == 0)
dc8c34
-        {
dc8c34
-            /* this attribute is not allowed */
dc8c34
-            return 0;
dc8c34
-        }
dc8c34
-    }
dc8c34
-
dc8c34
     /* ONREPL - should allow backends to plugin here to specify 
dc8c34
                 attributes that are not allowed */
dc8c34
 
dc8c34
-    if (!replicated_op)
dc8c34
-    {
dc8c34
-        /*
dc8c34
-         * check to see if attribute is marked as one clients can't modify
dc8c34
-         */
dc8c34
+    if (!replicated_op) {
dc8c34
         struct asyntaxinfo    *asi;
dc8c34
         int                    no_user_mod = 0;
dc8c34
 
dc8c34
+        /* check list of attributes that no client is allowed to specify */
dc8c34
+        for (i = 0; protected_attrs_all[i]; i ++) {
dc8c34
+            if (strcasecmp (attr_name, protected_attrs_all[i]) == 0) {
dc8c34
+                /* this attribute is not allowed */
dc8c34
+                return 0;
dc8c34
+            }
dc8c34
+        }
dc8c34
+        /*
dc8c34
+         * check to see if attribute is marked as one clients can't modify
dc8c34
+         */
dc8c34
         asi = attr_syntax_get_by_name( attr_name, 0 );
dc8c34
         if ( NULL != asi &&
dc8c34
-                0 != ( asi->asi_flags & SLAPI_ATTR_FLAG_NOUSERMOD ))
dc8c34
+             0 != ( asi->asi_flags & SLAPI_ATTR_FLAG_NOUSERMOD ))
dc8c34
         {
dc8c34
             /* this attribute is not allowed */
dc8c34
             no_user_mod = 1;
dc8c34
@@ -187,7 +180,7 @@ modify_update_last_modified_attr(Slapi_PBlock *pb, Slapi_Mods *smods)
dc8c34
             /* anonymous bind */
dc8c34
             bv.bv_val = "";
dc8c34
             bv.bv_len = strlen(bv.bv_val);
dc8c34
-   	    } else {
dc8c34
+        } else {
dc8c34
             bv.bv_val = binddn;
dc8c34
             bv.bv_len = strlen(bv.bv_val);
dc8c34
         }
dc8c34
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
dc8c34
index da9c925..c497c14 100644
dc8c34
--- a/ldap/servers/slapd/proto-slap.h
dc8c34
+++ b/ldap/servers/slapd/proto-slap.h
dc8c34
@@ -403,6 +403,7 @@ int config_set_malloc_mmap_threshold(const char *attrname, char *value, char *er
dc8c34
 
dc8c34
 int config_set_ndn_cache_enabled(const char *attrname, char *value, char *errorbuf, int apply);
dc8c34
 int config_set_ndn_cache_max_size(const char *attrname, char *value, char *errorbuf, int apply);
dc8c34
+int config_set_unhashed_pw_switch(const char *attrname, char *value, char *errorbuf, int apply);
dc8c34
 
dc8c34
 
dc8c34
 #if !defined(_WIN32) && !defined(AIX)
dc8c34
@@ -572,6 +573,7 @@ int config_get_malloc_mmap_threshold();
dc8c34
 int config_get_ndn_cache_count();
dc8c34
 size_t config_get_ndn_cache_size();
dc8c34
 int config_get_ndn_cache_enabled();
dc8c34
+int config_get_unhashed_pw_switch();
dc8c34
 PLHashNumber hashNocaseString(const void *key);
dc8c34
 PRIntn hashNocaseCompare(const void *v1, const void *v2);
dc8c34
 
dc8c34
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
dc8c34
index 70e8a51..c298033 100644
dc8c34
--- a/ldap/servers/slapd/slap.h
dc8c34
+++ b/ldap/servers/slapd/slap.h
dc8c34
@@ -306,9 +306,6 @@ typedef void	(*VFPV)(); /* takes undefined arguments */
dc8c34
 
dc8c34
 #define ATTR_NETSCAPEMDSUFFIX "netscapemdsuffix"
dc8c34
 
dc8c34
-/* Used to make unhashed passwords available to plugins. */
dc8c34
-#define	PSEUDO_ATTR_UNHASHEDUSERPASSWORD	"unhashed#user#password"
dc8c34
-
dc8c34
 #define REFERRAL_REMOVE_CMD "remove"
dc8c34
 
dc8c34
 /* Filenames for DSE storage */
dc8c34
@@ -339,6 +336,8 @@ typedef void	(*VFPV)(); /* takes undefined arguments */
dc8c34
 #define SLAPD_VALIDATE_CERT_ON          1
dc8c34
 #define SLAPD_VALIDATE_CERT_WARN        2
dc8c34
 
dc8c34
+typedef int slapi_onoff_t;
dc8c34
+
dc8c34
 struct subfilt {
dc8c34
 	char	*sf_type;
dc8c34
 	char	*sf_initial;
dc8c34
@@ -1891,6 +1890,7 @@ typedef struct _slapdEntryPoints {
dc8c34
 #define CONFIG_ERRORLOG_LOGGING_ENABLED_ATTRIBUTE "nsslapd-errorlog-logging-enabled"
dc8c34
 #define CONFIG_AUDITLOG_LOGGING_ENABLED_ATTRIBUTE "nsslapd-auditlog-logging-enabled"
dc8c34
 #define CONFIG_AUDITLOG_LOGGING_HIDE_UNHASHED_PW "nsslapd-auditlog-logging-hide-unhashed-pw"
dc8c34
+#define CONFIG_UNHASHED_PW_SWITCH_ATTRIBUTE "nsslapd-unhashed-pw-switch"
dc8c34
 #define CONFIG_ROOTDN_ATTRIBUTE "nsslapd-rootdn"
dc8c34
 #define CONFIG_ROOTPW_ATTRIBUTE "nsslapd-rootpw"
dc8c34
 #define CONFIG_ROOTPWSTORAGESCHEME_ATTRIBUTE "nsslapd-rootpwstoragescheme"
dc8c34
@@ -2277,7 +2277,7 @@ typedef struct _slapdFrontendConfig {
dc8c34
   PRInt64 disk_threshold;
dc8c34
   int disk_grace_period;
dc8c34
   int disk_logging_critical;
dc8c34
-
dc8c34
+  slapi_onoff_t unhashed_pw_switch;	/* switch to on/off/nolog unhashed pw */
dc8c34
   int ignore_time_skew;
dc8c34
 #if defined(LINUX)
dc8c34
   int malloc_mxfast;            /* mallopt M_MXFAST */
dc8c34
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
dc8c34
index e02127d..5c737ad 100644
dc8c34
--- a/ldap/servers/slapd/slapi-plugin.h
dc8c34
+++ b/ldap/servers/slapd/slapi-plugin.h
dc8c34
@@ -7057,6 +7057,14 @@ char **slapi_str2charray_ext( char *str, char *brkstr, int allow_dups );
dc8c34
 #endif
dc8c34
 #endif
dc8c34
 
dc8c34
+/* Used to make unhashed passwords available to plugins. */
dc8c34
+#define	PSEUDO_ATTR_UNHASHEDUSERPASSWORD	"unhashed#user#password"
dc8c34
+
dc8c34
+/* Unhashed password */
dc8c34
+#define SLAPD_UNHASHED_PW_OFF           0
dc8c34
+#define SLAPD_UNHASHED_PW_ON            1
dc8c34
+#define SLAPD_UNHASHED_PW_NOLOG         2
dc8c34
+
dc8c34
 /**
dc8c34
  * Set given "type: value" to the plugin default config entry
dc8c34
  * (cn=plugin default config,cn=config) unless the same "type: value" pair
dc8c34
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
dc8c34
index 18f0e94..9a4e339 100644
dc8c34
--- a/ldap/servers/slapd/slapi-private.h
dc8c34
+++ b/ldap/servers/slapd/slapi-private.h
dc8c34
@@ -816,6 +816,7 @@ int pw_rever_decode(char *cipher, char **plain, const char * attr_name);
dc8c34
 /* config routines */
dc8c34
 
dc8c34
 int slapi_config_get_readonly();
dc8c34
+int slapi_config_get_unhashed_pw_switch();
dc8c34
 
dc8c34
 /*
dc8c34
  * charray.c
dc8c34
diff --git a/ldap/servers/slapd/util.c b/ldap/servers/slapd/util.c
dc8c34
index 7a753f8..8c0b7ee 100644
dc8c34
--- a/ldap/servers/slapd/util.c
dc8c34
+++ b/ldap/servers/slapd/util.c
dc8c34
@@ -325,13 +325,15 @@ int slapi_mods2entry (Slapi_Entry **e, const char *idn, LDAPMod **iattrs)
dc8c34
     return rc;
dc8c34
 }
dc8c34
 
dc8c34
-int slapi_entry2mods (const Slapi_Entry *e, char **dn, LDAPMod ***attrs)
dc8c34
+int
dc8c34
+slapi_entry2mods (const Slapi_Entry *e, char **dn, LDAPMod ***attrs)
dc8c34
 {
dc8c34
 	Slapi_Mods smods;
dc8c34
 	Slapi_Attr *attr;
dc8c34
 	Slapi_Value **va;
dc8c34
 	char *type;
dc8c34
 	int rc;
dc8c34
+	int unhashed_pw_on = (SLAPD_UNHASHED_PW_ON == config_get_unhashed_pw_switch());
dc8c34
 
dc8c34
 	PR_ASSERT (e && attrs);
dc8c34
 
dc8c34
@@ -343,8 +345,11 @@ int slapi_entry2mods (const Slapi_Entry *e, char **dn, LDAPMod ***attrs)
dc8c34
 	while (rc == 0)
dc8c34
 	{
dc8c34
 		if ( NULL != ( va = attr_get_present_values( attr ))) {
dc8c34
-			slapi_attr_get_type(attr, &type);		
dc8c34
-			slapi_mods_add_mod_values(&smods, LDAP_MOD_ADD, type, va );
dc8c34
+			slapi_attr_get_type(attr, &type);
dc8c34
+			if (unhashed_pw_on || strcasecmp(type, PSEUDO_ATTR_UNHASHEDUSERPASSWORD)) {
dc8c34
+				/* SLAPD_UNHASHED_PW_ON or type is not unhashed pw */
dc8c34
+				slapi_mods_add_mod_values(&smods, LDAP_MOD_ADD, type, va );
dc8c34
+			}
dc8c34
 		}
dc8c34
 		rc = slapi_entry_next_attr(e, attr, &attr);
dc8c34
 	}
dc8c34
-- 
dc8c34
1.9.3
dc8c34