From a1aba13906c36ac7b63842e8f5ae9ded9be8dc40 Mon Sep 17 00:00:00 2001
From: Kurt Zeilenga <kurt@openldap.org>
Date: Fri, 22 Jun 2001 19:54:09 +0000
Subject: [PATCH] Import improved schema check error reporting from HEAD

---
 servers/slapd/back-ldbm/add.c    |  5 ++--
 servers/slapd/back-ldbm/modify.c | 11 +++++---
 servers/slapd/back-ldbm/modrdn.c |  5 +++-
 servers/slapd/back-ldbm/passwd.c | 19 +++++++++-----
 servers/slapd/proto-slap.h       |  3 ++-
 servers/slapd/schema_check.c     | 45 ++++++++++++++++++--------------
 servers/slapd/tools/slapadd.c    |  7 ++++-
 7 files changed, 61 insertions(+), 34 deletions(-)

diff --git a/servers/slapd/back-ldbm/add.c b/servers/slapd/back-ldbm/add.c
index 1b36200c88..a844bf90ce 100644
--- a/servers/slapd/back-ldbm/add.c
+++ b/servers/slapd/back-ldbm/add.c
@@ -31,7 +31,8 @@ ldbm_back_add(
 	int			rc; 
 	const char	*text = NULL;
 	AttributeDescription *children = slap_schema.si_ad_children;
-
+	char textbuf[SLAP_TEXT_BUFLEN];
+	size_t textlen = sizeof textbuf;
 
 	Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_add: %s\n", e->e_dn, 0, 0);
 
@@ -45,7 +46,7 @@ ldbm_back_add(
 		return( -1 );
 	}
 
-	rc = entry_schema_check( e, NULL, &text );
+	rc = entry_schema_check( e, NULL, &text, textbuf, textlen );
 
 	if ( rc != LDAP_SUCCESS ) {
 		ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
diff --git a/servers/slapd/back-ldbm/modify.c b/servers/slapd/back-ldbm/modify.c
index 8e7c7441a8..0dc69c133e 100644
--- a/servers/slapd/back-ldbm/modify.c
+++ b/servers/slapd/back-ldbm/modify.c
@@ -34,7 +34,9 @@ int ldbm_modify_internal(
     const char	*dn,
     Modifications	*modlist,
     Entry	*e,
-	const char **text 
+	const char **text,
+	char *textbuf,
+	size_t textlen
 )
 {
 	int rc, err;
@@ -135,7 +137,7 @@ int ldbm_modify_internal(
 	ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
 
 	/* check that the entry still obeys the schema */
-	rc = entry_schema_check( e, save_attrs, text );
+	rc = entry_schema_check( e, save_attrs, text, textbuf, textlen );
 	if ( rc != LDAP_SUCCESS ) {
 		attrs_free( e->e_attrs );
 		e->e_attrs = save_attrs;
@@ -182,6 +184,8 @@ ldbm_back_modify(
 	Entry		*e;
 	int		manageDSAit = get_manageDSAit( op );
 	const char *text = NULL;
+	char textbuf[SLAP_TEXT_BUFLEN];
+	size_t textlen = sizeof textbuf;
 
 	Debug(LDAP_DEBUG_ARGS, "ldbm_back_modify:\n", 0, 0, 0);
 
@@ -229,7 +233,8 @@ ldbm_back_modify(
 	}
 	
 	/* Modify the entry */
-	rc = ldbm_modify_internal( be, conn, op, ndn, modlist, e, &text );
+	rc = ldbm_modify_internal( be, conn, op, ndn, modlist, e,
+		&text, textbuf, textlen );
 
 	if( rc != LDAP_SUCCESS ) {
 		if( rc != SLAPD_ABANDON ) {
diff --git a/servers/slapd/back-ldbm/modrdn.c b/servers/slapd/back-ldbm/modrdn.c
index 45695414a7..ac78abf6b1 100644
--- a/servers/slapd/back-ldbm/modrdn.c
+++ b/servers/slapd/back-ldbm/modrdn.c
@@ -53,6 +53,8 @@ ldbm_back_modrdn(
 	int			rootlock = 0;
 	int			rc = -1;
 	const char *text = NULL;
+	char textbuf[SLAP_TEXT_BUFLEN];
+	size_t textlen = sizeof textbuf;
 	/* Added to support LDAP v2 correctly (deleteoldrdn thing) */
 	char		*new_rdn_val = NULL;	/* Val of new rdn */
 	char		*new_rdn_type = NULL;	/* Type of new rdn */
@@ -464,7 +466,8 @@ ldbm_back_modrdn(
 	}
 
 	/* modify memory copy of entry */
-	rc = ldbm_modify_internal( be, conn, op, dn, &mod[0], e, &text );
+	rc = ldbm_modify_internal( be, conn, op, dn, &mod[0], e,
+		&text, textbuf, textlen );
 
 	if( rc != LDAP_SUCCESS ) {
 		if( rc != SLAPD_ABANDON ) {
diff --git a/servers/slapd/back-ldbm/passwd.c b/servers/slapd/back-ldbm/passwd.c
index 00ef475a1c..563e2c89c2 100644
--- a/servers/slapd/back-ldbm/passwd.c
+++ b/servers/slapd/back-ldbm/passwd.c
@@ -116,6 +116,8 @@ ldbm_back_exop_passwd(
 	{
 		Modifications ml;
 		struct berval *vals[2];
+		char textbuf[SLAP_TEXT_BUFLEN]; /* non-returnable */
+		size_t textlen;
 
 		vals[0] = hash;
 		vals[1] = NULL;
@@ -126,16 +128,19 @@ ldbm_back_exop_passwd(
 		ml.sml_next = NULL;
 
 		rc = ldbm_modify_internal( be,
-			conn, op, op->o_ndn, &ml, e, text );
+			conn, op, op->o_ndn, &ml, e, text, textbuf, textlen );
 
+		if( rc ) {
+			/* cannot return textbuf */
+			*text = "entry modify failed";
+			goto done;
+		}
 	}
 
-	if( rc == LDAP_SUCCESS ) {
-		/* change the entry itself */
-		if( id2entry_add( be, e ) != 0 ) {
-			*text = "entry update failed";
-			rc = LDAP_OTHER;
-		}
+	/* change the entry itself */
+	if( id2entry_add( be, e ) != 0 ) {
+		*text = "entry update failed";
+		rc = LDAP_OTHER;
 	}
 	
 done:
diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h
index ba4ebec32a..c0e9a5f6f9 100644
--- a/servers/slapd/proto-slap.h
+++ b/servers/slapd/proto-slap.h
@@ -642,7 +642,8 @@ int oc_check_allowed(
 	struct berval **oclist );
 LDAP_SLAPD_F (int) entry_schema_check LDAP_P((
 	Entry *e, Attribute *attrs,
-	const char** text ));
+	const char** text,
+	char *textbuf, size_t textlen ));
 
 
 /*
diff --git a/servers/slapd/schema_check.c b/servers/slapd/schema_check.c
index 7cf27a55a1..bc43608b81 100644
--- a/servers/slapd/schema_check.c
+++ b/servers/slapd/schema_check.c
@@ -27,7 +27,8 @@ static char *	oc_check_required(Entry *e, struct berval *ocname);
 
 int
 entry_schema_check( 
-	Entry *e, Attribute *oldattrs, const char** text )
+	Entry *e, Attribute *oldattrs, const char** text,
+	char *textbuf, size_t textlen )
 {
 	Attribute	*a, *aoc;
 	ObjectClass *oc;
@@ -38,6 +39,8 @@ entry_schema_check(
 
 	if( !global_schemacheck ) return LDAP_SUCCESS;
 
+	*text = textbuf;
+
 	/* find the object class attribute - could error out here */
 	if ( (aoc = attr_find( e->e_attrs, ad_objectClass )) == NULL ) {
 		Debug( LDAP_DEBUG_ANY, "No objectClass for entry (%s)\n",
@@ -49,20 +52,28 @@ entry_schema_check(
 	/* check that the entry has required attrs for each oc */
 	for ( i = 0; aoc->a_vals[i] != NULL; i++ ) {
 		if ( (oc = oc_find( aoc->a_vals[i]->bv_val )) == NULL ) {
+			snprintf( textbuf, textlen, 
+				"unrecognized objectClass '%s'",
+				aoc->a_vals[i]->bv_val );
+
 			Debug( LDAP_DEBUG_ANY,
-				"entry_check_schema(%s): objectClass \"%s\" not defined\n",
-				e->e_dn, aoc->a_vals[i]->bv_val, 0 );
-			*text = "unrecognized objectclass";
+				"entry_check_schema(%s): \"%s\" not recognized\n",
+				e->e_dn, textbuf, 0 );
+
 			return LDAP_OBJECT_CLASS_VIOLATION;
 
 		} else {
 			char *s = oc_check_required( e, aoc->a_vals[i] );
 
 			if (s != NULL) {
+				snprintf( textbuf, textlen, 
+					"object class '%s' requires attribute '%s'",
+					aoc->a_vals[i]->bv_val, s );
+
 				Debug( LDAP_DEBUG_ANY,
-					"Entry (%s), oc \"%s\" requires attr \"%s\"\n",
-					e->e_dn, aoc->a_vals[i]->bv_val, s );
-				*text = "missing required attribute";
+					"Entry (%s): %s\n",
+					e->e_dn, textbuf, 0 );
+
 				return LDAP_OBJECT_CLASS_VIOLATION;
 			}
 
@@ -85,10 +96,15 @@ entry_schema_check(
 		ret = oc_check_allowed( a->a_desc->ad_type, aoc->a_vals );
 		if ( ret != 0 ) {
 			char *type = a->a_desc->ad_cname->bv_val;
+
+			snprintf( textbuf, textlen, 
+				"attribute '%s' not allowed",
+				type );
+
 			Debug( LDAP_DEBUG_ANY,
-			    "Entry (%s), attr \"%s\" not allowed\n",
-			    e->e_dn, type, 0 );
-			*text = "attribute not allowed";
+			    "Entry (%s), %s\n",
+			    e->e_dn, textbuf, 0 );
+
 			break;
 		}
 	}
@@ -181,18 +197,9 @@ int oc_check_allowed(
 				}
 			}
 			/* maybe the next oc allows it */
-
-#ifdef OC_UNDEFINED_IMPLES_EXTENSIBLE
-		/* we don't know about the oc. assume it allows it */
-		} else {
-			if ( t != type )
-				ldap_memfree( t );
-			return LDAP_SUCCESS;
-#endif
 		}
 	}
 
-
 	/* not allowed by any oc */
 	return LDAP_OBJECT_CLASS_VIOLATION;
 }
diff --git a/servers/slapd/tools/slapadd.c b/servers/slapd/tools/slapadd.c
index 0e16f60749..5bc3832970 100644
--- a/servers/slapd/tools/slapadd.c
+++ b/servers/slapd/tools/slapadd.c
@@ -94,7 +94,12 @@ main( int argc, char **argv )
 		if( global_schemacheck ) {
 			/* check schema */
 			const char *text;
-			if ( entry_schema_check( e, NULL, &text ) != LDAP_SUCCESS ) {
+			char textbuf[SLAP_TEXT_BUFLEN];
+			size_t textlen = sizeof textbuf;
+
+			rc = entry_schema_check( e, NULL, &text, textbuf, textlen );
+
+			if( rc != LDAP_SUCCESS ) {
 				fprintf( stderr, "%s: dn=\"%s\" (line=%d): %s\n",
 					progname, e->e_dn, lineno, text );
 				rc = EXIT_FAILURE;
-- 
GitLab