zrhoffman / rpms / 389-ds-base

Forked from rpms/389-ds-base 3 years ago
Clone
Blob Blame History Raw
From f60364cd9472edc61e7d327d13dca67eadf0c5b2 Mon Sep 17 00:00:00 2001
From: Simon Pichugin <simon.pichugin@gmail.com>
Date: Tue, 28 Apr 2020 23:44:20 +0200
Subject: [PATCH] Issue 50201 - nsIndexIDListScanLimit accepts any value

Bug Description: Setting of nsIndexIDListScanLimit like
'limit=2 limit=3' are detected and logged in error logs.
But the invalid value is successfully applied in the config entry
and the operation itself is successful.
The impact is limited because the index will be used following
idlistscanlimit rather than invalid definition nsIndexIDListScanLimit.

Fix Description: Print the errors to the user when he tries to add
or to modify index config entry with malformed values.
Change tests accordingly.

https://pagure.io/389-ds-base/issue/50201

Reviewed by: mreynolds, tbordaz (Thanks!)
---
 .../suites/filter/filterscanlimit_test.py     | 87 ++++++++-----------
 ldap/servers/slapd/back-ldbm/instance.c       |  4 +-
 ldap/servers/slapd/back-ldbm/ldbm_attr.c      | 33 ++++++-
 .../slapd/back-ldbm/ldbm_index_config.c       | 59 +++++++++----
 ldap/servers/slapd/back-ldbm/ldif2ldbm.c      |  2 +-
 .../servers/slapd/back-ldbm/proto-back-ldbm.h |  2 +-
 6 files changed, 114 insertions(+), 73 deletions(-)

diff --git a/dirsrvtests/tests/suites/filter/filterscanlimit_test.py b/dirsrvtests/tests/suites/filter/filterscanlimit_test.py
index dd9c6ee4e..0198f6533 100644
--- a/dirsrvtests/tests/suites/filter/filterscanlimit_test.py
+++ b/dirsrvtests/tests/suites/filter/filterscanlimit_test.py
@@ -11,6 +11,7 @@ This script will test different type of Filers.
 """
 
 import os
+import ldap
 import pytest
 
 from lib389._constants import DEFAULT_SUFFIX, PW_DM
@@ -19,11 +20,10 @@ from lib389.idm.user import UserAccounts
 from lib389.idm.organizationalunit import OrganizationalUnits
 from lib389.index import Index
 from lib389.idm.account import Accounts
-from lib389.idm.group import UniqueGroups, Group
+from lib389.idm.group import UniqueGroups
 
 pytestmark = pytest.mark.tier1
 
-
 GIVEN_NAME = 'cn=givenname,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config'
 CN_NAME = 'cn=sn,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config'
 UNIQMEMBER = 'cn=uniquemember,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config'
@@ -39,7 +39,6 @@ LIST_OF_USER_ACCOUNTING = [
     "Judy Wallace",
     "Marcus Ward",
     "Judy McFarland",
-    "Anuj Hall",
     "Gern Triplett",
     "Emanuel Johnson",
     "Brad Walker",
@@ -57,7 +56,6 @@ LIST_OF_USER_ACCOUNTING = [
     "Randy Ulrich",
     "Richard Francis",
     "Morgan White",
-    "Anuj Maddox",
     "Jody Jensen",
     "Mike Carter",
     "Gern Tyler",
@@ -77,8 +75,6 @@ LIST_OF_USER_HUMAN = [
     "Robert Daugherty",
     "Torrey Mason",
     "Brad Talbot",
-    "Anuj Jablonski",
-    "Harry Miller",
     "Jeffrey Campaigne",
     "Stephen Triplett",
     "John Falena",
@@ -107,8 +103,7 @@ LIST_OF_USER_HUMAN = [
     "Tobias Schmith",
     "Jon Goldstein",
     "Janet Lutz",
-    "Karl Cope",
-]
+    "Karl Cope"]
 
 LIST_OF_USER_TESTING = [
     "Andy Bergin",
@@ -122,8 +117,7 @@ LIST_OF_USER_TESTING = [
     "Alan White",
     "Daniel Ward",
     "Lee Stockton",
-    "Matthew Vaughan"
-]
+    "Matthew Vaughan"]
 
 LIST_OF_USER_DEVELOPMENT = [
     "Kelly Winters",
@@ -143,7 +137,6 @@ LIST_OF_USER_DEVELOPMENT = [
     "Timothy Kelly",
     "Sue Mason",
     "Chris Alexander",
-    "Anuj Jensen",
     "Martin Talbot",
     "Scott Farmer",
     "Allison Jensen",
@@ -152,9 +145,7 @@ LIST_OF_USER_DEVELOPMENT = [
     "Dan Langdon",
     "Ashley Knutson",
     "Jon Bourke",
-    "Pete Hunt",
-
-]
+    "Pete Hunt"]
 
 LIST_OF_USER_PAYROLL = [
     "Ashley Chassin",
@@ -164,12 +155,17 @@ LIST_OF_USER_PAYROLL = [
     "Patricia Shelton",
     "Dietrich Swain",
     "Allison Hunter",
-    "Anne-Louise Barnes"
+    "Anne-Louise Barnes"]
 
-]
+LIST_OF_USER_PEOPLE = [
+    'Sam Carter',
+    'Tom Morris',
+    'Kevin Vaughan',
+    'Rich Daugherty',
+    'Harry Miller',
+    'Sam Schmith']
 
 
-@pytest.mark.skip(reason="https://pagure.io/389-ds-base/issue/50201")
 def test_invalid_configuration(topo):
     """"
     Error handling for invalid configuration
