Blame SOURCES/0070-Ticket-49379-Allowed-sasl-mapping-requires-restart.patch

b69e47
From 8a7b47602acc910d2f64439b81af3299b60359c8 Mon Sep 17 00:00:00 2001
b69e47
From: Mark Reynolds <mreynolds@redhat.com>
b69e47
Date: Mon, 18 Sep 2017 10:35:20 -0400
b69e47
Subject: [PATCH] Ticket 49379 - Allowed sasl mapping requires restart
b69e47
b69e47
Bug Description:  If allowed sasl mechanisms are configured, and the server is
b69e47
                  restarted, trying to add new sasl mechanisms does not get applied
b69e47
                  until the server is restarted again. [1]
b69e47
b69e47
                  We were also overwriting memory when we stripped the commas from
b69e47
                  the allowed machanism list.  THis lead to the allowed mechanisms
b69e47
                  to get truncated,and permanently lose certain mechs. [2]
b69e47
b69e47
                  A crash with PLAIN sasl mechanism was also found. [3]
b69e47
b69e47
Fix Description:  To address allowed sasl mechs, we no longer explicitly the mechanisms
b69e47
                  during the sasl_init at server startup.  Instead we check the allowed
b69e47
                  list ourselves during a bind. [1]
b69e47
b69e47
                  When setting the allowed sasl mechs, make a copy of the value to
b69e47
                  apply the changes to(removing coamms), and do not change the original
b69e47
                  value as it's still being used. [2]
b69e47
b69e47
                  The crash when using sasl PLAIN was due to unlocking a rwlock that
b69e47
                  was not locked. [3]
b69e47
b69e47
https://pagure.io/389-ds-base/issue/49379
b69e47
b69e47
Reviewed by: tbordaz(Thanks!)
b69e47
b69e47
(cherry picked from commit c78f41db31752a99aadd6abcbf7a1d852a8e7931)
b69e47
---
b69e47
 dirsrvtests/tests/suites/sasl/allowed_mechs.py | 114 ++++++++++++++++++++++--
b69e47
 dirsrvtests/tests/suites/sasl/plain.py         |  10 ++-
b69e47
 ldap/servers/slapd/libglobs.c                  |  23 ++---
b69e47
 ldap/servers/slapd/saslbind.c                  | 116 +++++++++++++------------
b69e47
 4 files changed, 187 insertions(+), 76 deletions(-)
b69e47
b69e47
diff --git a/dirsrvtests/tests/suites/sasl/allowed_mechs.py b/dirsrvtests/tests/suites/sasl/allowed_mechs.py
b69e47
index 7958db4..5b1b92c 100644
b69e47
--- a/dirsrvtests/tests/suites/sasl/allowed_mechs.py
b69e47
+++ b/dirsrvtests/tests/suites/sasl/allowed_mechs.py
b69e47
@@ -8,45 +8,141 @@
b69e47
 #
b69e47
 
b69e47
 import pytest
b69e47
-import ldap
b69e47
-
b69e47
-import time
b69e47
-
b69e47
+import os
b69e47
 from lib389.topologies import topology_st
b69e47
 
b69e47
+
b69e47
 def test_sasl_allowed_mechs(topology_st):
b69e47
+    """Test the alloweed sasl mechanism feature
b69e47
+
b69e47
+    :ID: ab7d9f86-8cfe-48c3-8baa-739e599f006a
b69e47
+    :feature: Allowed sasl mechanisms
b69e47
+    :steps: 1.  Get the default list of mechanisms
b69e47
+            2.  Set allowed mechanism PLAIN, and verify it's correctly listed
b69e47
+            3.  Restart server, and verify list is still correct
b69e47
+            4.  Test EXTERNAL is properly listed
b69e47
+            5.  Add GSSAPI to the existing list, and verify it's correctly listed
b69e47
+            6.  Restart server and verify list is still correct
b69e47
+            7.  Add ANONYMOUS to the existing list, and veirfy it's correctly listed
b69e47
+            8.  Restart server and verify list is still correct
b69e47
+            9.  Remove GSSAPI and verify it's correctly listed
b69e47
+            10. Restart server and verify list is still correct
b69e47
+            11. Reset allowed list to nothing, verify "all" the mechanisms are returned
b69e47
+            12. Restart server and verify list is still correct
b69e47
+
b69e47
+    :expectedresults: The supported mechanisms supported what is set for the allowed
b69e47
+                      mechanisms
b69e47
+    """
b69e47
     standalone = topology_st.standalone
