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

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