@@ -190,10 +186,7 @@ def test_invalid_configuration(topo):
               'limit=0 flags=AND flags=AND',
               'limit=0 type=eq values=foo values=foo',
               'limit=0 type=eq values=foo,foo',
-              'limit=0 type=sub',
-              'limit=0 type=eq values=notvalid',
               'limit',
-              'limit=0 type=eq values=notavaliddn',
               'limit=0 type=pres values=bogus',
               'limit=0 type=eq,sub values=bogus',
               'limit=',
@@ -203,7 +196,8 @@ def test_invalid_configuration(topo):
               'limit=-2',
               'type=eq',
               'limit=0 type=bogus']:
-        Index(topo.standalone, GIVEN_NAME).replace('nsIndexIDListScanLimit', i)
+        with pytest.raises(ldap.UNWILLING_TO_PERFORM):
+            Index(topo.standalone, GIVEN_NAME).replace('nsIndexIDListScanLimit', i)
 
 
 def test_idlistscanlimit(topo):
@@ -247,28 +241,24 @@ def test_idlistscanlimit(topo):
                  (LIST_OF_USER_HUMAN, users_human),
                  (LIST_OF_USER_TESTING, users_testing),
                  (LIST_OF_USER_DEVELOPMENT, users_development),
-                 (LIST_OF_USER_PAYROLL, users_payroll)]:
+                 (LIST_OF_USER_PAYROLL, users_payroll),
+                 (LIST_OF_USER_PEOPLE, users_people)]:
         for demo1 in data[0]:
+            fn = demo1.split()[0]
+            sn = demo1.split()[1]
+            uid = ''.join([fn[:1], sn]).lower()
             data[1].create(properties={
-                'uid': demo1,
+                'uid': uid,
                 'cn': demo1,
-                'sn': demo1.split()[1],
+                'sn': sn,
                 'uidNumber': str(1000),
                 'gidNumber': '2000',
-                'homeDirectory': '/home/' + demo1,
-                'givenname': demo1.split()[0],
-                'userpassword': PW_DM
+                'homeDirectory': f'/home/{uid}',
+                'givenname': fn,
+                'userpassword': PW_DM,
+                'mail': f'{uid}@test.com'
             })
 
