From 2dc43f27f613bb8156bf65b81c53e6b035fca2e3 Mon Sep 17 00:00:00 2001
From: Quanah Gibson-Mount <quanah@openldap.org>
Date: Mon, 10 Nov 2008 23:57:29 +0000
Subject: [PATCH] ITS#4556

---
 doc/man/man5/slapd-config.5 | 10 +++++++++-
 doc/man/man5/slapd.access.5 | 10 +++++++++-
 doc/man/man5/slapd.conf.5   |  8 ++++++++
 servers/slapd/acl.c         |  4 ++++
 servers/slapd/bconfig.c     | 21 ++++++++++++++++++++-
 servers/slapd/slap.h        |  2 ++
 tests/data/slapd-acl.conf   |  2 +-
 tests/data/slapd-dds.conf   |  1 +
 8 files changed, 54 insertions(+), 4 deletions(-)

diff --git a/doc/man/man5/slapd-config.5 b/doc/man/man5/slapd-config.5
index 4c22b3eef2..41e7da2cf2 100644
--- a/doc/man/man5/slapd-config.5
+++ b/doc/man/man5/slapd-config.5
@@ -1204,7 +1204,7 @@ See
 .BR olcLimits
 for an explanation of the different flags.
 .TP
-.B olcSortVals <attr> [...]
+.B olcSortVals: <attr> [...]
 Specify a list of multi-valued attributes whose values will always
 be maintained in sorted order. Using this option will allow Modify,
 Compare, and filter evaluations on these attributes to be performed
@@ -1234,6 +1234,14 @@ which they are defined.  They are supported by every
 type of backend. All of the Global Database Options may also be
 used here.
 .TP
+.B olcAddContentAcl: TRUE | FALSE
+Controls whether Add operations will perform ACL checks on
+the content of the entry being added. This check is off
+by default. See the
+.BR slapd.access (5)
+manual page for more details on ACL requirements for
+Add operations.
+.TP
 .B olcHidden: TRUE | FALSE
 Controls whether the database will be used to answer
 queries. A database that is hidden will never be
diff --git a/doc/man/man5/slapd.access.5 b/doc/man/man5/slapd.access.5
index 5fe76f684e..dd24af2018 100644
--- a/doc/man/man5/slapd.access.5
+++ b/doc/man/man5/slapd.access.5
@@ -911,7 +911,15 @@ When adding the suffix entry of a database,
 .B add
 access to
 .B children
-of the empty DN ("") is required.
+of the empty DN ("") is required. Also if
+Add content ACL checking has been configured on
+the database (see the
+.BR slapd.conf (5)
+or
+.BR slapd-config (5)
+manual page),
+.B add (=a)
+will be required on all of the attributes being added.
 
 .LP
 The 
diff --git a/doc/man/man5/slapd.conf.5 b/doc/man/man5/slapd.conf.5
index 8a7f8e8477..3e2ab714d2 100644
--- a/doc/man/man5/slapd.conf.5
+++ b/doc/man/man5/slapd.conf.5
@@ -1162,6 +1162,14 @@ or
 .BR sql ,
 depending on which backend will serve the database.
 .TP
+.B add_content_acl on | off
+Controls whether Add operations will perform ACL checks on
+the content of the entry being added. This check is off
+by default. See the
+.BR slapd.access (5)
+manual page for more details on ACL requirements for
+Add operations.
+.TP
 .B hidden on | off
 Controls whether the database will be used to answer
 queries. A database that is hidden will never be
diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c
index dcb0844aa3..a9c2a79155 100644
--- a/servers/slapd/acl.c
+++ b/servers/slapd/acl.c
@@ -1843,6 +1843,10 @@ acl_check_modlist(
 	}
 	assert( be != NULL );
 