b69e47
 
b69e47
     # Get the supported mechs. This should contain PLAIN, GSSAPI, EXTERNAL at least
b69e47
+    standalone.log.info("Test we have some of the default mechanisms")
b69e47
     orig_mechs = standalone.rootdse.supported_sasl()
b69e47
     print(orig_mechs)
b69e47
     assert('GSSAPI' in orig_mechs)
b69e47
     assert('PLAIN' in orig_mechs)
b69e47
     assert('EXTERNAL' in orig_mechs)
b69e47
 
b69e47
-    # Now edit the supported mechs. CHeck them again.
b69e47
+    # Now edit the supported mechs. Check them again.
b69e47
+    standalone.log.info("Edit mechanisms to allow just PLAIN")
b69e47
     standalone.config.set('nsslapd-allowed-sasl-mechanisms', 'PLAIN')
b69e47
+    limit_mechs = standalone.rootdse.supported_sasl()
b69e47
+    assert('PLAIN' in limit_mechs)
b69e47
+    assert('EXTERNAL' in limit_mechs)  # Should always be in the allowed list, even if not set.
b69e47
+    assert('GSSAPI' not in limit_mechs)  # Should not be there!
b69e47
 
b69e47
+    # Restart the server a few times and make sure nothing changes
b69e47
+    standalone.log.info("Restart server and make sure we still have correct allowed mechs")
b69e47
+    standalone.restart()
b69e47
+    standalone.restart()
b69e47
     limit_mechs = standalone.rootdse.supported_sasl()
b69e47
     assert('PLAIN' in limit_mechs)
b69e47
-    # Should always be in the allowed list, even if not set.
b69e47
     assert('EXTERNAL' in limit_mechs)
b69e47
-    # Should not be there!
b69e47
     assert('GSSAPI' not in limit_mechs)
b69e47
 
b69e47
+    # Set EXTERNAL, even though its always supported
b69e47
+    standalone.log.info("Edit mechanisms to allow just PLAIN and EXTERNAL")
b69e47
     standalone.config.set('nsslapd-allowed-sasl-mechanisms', 'PLAIN, EXTERNAL')
