From 64c904e60af04fa300e34106addcf7f233cda015 Mon Sep 17 00:00:00 2001
From: Quanah Gibson-Mount <quanah@openldap.org>
Date: Wed, 1 Jul 2009 22:44:21 +0000
Subject: [PATCH] Add ppolicy_forward_updates: if configured, ppolicy state
 changes due to Binds are performed using the frontend, to allow them to
 trigger the updateref on a consumer, which can then be forwarded by the chain
 overlay. Setting is ignored if server is not a consumer.

---
 doc/man/man5/slapo-ppolicy.5     | 14 +++++++++++++-
 servers/slapd/overlays/ppolicy.c | 27 +++++++++++++++++++++------
 2 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/doc/man/man5/slapo-ppolicy.5 b/doc/man/man5/slapo-ppolicy.5
index 28f6e40296..2bb99e4af7 100644
--- a/doc/man/man5/slapo-ppolicy.5
+++ b/doc/man/man5/slapo-ppolicy.5
@@ -49,6 +49,17 @@ Specify the DN of the pwdPolicy object to use when no specific policy is
 set on a given user's entry. If there is no specific policy for an entry
 and no default is given, then no policies will be enforced.
 .TP
+.B ppolicy_forward_updates
+Specify that policy state changes that result from Bind operations (such
+as recording failures, lockout, etc.) on a consumer should be forwarded
+to a master instead of being written directly into the consumer's local
+database. This setting is only useful on a replication consumer, and
+also requires the
+.B updateref
+setting and
+.B chain
+overlay to be appropriately configured.
+.TP
 .B ppolicy_hash_cleartext
 Specify that cleartext passwords present in Add and Modify requests should
 be hashed before being stored in the database. This violates the X.500/LDAP
@@ -742,7 +753,8 @@ ppolicy_default "cn=Standard,ou=Policies,dc=example,dc=com"
 .SH SEE ALSO
 .BR ldap (3),
 .BR slapd.conf (5),
-.BR slapd\-config (5).
+.BR slapd\-config (5),
+.BR slapo\-chain (5).
 .LP
 "OpenLDAP Administrator's Guide" (http://www.OpenLDAP.org/doc/admin/)
 .LP
diff --git a/servers/slapd/overlays/ppolicy.c b/servers/slapd/overlays/ppolicy.c
index 572ef9cdda..639fc5beeb 100644
--- a/servers/slapd/overlays/ppolicy.c
+++ b/servers/slapd/overlays/ppolicy.c
@@ -50,6 +50,7 @@ typedef struct pp_info {
 	struct berval def_policy;	/* DN of default policy subentry */
 	int use_lockout;		/* send AccountLocked result? */
 	int hash_passwords;		/* transparently hash cleartext pwds */
+	int forward_updates;	/* use frontend for policy state updates */
 } pp_info;
 
 /* Our per-connection info - note, it is not per-instance, it is 
@@ -224,6 +225,12 @@ static ConfigTable ppolicycfg[] = {
 	  "( OLcfgOvAt:12.2 NAME 'olcPPolicyHashCleartext' "
 	  "DESC 'Hash passwords on add or modify' "
 	  "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
+	{ "ppolicy_forward_updates", "on|off", 1, 2, 0,
+	  ARG_ON_OFF|ARG_OFFSET,
+	  (void *)offsetof(pp_info,forward_updates),
+	  "( OLcfgOvAt:12.4 NAME 'olcPPolicyForwardUpdates' "
+	  "DESC 'Allow policy state updates to be forwarded via updateref' "
+	  "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
 	{ "ppolicy_use_lockout", "on|off", 1, 2, 0,
 	  ARG_ON_OFF|ARG_OFFSET|PPOLICY_USE_LOCKOUT,
 	  (void *)offsetof(pp_info,use_lockout),
@@ -239,7 +246,7 @@ static ConfigOCs ppolicyocs[] = {
 	  "DESC 'Password Policy configuration' "
 	  "SUP olcOverlayConfig "
 	  "MAY ( olcPPolicyDefault $ olcPPolicyHashCleartext $ "
-	  "olcPPolicyUseLockout ) )",
+	  "olcPPolicyUseLockout $ olcPPolicyForwardUpdates ) )",
 	  Cft_Overlay, ppolicycfg },
 	{ NULL, 0, NULL }
 };
@@ -1115,17 +1122,25 @@ locked:
 		Operation op2 = *op;
 		SlapReply r2 = { REP_RESULT };
 		slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
+		pp_info *pi = on->on_bi.bi_private;
 
-		/* FIXME: Need to handle replication of some (but not all)
-		 * of the operational attributes...
-		 */
 		op2.o_tag = LDAP_REQ_MODIFY;
 		op2.o_callback = &cb;
 		op2.orm_modlist = mod;
 		op2.o_dn = op->o_bd->be_rootdn;
 		op2.o_ndn = op->o_bd->be_rootndn;
-		op2.o_bd->bd_info = (BackendInfo *)on->on_info;
-		rc = op->o_bd->be_modify( &op2, &r2 );
+
+		/* If this server is a shadow and forward_updates is true,
+		 * use the frontend to perform this modify. That will trigger
+		 * the update referral, which can then be forwarded by the
+		 * chain overlay. Obviously the updateref and chain overlay
+		 * must be configured appropriately for this to be useful.
+		 */
+		if ( SLAP_SHADOW( op->o_bd ) && pi->forward_updates )
+			op2.o_bd = frontendDB;
+		else
+			op2.o_bd->bd_info = (BackendInfo *)on->on_info;
+		rc = op2.o_bd->be_modify( &op2, &r2 );
 		slap_mods_free( mod, 1 );
 	}
 
-- 
GitLab