-    users_people.create(properties={
-        'uid': 'scarter',
-        'cn': 'Sam Carter',
-        'sn': 'Carter',
-        'uidNumber': str(1000),
-        'gidNumber': '2000',
-        'homeDirectory': '/home/' + 'scarter',
-        'mail': 'scarter@anuj.com',
-    })
     try:
         # Change log levels
         errorlog_value = topo.standalone.config.get_attr_val_utf8('nsslapd-errorlog-level')
@@ -297,16 +287,12 @@ def test_idlistscanlimit(topo):
 
         Index(topo.standalone, UNIQMEMBER).\
         replace('nsIndexIDListScanLimit',
-                'limit=0 type=eq values=uid=kvaughan,ou=People,'
-                'dc=example,dc=com,uid=rdaugherty,ou=People,dc=example,dc=com')
+                'limit=0 type=eq values=uid=kvaughan\2Cou=People\2Cdc=example\2Cdc=com,'
+                'uid=rdaugherty\2Cou=People\2Cdc=example\2Cdc=com')
 
         Index(topo.standalone, OBJECTCLASS).\
         replace('nsIndexIDListScanLimit', 'limit=0 type=eq flags=AND values=inetOrgPerson')
 
-        Index(topo.standalone, MAIL).\
-        replace('nsIndexIDListScanLimit',
-                'cn=mail,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config')
-
         # Search with filter
         for i in ['(sn=Lutz)',
                   '(sn=*ter)',
@@ -321,22 +307,24 @@ def test_idlistscanlimit(topo):
                   '(&(sn=*)(cn=*))',
                   '(sn=Hunter)',
                   '(&(givenname=Richard)(objectclass=organizationalPerson))',
-                  '(givenname=Anuj)',
+                  '(givenname=Morgan)',
                   '(&(givenname=*)(cn=*))',
                   '(givenname=*)']:
             assert Accounts(topo.standalone, DEFAULT_SUFFIX).filter(f'{i}')
 