b69e47
+    limit_mechs = standalone.rootdse.supported_sasl()
b69e47
+    assert('PLAIN' in limit_mechs)
b69e47
+    assert('EXTERNAL' in limit_mechs)
b69e47
+    assert('GSSAPI' not in limit_mechs)
b69e47
+
b69e47
+    # Now edit the supported mechs. Check them again.
b69e47
+    standalone.log.info("Edit mechanisms to allow just PLAIN and GSSAPI")
b69e47
+    standalone.config.set('nsslapd-allowed-sasl-mechanisms', 'PLAIN, GSSAPI')
b69e47
+    limit_mechs = standalone.rootdse.supported_sasl()
b69e47
+    assert('PLAIN' in limit_mechs)
b69e47
+    assert('EXTERNAL' in limit_mechs)
b69e47
+    assert('GSSAPI' in limit_mechs)
b69e47
+    assert(len(limit_mechs) == 3)
b69e47
+
b69e47
+    # Restart server twice and make sure the allowed list is the same
b69e47
+    standalone.restart()
b69e47
+    standalone.restart()  # For ticket 49379 (test double restart)
b69e47
+    limit_mechs = standalone.rootdse.supported_sasl()
b69e47
+    assert('PLAIN' in limit_mechs)
b69e47
+    assert('EXTERNAL' in limit_mechs)
b69e47
+    assert('GSSAPI' in limit_mechs)
b69e47
+    assert(len(limit_mechs) == 3)
b69e47
+
b69e47
+    # Add ANONYMOUS to the supported mechs and test again.
b69e47
+    standalone.log.info("Edit mechanisms to allow just PLAIN, GSSAPI, and ANONYMOUS")
b69e47
+    standalone.config.set('nsslapd-allowed-sasl-mechanisms', 'PLAIN, GSSAPI, ANONYMOUS')
b69e47
+    limit_mechs = standalone.rootdse.supported_sasl()
b69e47
+    assert('PLAIN' in limit_mechs)
b69e47
+    assert('EXTERNAL' in limit_mechs)
b69e47
+    assert('GSSAPI' in limit_mechs)
b69e47
+    assert('ANONYMOUS' in limit_mechs)
b69e47
+    assert(len(limit_mechs) == 4)
b69e47
+
b69e47
+    # Restart server and make sure the allowed list is the same
b69e47
+    standalone.restart()
b69e47
+    standalone.restart()  # For ticket 49379 (test double restart)
b69e47
+    limit_mechs = standalone.rootdse.supported_sasl()
b69e47
+    assert('PLAIN' in limit_mechs)
b69e47
+    assert('EXTERNAL' in limit_mechs)
b69e47
+    assert('GSSAPI' in limit_mechs)
b69e47
+    assert('ANONYMOUS' in limit_mechs)
b69e47
+    assert(len(limit_mechs) == 4)
b69e47
 
b69e47
+    # Remove GSSAPI
b69e47
+    standalone.log.info("Edit mechanisms to allow just PLAIN and ANONYMOUS")
b69e47
+    standalone.config.set('nsslapd-allowed-sasl-mechanisms', 'PLAIN, ANONYMOUS')
b69e47
     limit_mechs = standalone.rootdse.supported_sasl()
b69e47
     assert('PLAIN' in limit_mechs)
b69e47
     assert('EXTERNAL' in limit_mechs)
b69e47
-    # Should not be there!
b69e47
     assert('GSSAPI' not in limit_mechs)
b69e47
+    assert('ANONYMOUS' in limit_mechs)
b69e47
+    assert(len(limit_mechs) == 3)
b69e47
+
b69e47
+    # Restart server and make sure the allowed list is the same
b69e47
+    standalone.restart()
b69e47
+    limit_mechs = standalone.rootdse.supported_sasl()
b69e47
+    assert('PLAIN' in limit_mechs)
b69e47
+    assert('EXTERNAL' in limit_mechs)
b69e47
+    assert('GSSAPI' not in limit_mechs)
b69e47
+    assert('ANONYMOUS' in limit_mechs)
b69e47
+    assert(len(limit_mechs) == 3)
b69e47
 
b69e47
     # Do a config reset
b69e47
+    standalone.log.info("Reset allowed mechaisms")
b69e47
     standalone.config.reset('nsslapd-allowed-sasl-mechanisms')
b69e47
 
b69e47
     # check the supported list is the same as our first check.
b69e47
+    standalone.log.info("Check that we have the original set of mechanisms")
b69e47
     final_mechs = standalone.rootdse.supported_sasl()
b69e47
-    print(final_mechs)
b69e47
     assert(set(final_mechs) == set(orig_mechs))
b69e47
 
