Blame SOURCES/0014-Issue-50201-nsIndexIDListScanLimit-accepts-any-value.patch

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