+	/* If ADD attribute checking is not enabled, just allow it */
+	if ( op->o_tag == LDAP_REQ_ADD && !SLAP_DBACL_ADD( be ))
+		return 1;
+
 	/* short circuit root database access */
 	if ( be_isroot( op ) ) {
 		Debug( LDAP_DEBUG_ACL,
diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c
index 974f2fd53f..0d1431923b 100644
--- a/servers/slapd/bconfig.c
+++ b/servers/slapd/bconfig.c
@@ -184,6 +184,7 @@ enum {
 	CFG_SORTVALS,
 	CFG_IX_INTLEN,
 	CFG_SYNTAX,
+	CFG_ACL_ADD,
 
 	CFG_LAST
 };
@@ -280,6 +281,10 @@ static ConfigTable config_back_cf_table[] = {
 			"DESC 'Access Control List' "
 			"EQUALITY caseIgnoreMatch "
 			"SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
+	{ "add_content_acl",	NULL, 0, 0, 0, ARG_MAY_DB|ARG_ON_OFF|ARG_MAGIC|CFG_ACL_ADD,
+		&config_generic, "( OLcfgGlAt:86 NAME 'olcAddContentAcl' "
+			"DESC 'Check ACLs against content of Add ops' "
+			"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
 	{ "allows",	"features", 2, 0, 5, ARG_PRE_DB|ARG_MAGIC,
 		&config_allows, "( OLcfgGlAt:2 NAME 'olcAllows' "
 			"DESC 'Allowed set of deprecated features' "
@@ -771,7 +776,7 @@ static ConfigOCs cf_ocs[] = {
 		"SUP olcConfig STRUCTURAL "
 		"MUST olcDatabase "
 		"MAY ( olcHidden $ olcSuffix $ olcSubordinate $ olcAccess $ "
-		 "olcLastMod $ olcLimits $ "
+		 "olcAddContentAcl $ olcLastMod $ olcLimits $ "
 		 "olcMaxDerefDepth $ olcPlugin $ olcReadOnly $ olcReplica $ "
 		 "olcReplicaArgsFile $ olcReplicaPidFile $ olcReplicationInterval $ "
 		 "olcReplogFile $ olcRequires $ olcRestrict $ olcRootDN $ olcRootPW $ "
@@ -1006,6 +1011,9 @@ config_generic(ConfigArgs *c) {
 			rc = (!i);
 			break;
 		}
+		case CFG_ACL_ADD:
+			c->value_int = (SLAP_DBACL_ADD(c->be) != 0);
+			break;
 		case CFG_ROOTDSE: {
 			ConfigFile *cf = c->ca_private;
 			if ( cf->c_dseFiles ) {
@@ -1159,6 +1167,7 @@ config_generic(ConfigArgs *c) {
 		case CFG_SASLSECP:
 		case CFG_SSTR_IF_MAX:
 		case CFG_SSTR_IF_MIN:
+		case CFG_ACL_ADD:
 			break;
 
 		/* no-ops, requires slapd restart */
@@ -1694,6 +1703,13 @@ sortval_reject:
 			}
 			break;
 
+		case CFG_ACL_ADD:
+			if(c->value_int)
+				SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_ACL_ADD;
+			else
+				SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_ACL_ADD;
+			break;
+
 		case CFG_ROOTDSE:
 			if(root_dse_read_file(c->argv[1])) {
 				snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> could not read file", c->argv[0] );
@@ -6193,6 +6209,9 @@ config_back_db_init( BackendDB *be, ConfigReply* cr )
 	/* Hide from namingContexts */
 	SLAP_BFLAGS(be) |= SLAP_BFLAG_CONFIG;
 
+	/* Check ACLs on content of Adds by default */
+	SLAP_DBFLAGS(be) |= SLAP_DBFLAG_ACL_ADD;
+
 	return 0;
 }
 
diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h
index 8822e1f02b..3e0fb9a91d 100644
--- a/servers/slapd/slap.h
+++ b/servers/slapd/slap.h
@@ -1789,6 +1789,7 @@ struct BackendDB {
 #define SLAP_DBFLAG_SYNC_SHADOW		0x1000U /* a sync shadow */
 #define SLAP_DBFLAG_SLURP_SHADOW	0x2000U /* a slurp shadow */
 #define SLAP_DBFLAG_CLEAN		0x10000U /* was cleanly shutdown */
+#define SLAP_DBFLAG_ACL_ADD		0x20000U /* check attr ACLs on adds */
 	slap_mask_t	be_flags;
 #define SLAP_DBFLAGS(be)			((be)->be_flags)
 #define SLAP_NOLASTMOD(be)			(SLAP_DBFLAGS(be) & SLAP_DBFLAG_NOLASTMOD)
@@ -1814,6 +1815,7 @@ struct BackendDB {
 #define SLAP_SINGLE_SHADOW(be)			(SLAP_DBFLAGS(be) & SLAP_DBFLAG_SINGLE_SHADOW)
 #define SLAP_MULTIMASTER(be)			(!SLAP_SINGLE_SHADOW(be))
 #define SLAP_DBCLEAN(be)			(SLAP_DBFLAGS(be) & SLAP_DBFLAG_CLEAN)
+#define SLAP_DBACL_ADD(be)			(SLAP_DBFLAGS(be) & SLAP_DBFLAG_ACL_ADD)
 
 	slap_mask_t	be_restrictops;		/* restriction operations */
 #define SLAP_RESTRICT_OP_ADD		0x0001U
diff --git a/tests/data/slapd-acl.conf b/tests/data/slapd-acl.conf
index 64cde948c7..fca529b082 100644
--- a/tests/data/slapd-acl.conf
+++ b/tests/data/slapd-acl.conf
@@ -52,7 +52,7 @@ rootpw		secret
 #hdb#index		cn,sn,uid	pres,eq,sub
 #ndb#dbname db_1
 #ndb#include @DATADIR@/ndb.conf
-
+add_content_acl	on
 #access		to attrs=objectclass dn.subtree="dc=example,dc=com"
 access		to attrs=objectclass
 		by dn.exact="cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=example,dc=com" add
diff --git a/tests/data/slapd-dds.conf b/tests/data/slapd-dds.conf
index bb9ebbf10d..955a23734a 100644
--- a/tests/data/slapd-dds.conf
+++ b/tests/data/slapd-dds.conf
@@ -48,6 +48,7 @@ rootpw		secret
 #hdb#index		entryExpireTimestamp	eq
 #ndb#dbname db_1
 #ndb#include @DATADIR@/ndb.conf
+add_content_acl	on
 
 overlay		dds
 dds-max-ttl	1d
-- 
GitLab