b69e47
+    # Check it after a restart
b69e47
+    standalone.log.info("Check that we have the original set of mechanisms after a restart")
b69e47
+    standalone.restart()
b69e47
+    final_mechs = standalone.rootdse.supported_sasl()
b69e47
+    assert(set(final_mechs) == set(orig_mechs))
b69e47
+
b69e47
+
b69e47
+if __name__ == '__main__':
b69e47
+    # Run isolated
b69e47
+    # -s for DEBUG mode
b69e47
+    CURRENT_FILE = os.path.realpath(__file__)
b69e47
+    pytest.main("-s %s" % CURRENT_FILE)
b69e47
diff --git a/dirsrvtests/tests/suites/sasl/plain.py b/dirsrvtests/tests/suites/sasl/plain.py
b69e47
index 91ccb02..6bf39a8 100644
b69e47
--- a/dirsrvtests/tests/suites/sasl/plain.py
b69e47
+++ b/dirsrvtests/tests/suites/sasl/plain.py
b69e47
@@ -15,9 +15,11 @@ from lib389.topologies import topology_st
b69e47
 from lib389.utils import *
b69e47
 from lib389.sasl import PlainSASL
b69e47
 from lib389.idm.services import ServiceAccounts
b69e47
+from lib389._constants import (SECUREPORT_STANDALONE1, DEFAULT_SUFFIX)
b69e47
 
b69e47
 log = logging.getLogger(__name__)
b69e47
 
b69e47
+
b69e47
 def test_sasl_plain(topology_st):
b69e47
 
b69e47
     standalone = topology_st.standalone
b69e47
@@ -38,7 +40,7 @@ def test_sasl_plain(topology_st):
b69e47
     standalone.rsa.create()
b69e47
     # Set the secure port and nsslapd-security
b69e47
     # Could this fail with selinux?
b69e47
-    standalone.config.set('nsslapd-secureport', '%s' % SECUREPORT_STANDALONE1 )
b69e47
+    standalone.config.set('nsslapd-secureport', '%s' % SECUREPORT_STANDALONE1)
b69e47
     standalone.config.set('nsslapd-security', 'on')
b69e47
     # Do we need to restart to allow starttls?
b69e47
     standalone.restart()
b69e47
@@ -65,12 +67,14 @@ def test_sasl_plain(topology_st):
b69e47
     # I can not solve. I think it's leaking state across connections in start_tls_s?
b69e47
 
b69e47
     # Check that it works with TLS
b69e47
-    conn = standalone.openConnection(saslmethod='PLAIN', sasltoken=auth_tokens, starttls=True, connOnly=True, certdir=standalone.get_cert_dir(), reqcert=ldap.OPT_X_TLS_NEVER)
b69e47
+    conn = standalone.openConnection(saslmethod='PLAIN', sasltoken=auth_tokens, starttls=True, connOnly=True,
b69e47
+                                    certdir=standalone.get_cert_dir(), reqcert=ldap.OPT_X_TLS_NEVER)
b69e47
     conn.close()
b69e47
 
b69e47
     # Check that it correct fails our bind if we don't have the password.
b69e47
     auth_tokens = PlainSASL("dn:%s" % sa.dn, 'password-wrong')
b69e47
     with pytest.raises(ldap.INVALID_CREDENTIALS):
b69e47
-        standalone.openConnection(saslmethod='PLAIN', sasltoken=auth_tokens, starttls=False, connOnly=True, certdir=standalone.get_cert_dir(), reqcert=ldap.OPT_X_TLS_NEVER)
b69e47
+        standalone.openConnection(saslmethod='PLAIN', sasltoken=auth_tokens, starttls=True, connOnly=True,
b69e47
+                                  certdir=standalone.get_cert_dir(), reqcert=ldap.OPT_X_TLS_NEVER)
b69e47
 
b69e47
     # Done!