-        # Creating Group
-        Group(topo.standalone, 'cn=Accounting Managers,ou=groups,dc=example,dc=com').\
-        add('uniquemember',
+        # Creating Groups and adding members
+        groups = UniqueGroups(topo.standalone, DEFAULT_SUFFIX)
+        accounting_managers = groups.ensure_state(properties={'cn': 'Accounting Managers'})
+        hr_managers = groups.ensure_state(properties={'cn': 'HR Managers'})
+
+        accounting_managers.add('uniquemember',
             ['uid=scarter, ou=People, dc=example,dc=com',
              'uid=tmorris, ou=People, dc=example,dc=com',
              'uid=kvaughan, ou=People, dc=example,dc=com',
              'uid=rdaugherty, ou=People, dc=example,dc=com',
              'uid=hmiller, ou=People, dc=example,dc=com'])
 
-        Group(topo.standalone, 'cn=HR Managers,ou=groups,dc=example,dc=com').\
-        add('uniquemember',
+        hr_managers.add('uniquemember',
             ['uid=kvaughan, ou=People, dc=example,dc=com',
              'uid=cschmith, ou=People, dc=example,dc=com'])
 
@@ -403,10 +391,9 @@ def test_idlistscanlimit(topo):
                       '(&(sn=*)(cn=*))',
                       '(sn=Hunter)',
                       '(&(givenname=Richard)(objectclass=organizationalPerson))',
-                      '(givenname=Anuj)',
+                      '(givenname=Morgan)',
                       '(&(givenname=*)(cn=*))',
                       '(givenname=*)']:
-
             assert Accounts(topo.standalone, DEFAULT_SUFFIX).filter(value)
 
     finally:
diff --git a/ldap/servers/slapd/back-ldbm/instance.c b/ldap/servers/slapd/back-ldbm/instance.c
index 04c28ff39..07655a8ec 100644
--- a/ldap/servers/slapd/back-ldbm/instance.c
+++ b/ldap/servers/slapd/back-ldbm/instance.c
@@ -231,7 +231,7 @@ ldbm_instance_create_default_indexes(backend *be)
 
     /* ldbm_instance_config_add_index_entry(inst, 2, argv); */
     e = ldbm_instance_init_config_entry(LDBM_PSEUDO_ATTR_DEFAULT, "none", 0, 0, 0);
-    attr_index_config(be, "ldbm index init", 0, e, 1, 0);
+    attr_index_config(be, "ldbm index init", 0, e, 1, 0, NULL);
     slapi_entry_free(e);
 
     if (!entryrdn_get_noancestorid()) {
@@ -240,7 +240,7 @@ ldbm_instance_create_default_indexes(backend *be)
          * but we still want to use the attr index file APIs.
          */
         e = ldbm_instance_init_config_entry(LDBM_ANCESTORID_STR, "eq", 0, 0, 0);
-        attr_index_config(be, "ldbm index init", 0, e, 1, 0);
+        attr_index_config(be, "ldbm index init", 0, e, 1, 0, NULL);
         slapi_entry_free(e);
     }
 
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_attr.c b/ldap/servers/slapd/back-ldbm/ldbm_attr.c
index b9e130d77..f0d418572 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_attr.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_attr.c
@@ -633,6 +633,18 @@ attr_index_idlistsize_config(Slapi_Entry *e, struct attrinfo *ai, char *returnte
     return rc;
 }
 
+/*
+ * Function that process index attributes and modifies attrinfo structure
+ *
+ * Called while adding default indexes, during db2index execution and
+ * when we add/modify/delete index config entry
+ *
+ * If char *err_buf is not NULL, it will additionally print all error messages to STDERR
+ * It is used when we add/modify/delete index config entry, so the user would have a better verbose
+ *
+ * returns -1, 1 on a failure
+ *         0 on success
+ */
 int
 attr_index_config(
     backend *be,
@@ -640,7 +652,8 @@ attr_index_config(
     int lineno,
     Slapi_Entry *e,
     int init __attribute__((unused)),
-    int indextype_none)
+    int indextype_none,
+    char *err_buf)
 {
     ldbm_instance *inst = (ldbm_instance *)be->be_instance_info;
     int j = 0;
@@ -662,6 +675,7 @@ attr_index_config(
         slapi_attr_first_value(attr, &sval);
         attrValue = slapi_value_get_berval(sval);
     } else {
+        slapi_create_errormsg(err_buf, SLAPI_DSE_RETURNTEXT_SIZE, "Error: missing indexing arguments\n");
         slapi_log_err(SLAPI_LOG_ERR, "attr_index_config", "Missing indexing arguments\n");
         return -1;
     }
@@ -705,6 +719,10 @@ attr_index_config(
                 }
                 a->ai_indexmask = INDEX_OFFLINE; /* note that the index isn't available */
             } else {
+                slapi_create_errormsg(err_buf, SLAPI_DSE_RETURNTEXT_SIZE,
+                                      "Error: %s: line %d: unknown index type \"%s\" (ignored) in entry (%s), "
+                                      "valid index types are \"pres\", \"eq\", \"approx\", or \"sub\"\n",
+                                      fname, lineno, attrValue->bv_val, slapi_entry_get_dn(e));
                 slapi_log_err(SLAPI_LOG_ERR, "attr_index_config",
                               "%s: line %d: unknown index type \"%s\" (ignored) in entry (%s), "
                               "valid index types are \"pres\", \"eq\", \"approx\", or \"sub\"\n",
@@ -715,6 +733,7 @@ attr_index_config(
         }
         if (hasIndexType == 0) {
             /* indexType missing, error out */
+            slapi_create_errormsg(err_buf, SLAPI_DSE_RETURNTEXT_SIZE, "Error: missing index type\n");
             slapi_log_err(SLAPI_LOG_ERR, "attr_index_config", "Missing index type\n");
             attrinfo_delete(&a);
             return -1;
@@ -873,16 +892,26 @@ attr_index_config(
             slapi_ch_free((void **)&official_rules);
         }
     }
-
     if ((return_value = attr_index_idlistsize_config(e, a, myreturntext))) {
+        slapi_create_errormsg(err_buf, SLAPI_DSE_RETURNTEXT_SIZE,
+                              "Error: %s: Failed to parse idscanlimit info: %d:%s\n",
+                              fname, return_value, myreturntext);
         slapi_log_err(SLAPI_LOG_ERR, "attr_index_config", "%s: Failed to parse idscanlimit info: %d:%s\n",
                       fname, return_value, myreturntext);
+        if (err_buf != NULL) {
+            /* we are inside of a callback, we shouldn't allow malformed attributes in index entries */
+            attrinfo_delete(&a);
+            return return_value;
+        }
     }
 
     /* initialize the IDL code's private data */
     return_value = idl_init_private(be, a);
     if (0 != return_value) {
         /* fatal error, exit */
+        slapi_create_errormsg(err_buf, SLAPI_DSE_RETURNTEXT_SIZE,
+                              "Error: %s: line %d:Fatal Error: Failed to initialize attribute structure\n",
+                              fname, lineno);
         slapi_log_err(SLAPI_LOG_CRIT, "attr_index_config",
                       "%s: line %d:Fatal Error: Failed to initialize attribute structure\n",
                       fname, lineno);
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_index_config.c b/ldap/servers/slapd/back-ldbm/ldbm_index_config.c
index 45f0034f0..720f93036 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_index_config.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_index_config.c
@@ -25,26 +25,34 @@ int ldbm_instance_index_config_delete_callback(Slapi_PBlock *pb, Slapi_Entry *en
 #define INDEXTYPE_NONE 1
 
 static int
-ldbm_index_parse_entry(ldbm_instance *inst, Slapi_Entry *e, const char *trace_string, char **index_name)
+ldbm_index_parse_entry(ldbm_instance *inst, Slapi_Entry *e, const char *trace_string, char **index_name, char *err_buf)
 {
     Slapi_Attr *attr;
     const struct berval *attrValue;
     Slapi_Value *sval;
+    char *edn = slapi_entry_get_dn(e);
 
     /* Get the name of the attribute to index which will be the value
      * of the cn attribute. */
     if (slapi_entry_attr_find(e, "cn", &attr) != 0) {
-        slapi_log_err(SLAPI_LOG_ERR, "ldbm_index_parse_entry", "Malformed index entry %s\n",
-                      slapi_entry_get_dn(e));
+        slapi_create_errormsg(err_buf, SLAPI_DSE_RETURNTEXT_SIZE,
+                              "Error: malformed index entry %s\n",
+                              edn);
+        slapi_log_err(SLAPI_LOG_ERR,
+                      "ldbm_index_parse_entry", "Malformed index entry %s\n",
+                      edn);
         return LDAP_OPERATIONS_ERROR;
     }
 
     slapi_attr_first_value(attr, &sval);
     attrValue = slapi_value_get_berval(sval);
     if (NULL == attrValue->bv_val || 0 == attrValue->bv_len) {
+        slapi_create_errormsg(err_buf, SLAPI_DSE_RETURNTEXT_SIZE,
+                              "Error: malformed index entry %s -- empty index name\n",
+                              edn);
         slapi_log_err(SLAPI_LOG_ERR,
                       "ldbm_index_parse_entry", "Malformed index entry %s -- empty index name\n",
-                      slapi_entry_get_dn(e));
+                      edn);
         return LDAP_OPERATIONS_ERROR;
     }
 
@@ -59,16 +67,19 @@ ldbm_index_parse_entry(ldbm_instance *inst, Slapi_Entry *e, const char *trace_st
         attrValue = slapi_value_get_berval(sval);
         if (NULL == attrValue->bv_val || attrValue->bv_len == 0) {
             /* missing the index type, error out */
-            slapi_log_err(SLAPI_LOG_ERR,
-                          "ldbm_index_parse_entry", "Malformed index entry %s -- empty nsIndexType\n",
-                          slapi_entry_get_dn(e));
+            slapi_create_errormsg(err_buf, SLAPI_DSE_RETURNTEXT_SIZE,
+                                  "Error: malformed index entry %s -- empty nsIndexType\n",
+                                  edn);
+            slapi_log_err(SLAPI_LOG_ERR, "ldbm_index_parse_entry",
+                          "Malformed index entry %s -- empty nsIndexType\n",
+                          edn);
             slapi_ch_free_string(index_name);
             return LDAP_OPERATIONS_ERROR;
         }
     }
 
     /* ok the entry is good to process, pass it to attr_index_config */
-    if (attr_index_config(inst->inst_be, (char *)trace_string, 0, e, 0, 0)) {
+    if (attr_index_config(inst->inst_be, (char *)trace_string, 0, e, 0, 0, err_buf)) {
         slapi_ch_free_string(index_name);
         return LDAP_OPERATIONS_ERROR;
     }
@@ -92,7 +103,7 @@ ldbm_index_init_entry_callback(Slapi_PBlock *pb __attribute__((unused)),
     ldbm_instance *inst = (ldbm_instance *)arg;
 
     returntext[0] = '\0';
-    *returncode = ldbm_index_parse_entry(inst, e, "from ldbm instance init", NULL);
+    *returncode = ldbm_index_parse_entry(inst, e, "from ldbm instance init", NULL, NULL);
     if (*returncode == LDAP_SUCCESS) {
         return SLAPI_DSE_CALLBACK_OK;
     } else {
@@ -117,7 +128,7 @@ ldbm_instance_index_config_add_callback(Slapi_PBlock *pb __attribute__((unused))
     char *index_name = NULL;
 
     returntext[0] = '\0';
-    *returncode = ldbm_index_parse_entry(inst, e, "from DSE add", &index_name);
+    *returncode = ldbm_index_parse_entry(inst, e, "from DSE add", &index_name, returntext);
     if (*returncode == LDAP_SUCCESS) {
         struct attrinfo *ai = NULL;
         /* if the index is a "system" index, we assume it's being added by
@@ -179,7 +190,7 @@ ldbm_instance_index_config_delete_callback(Slapi_PBlock *pb,
     slapi_attr_first_value(attr, &sval);
     attrValue = slapi_value_get_berval(sval);
 
-    attr_index_config(inst->inst_be, "From DSE delete", 0, e, 0, INDEXTYPE_NONE);
+    attr_index_config(inst->inst_be, "From DSE delete", 0, e, 0, INDEXTYPE_NONE, returntext);
 
     ainfo_get(inst->inst_be, attrValue->bv_val, &ainfo);
     if (NULL == ainfo) {
@@ -213,14 +224,19 @@ ldbm_instance_index_config_modify_callback(Slapi_PBlock *pb __attribute__((unuse
     Slapi_Value *sval;
     const struct berval *attrValue;
     struct attrinfo *ainfo = NULL;
+    char *edn = slapi_entry_get_dn(e);
+    char *edn_after = slapi_entry_get_dn(entryAfter);
 
     returntext[0] = '\0';
     *returncode = LDAP_SUCCESS;
 
     if (slapi_entry_attr_find(entryAfter, "cn", &attr) != 0) {
+        slapi_create_errormsg(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
+                              "Error: malformed index entry %s - missing cn attribute\n",
+                              edn_after);
         slapi_log_err(SLAPI_LOG_ERR,
                       "ldbm_instance_index_config_modify_callback", "Malformed index entry %s - missing cn attribute\n",
-                      slapi_entry_get_dn(entryAfter));
+                      edn_after);
         *returncode = LDAP_OBJECT_CLASS_VIOLATION;
         return SLAPI_DSE_CALLBACK_ERROR;
     }
@@ -228,31 +244,40 @@ ldbm_instance_index_config_modify_callback(Slapi_PBlock *pb __attribute__((unuse
     attrValue = slapi_value_get_berval(sval);
 
     if (NULL == attrValue->bv_val || 0 == attrValue->bv_len) {
+        slapi_create_errormsg(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
+                              "Error: malformed index entry %s - missing index name\n",
+                              edn);
         slapi_log_err(SLAPI_LOG_ERR,
                       "ldbm_instance_index_config_modify_callback", "Malformed index entry %s, missing index name\n",
-                      slapi_entry_get_dn(e));
+                      edn);
         *returncode = LDAP_UNWILLING_TO_PERFORM;
         return SLAPI_DSE_CALLBACK_ERROR;
     }
 
     ainfo_get(inst->inst_be, attrValue->bv_val, &ainfo);
     if (NULL == ainfo) {
+        slapi_create_errormsg(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
+                              "Error: malformed index entry %s - missing cn attribute info\n",
+                              edn);
         slapi_log_err(SLAPI_LOG_ERR,
                       "ldbm_instance_index_config_modify_callback", "Malformed index entry %s - missing cn attribute info\n",
-                      slapi_entry_get_dn(e));
+                      edn);
         *returncode = LDAP_UNWILLING_TO_PERFORM;
         return SLAPI_DSE_CALLBACK_ERROR;
     }
 
     if (slapi_entry_attr_find(entryAfter, "nsIndexType", &attr) != 0) {
+        slapi_create_errormsg(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
+                              "Error: malformed index entry %s - missing nsIndexType attribute\n",
+                              edn_after);
         slapi_log_err(SLAPI_LOG_ERR,
                       "ldbm_instance_index_config_modify_callback", "Malformed index entry %s - missing nsIndexType attribute\n",
-                      slapi_entry_get_dn(entryAfter));
+                      edn_after);
         *returncode = LDAP_OBJECT_CLASS_VIOLATION;
         return SLAPI_DSE_CALLBACK_ERROR;
     }
 
-    if (attr_index_config(inst->inst_be, "from DSE modify", 0, entryAfter, 0, 0)) {
+    if (attr_index_config(inst->inst_be, "from DSE modify", 0, entryAfter, 0, 0, returntext)) {
         *returncode = LDAP_UNWILLING_TO_PERFORM;
         return SLAPI_DSE_CALLBACK_ERROR;
     }
@@ -364,7 +389,7 @@ ldbm_instance_index_config_enable_index(ldbm_instance *inst, Slapi_Entry *e)
         ainfo_get(inst->inst_be, index_name, &ai);
     }
     if (!ai) {
-        rc = ldbm_index_parse_entry(inst, e, "from DSE add", &index_name);
+        rc = ldbm_index_parse_entry(inst, e, "from DSE add", &index_name, NULL);
     }
     if (rc == LDAP_SUCCESS) {
         /* Assume the caller knows if it is OK to go online immediately */
diff --git a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
index 9d82c8228..f2ef5ecd4 100644
--- a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
+++ b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
@@ -291,7 +291,7 @@ db2index_add_indexed_attr(backend *be, char *attrString)
         }
     }
 
-    attr_index_config(be, "from db2index()", 0, e, 0, 0);
+    attr_index_config(be, "from db2index()", 0, e, 0, 0, NULL);
     slapi_entry_free(e);
 
     return (0);
diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
index 9a86c752b..a07acee5e 100644
--- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
+++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
@@ -24,7 +24,7 @@ void attrinfo_delete(struct attrinfo **pp);
 void ainfo_get(backend *be, char *type, struct attrinfo **at);
 void attr_masks(backend *be, char *type, int *indexmask, int *syntaxmask);
 void attr_masks_ex(backend *be, char *type, int *indexmask, int *syntaxmask, struct attrinfo **at);
-int attr_index_config(backend *be, char *fname, int lineno, Slapi_Entry *e, int init, int none);
+int attr_index_config(backend *be, char *fname, int lineno, Slapi_Entry *e, int init, int none, char *err_buf);
 int db2index_add_indexed_attr(backend *be, char *attrString);
 int ldbm_compute_init(void);
 void attrinfo_deletetree(ldbm_instance *inst);
-- 
2.26.2