b69e47
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
b69e47
index bb51827..2fb4bab 100644
b69e47
--- a/ldap/servers/slapd/libglobs.c
b69e47
+++ b/ldap/servers/slapd/libglobs.c
b69e47
@@ -7137,22 +7137,25 @@ config_set_allowed_sasl_mechs(const char *attrname, char *value, char *errorbuf,
b69e47
 
b69e47
     /* During a reset, the value is "", so we have to handle this case. */
b69e47
     if (strcmp(value, "") != 0) {
b69e47
-        /* cyrus sasl doesn't like comma separated lists */
b69e47
-        remove_commas(value);
b69e47
+        char *nval = slapi_ch_strdup(value);
b69e47
 
b69e47
-        if(invalid_sasl_mech(value)){
b69e47
-            slapi_log_err(SLAPI_LOG_ERR,"config_set_allowed_sasl_mechs",
b69e47
-                    "Invalid value/character for sasl mechanism (%s).  Use ASCII "
b69e47
-                    "characters, upto 20 characters, that are upper-case letters, "
b69e47
-                    "digits, hyphens, or underscores\n", value);
b69e47
+        /* cyrus sasl doesn't like comma separated lists */
b69e47
+        remove_commas(nval);
b69e47
+
b69e47
+        if (invalid_sasl_mech(nval)) {
b69e47
+            slapi_log_err(SLAPI_LOG_ERR, "config_set_allowed_sasl_mechs",
b69e47
+                          "Invalid value/character for sasl mechanism (%s).  Use ASCII "
b69e47
+                          "characters, upto 20 characters, that are upper-case letters, "
b69e47
+                          "digits, hyphens, or underscores\n",
b69e47
+                          nval);
b69e47
+            slapi_ch_free_string(&nval);
b69e47
             return LDAP_UNWILLING_TO_PERFORM;
b69e47
         }
b69e47
-
b69e47
         CFG_LOCK_WRITE(slapdFrontendConfig);
b69e47
         slapi_ch_free_string(&slapdFrontendConfig->allowed_sasl_mechs);
b69e47
         slapi_ch_array_free(slapdFrontendConfig->allowed_sasl_mechs_array);
b69e47
-        slapdFrontendConfig->allowed_sasl_mechs = slapi_ch_strdup(value);
b69e47
-        slapdFrontendConfig->allowed_sasl_mechs_array = slapi_str2charray_ext(value, " ", 0);
b69e47
+        slapdFrontendConfig->allowed_sasl_mechs = nval;
b69e47
+        slapdFrontendConfig->allowed_sasl_mechs_array = slapi_str2charray_ext(nval, " ", 0);
b69e47
         CFG_UNLOCK_WRITE(slapdFrontendConfig);
b69e47
     } else {
b69e47
         /* If this value is "", we need to set the list to *all* possible mechs */
b69e47
diff --git a/ldap/servers/slapd/saslbind.c b/ldap/servers/slapd/saslbind.c
b69e47
index 134f5aa..03e2a97 100644
b69e47
--- a/ldap/servers/slapd/saslbind.c
b69e47
+++ b/ldap/servers/slapd/saslbind.c
b69e47
@@ -169,8 +169,6 @@ static int ids_sasl_getopt(
b69e47
         }
b69e47
     } else if (strcasecmp(option, "auxprop_plugin") == 0) {
b69e47
         *result = "iDS";
b69e47
-    } else if (strcasecmp(option, "mech_list") == 0){
b69e47
-        *result = config_get_allowed_sasl_mechs();
b69e47
     }
b69e47
 
b69e47
     if (*result) *len = strlen(*result);
b69e47
@@ -572,12 +570,8 @@ static int ids_sasl_userdb_checkpass(sasl_conn_t *conn, void *context, const cha
b69e47
         slapi_pblock_set(pb, SLAPI_BIND_METHOD, &method);
b69e47
         /* Feed it to pw_verify_be_dn */
b69e47
         bind_result = pw_verify_be_dn(pb, &referral);
b69e47
-        /* Now check the result, and unlock be if needed. */
b69e47
-        if (bind_result == SLAPI_BIND_SUCCESS || bind_result == SLAPI_BIND_ANONYMOUS) {
b69e47
-            Slapi_Backend *be = NULL;
b69e47
-            slapi_pblock_get(pb, SLAPI_BACKEND, &be);
b69e47
-            slapi_be_Unlock(be);
b69e47
-        } else if (bind_result == SLAPI_BIND_REFERRAL) {
b69e47
+        /* Now check the result. */
b69e47
+        if (bind_result == SLAPI_BIND_REFERRAL) {
b69e47
             /* If we have a referral do we ignore it for sasl? */
b69e47
             slapi_entry_free(referral);
b69e47
         }
b69e47
@@ -760,22 +754,25 @@ char **ids_sasl_listmech(Slapi_PBlock *pb)
b69e47
     sup_ret = slapi_get_supported_saslmechanisms_copy();
b69e47
 
b69e47
     /* If we have a connection, get the provided list from SASL */
b69e47
-    if (pb->pb_conn != NULL) {
b69e47
-        sasl_conn = (sasl_conn_t*)pb->pb_conn->c_sasl_conn;
b69e47
-
b69e47
-        /* sasl library mechanisms are connection dependent */
b69e47
-        PR_EnterMonitor(pb->pb_conn->c_mutex);
b69e47
-        if (sasl_listmech(sasl_conn,
b69e47
-                          NULL,     /* username */
b69e47
-                          "", ",", "",
b69e47
-                          &str, NULL, NULL) == SASL_OK) {
b69e47
-            slapi_log_err(SLAPI_LOG_TRACE, "ids_sasl_listmech", "sasl library mechs: %s\n", str);
b69e47
-            /* merge into result set */
b69e47
-            dupstr = slapi_ch_strdup(str);
b69e47
-            others = slapi_str2charray_ext(dupstr, ",", 0 /* don't list duplicate mechanisms */);
b69e47
-            charray_merge(&sup_ret, others, 1);
b69e47
-            charray_free(others);
b69e47
-            slapi_ch_free((void**)&dupstr);
b69e47
+    if (pb_conn != NULL) {
b69e47
+        sasl_conn = (sasl_conn_t*)pb_conn->c_sasl_conn;
b69e47
+        if (sasl_conn != NULL) {
b69e47
+            /* sasl library mechanisms are connection dependent */
b69e47
+            PR_EnterMonitor(pb_conn->c_mutex);
b69e47
+            if (sasl_listmech(sasl_conn,
b69e47
+                              NULL,     /* username */
b69e47
+                              "", ",", "",
b69e47
+                              &str, NULL, NULL) == SASL_OK) {
b69e47
+                slapi_log_err(SLAPI_LOG_TRACE, "ids_sasl_listmech", "sasl library mechs: %s\n", str);
b69e47
+                /* merge into result set */
b69e47
+                dupstr = slapi_ch_strdup(str);
b69e47
+                others = slapi_str2charray_ext(dupstr, ",", 0 /* don't list duplicate mechanisms */);
b69e47
+
b69e47
+                charray_merge(&sup_ret, others, 1);
b69e47
+                charray_free(others);
b69e47
+                slapi_ch_free((void**)&dupstr);
b69e47
+            }
b69e47
+            PR_ExitMonitor(pb_conn->c_mutex);
b69e47
         }
b69e47
         PR_ExitMonitor(pb->pb_conn->c_mutex);
b69e47
     }
b69e47
@@ -785,7 +782,7 @@ char **ids_sasl_listmech(Slapi_PBlock *pb)
b69e47
 
b69e47
     /* Remove any content that isn't in the allowed list */
b69e47
     if (config_ret != NULL) {
b69e47
-        /* Get the set of supported mechs in the insection of the two */
b69e47
+        /* Get the set of supported mechs in the intersection of the two */
b69e47
         ret = charray_intersection(sup_ret, config_ret);
b69e47
         charray_free(sup_ret);
b69e47
         charray_free(config_ret);
b69e47
@@ -816,41 +813,52 @@ char **ids_sasl_listmech(Slapi_PBlock *pb)
b69e47
 static int
b69e47
 ids_sasl_mech_supported(Slapi_PBlock *pb, const char *mech)
b69e47
 {
b69e47
-  int i, ret = 0;
b69e47
-  char **mechs;
b69e47
-  char *dupstr;
b69e47
-  const char *str;
b69e47
-  int sasl_result = 0;
b69e47
-  sasl_conn_t *sasl_conn = (sasl_conn_t *)pb->pb_conn->c_sasl_conn;
b69e47
-
b69e47
-  slapi_log_err(SLAPI_LOG_TRACE, "ids_sasl_mech_supported", "=>\n");
b69e47
-
b69e47
-
b69e47
-  /* sasl_listmech is not thread-safe - caller must lock pb_conn */
b69e47
-  sasl_result = sasl_listmech(sasl_conn, 
b69e47
-                    NULL,     /* username */
b69e47
-                    "", ",", "",
b69e47
-                    &str, NULL, NULL);
b69e47
-  if (sasl_result != SASL_OK) {
b69e47
-    return 0;
b69e47
-  }
b69e47
+    int i, ret = 0;
b69e47
+    char **mechs;
b69e47
+    char **allowed_mechs = NULL;
b69e47
+    char *dupstr;
b69e47
+    const char *str;
b69e47
+    int sasl_result = 0;
b69e47
+    Connection *pb_conn = NULL;
b69e47
+
b69e47
+    slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
b69e47
+    sasl_conn_t *sasl_conn = (sasl_conn_t *)pb_conn->c_sasl_conn;
b69e47
+    slapi_log_err(SLAPI_LOG_TRACE, "ids_sasl_mech_supported", "=>\n");
b69e47
+
b69e47
+    /* sasl_listmech is not thread-safe - caller must lock pb_conn */
b69e47
+    sasl_result = sasl_listmech(sasl_conn,
b69e47
+                                NULL, /* username */
b69e47
+                                "", ",", "",
b69e47
+                                &str, NULL, NULL);
b69e47
+    if (sasl_result != SASL_OK) {
b69e47
+        return 0;
b69e47
+    }
b69e47
 
b69e47
-  dupstr = slapi_ch_strdup(str);
b69e47
-  mechs = slapi_str2charray(dupstr, ",");
b69e47
+    dupstr = slapi_ch_strdup(str);
b69e47
+    mechs = slapi_str2charray(dupstr, ",");
b69e47
+    allowed_mechs = config_get_allowed_sasl_mechs_array();
b69e47
 
b69e47
-  for (i = 0; mechs[i] != NULL; i++) {
b69e47
-    if (strcasecmp(mech, mechs[i]) == 0) {
b69e47
-      ret = 1;
b69e47
-      break;
b69e47
+    for (i = 0; mechs[i] != NULL; i++) {
b69e47
+        if (strcasecmp(mech, mechs[i]) == 0) {
b69e47
+            if (allowed_mechs) {
b69e47
+                if (charray_inlist(allowed_mechs, (char *)mech) == 0) {
b69e47
+                    ret = 1;
b69e47
+                }
b69e47
+                break;
b69e47
+            } else {
b69e47
+                ret = 1;
b69e47
+                break;
b69e47
+            }
b69e47
+        }
b69e47
     }
b69e47
-  }
b69e47
 
b69e47
-  charray_free(mechs);
b69e47
-  slapi_ch_free((void**)&dupstr);
b69e47
+    charray_free(allowed_mechs);
b69e47
+    charray_free(mechs);
b69e47
+    slapi_ch_free((void **)&dupstr);
b69e47
 
b69e47
-  slapi_log_err(SLAPI_LOG_TRACE, "ids_sasl_mech_supported", "<=\n");
b69e47
+    slapi_log_err(SLAPI_LOG_TRACE, "ids_sasl_mech_supported", "<=\n");
b69e47
 
b69e47
-  return ret;
b69e47
+    return ret;
b69e47
 }
b69e47
 
b69e47
 /*
b69e47
-- 
b69e47
2.9.5
b69e47