From a82efd08d595c87cd3efa99fd52a97ba372b2b72 Mon Sep 17 00:00:00 2001
From: Quanah Gibson-Mount <quanah@openldap.org>
Date: Thu, 15 Apr 2010 00:31:47 +0000
Subject: [PATCH] Add pbind proxybind overlay. Just intercepts Bind requests on
 a regular DB and proxies them to a remote server.

---
 CHANGES                              |   1 +
 doc/man/man5/slapo-chain.5           |   4 +
 doc/man/man5/slapo-pbind.5           |  61 ++++++++++
 servers/slapd/back-ldap/Makefile.in  |   4 +-
 servers/slapd/back-ldap/config.c     |  72 +++++++++++
 servers/slapd/back-ldap/init.c       |   5 +
 servers/slapd/back-ldap/pbind.c      | 173 +++++++++++++++++++++++++++
 servers/slapd/back-ldap/proto-ldap.h |   2 +
 8 files changed, 320 insertions(+), 2 deletions(-)
 create mode 100644 doc/man/man5/slapo-pbind.5
 create mode 100644 servers/slapd/back-ldap/pbind.c

diff --git a/CHANGES b/CHANGES
index b92c65040d..317533e3fc 100644
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,7 @@ OpenLDAP 2.4 Change Log
 
 OpenLDAP 2.4.22 Engineering
 	Added slapd SLAP_SCHEMA_EXPOSE flag for hidden schema elements (ITS#6435)
+	Added slapo-pbind
 	Fixed libldap GnuTLS serial length (ITS#6460)
 	Fixed slapd certificateListValidate (ITS#6466)
 	Fixed slapd empty URI parsing (ITS#6465)
diff --git a/doc/man/man5/slapo-chain.5 b/doc/man/man5/slapo-chain.5
index 7f6b750865..d3ba35c98b 100644
--- a/doc/man/man5/slapo-chain.5
+++ b/doc/man/man5/slapo-chain.5
@@ -42,6 +42,10 @@ in conjunction with this overlay.  They are described in
 .BR slapd\-ldap (5),
 and they also need to be prefixed by
 .BR chain\- .
+
+Note: this overlay is built into the \fIldap\fP backend; it is not 
+a separate module.
+
 .TP
 .B overlay chain
 This directive adds the chain overlay to the current backend.
diff --git a/doc/man/man5/slapo-pbind.5 b/doc/man/man5/slapo-pbind.5
new file mode 100644
index 0000000000..4fe43a2f10
--- /dev/null
+++ b/doc/man/man5/slapo-pbind.5
@@ -0,0 +1,61 @@
+.TH SLAPO-PBIND 5 "RELEASEDATE" "OpenLDAP LDVERSION"
+.\" Copyright 2010-2010 The OpenLDAP Foundation, All Rights Reserved.
+.\" Copying restrictions apply.  See the COPYRIGHT file.
+.\" $OpenLDAP$
+.SH NAME
+slapo\-pbind \- proxy bind overlay to slapd
+.SH SYNOPSIS
+ETCDIR/slapd.conf
+.SH DESCRIPTION
+The
+.B pbind
+overlay to
+.BR slapd (8)
+forwards Simple Binds on a local database to a remote
+LDAP server instead of processing them locally. The remote
+connection is managed using an instance of the ldap backend.
+
+.LP 
+The
+.B pbind
+overlay uses a subset of the \fIldap\fP backend's config directives. They
+are described in more detail in
+.BR slapd\-ldap (5).
+
+Note: this overlay is built into the \fIldap\fP backend; it is not a
+separate module.
+
+.TP
+.B overlay pbind
+This directive adds the proxy bind overlay to the current backend.
+The proxy bind overlay may be used with any backend, but it is mainly 
+intended for use with local storage backends.
+
+.TP
+.B uri <ldapurl>
+LDAP server to use.
+
+.TP
+.B tls <TLS parameters>
+Specify the use of TLS.
+
+.TP
+.B network\-timeout <time>
+Set the network timeout.
+
+.TP
+.B quarantine <quarantine parameters>
+Turns on quarantine of URIs that returned
+.IR LDAP_UNAVAILABLE .
+
+.SH FILES
+.TP
+ETCDIR/slapd.conf
+default slapd configuration file
+.SH SEE ALSO
+.BR slapd.conf (5),
+.BR slapd\-config (5),
+.BR slapd\-ldap (5),
+.BR slapd (8).
+.SH AUTHOR
+Howard Chu
diff --git a/servers/slapd/back-ldap/Makefile.in b/servers/slapd/back-ldap/Makefile.in
index 83c3d2cd07..64a4af82ff 100644
--- a/servers/slapd/back-ldap/Makefile.in
+++ b/servers/slapd/back-ldap/Makefile.in
@@ -15,10 +15,10 @@
 
 SRCS	= init.c config.c search.c bind.c unbind.c add.c compare.c \
 		delete.c modify.c modrdn.c extended.c chain.c \
-		distproc.c monitor.c
+		distproc.c monitor.c pbind.c
 OBJS	= init.lo config.lo search.lo bind.lo unbind.lo add.lo compare.lo \
 		delete.lo modify.lo modrdn.lo extended.lo chain.lo \
-		distproc.lo monitor.lo
+		distproc.lo monitor.lo pbind.lo
 
 LDAP_INCDIR= ../../../include       
 LDAP_LIBDIR= ../../../libraries
diff --git a/servers/slapd/back-ldap/config.c b/servers/slapd/back-ldap/config.c
index 98f51b9a8e..f0b47b81f5 100644
--- a/servers/slapd/back-ldap/config.c
+++ b/servers/slapd/back-ldap/config.c
@@ -41,6 +41,7 @@
 static SLAP_EXTOP_MAIN_FN ldap_back_exop_whoami;
 
 static ConfigDriver ldap_back_cf_gen;
+static ConfigDriver ldap_pbind_cf_gen;
 
 enum {
 	LDAP_BACK_CFG_URI = 1,
@@ -374,6 +375,57 @@ static ConfigOCs ldapocs[] = {
 	{ NULL, 0, NULL }
 };
 
+static ConfigTable pbindcfg[] = {
+	{ "uri", "uri", 2, 2, 0,
+		ARG_MAGIC|LDAP_BACK_CFG_URI,
+		ldap_pbind_cf_gen, "( OLcfgDbAt:0.14 "
+			"NAME 'olcDbURI' "
+			"DESC 'URI (list) for remote DSA' "
+			"SYNTAX OMsDirectoryString "
+			"SINGLE-VALUE )",
+		NULL, NULL },
+	{ "tls", "what", 2, 0, 0,
+		ARG_MAGIC|LDAP_BACK_CFG_TLS,
+		ldap_pbind_cf_gen, "( OLcfgDbAt:3.1 "
+			"NAME 'olcDbStartTLS' "
+			"DESC 'StartTLS' "
+			"SYNTAX OMsDirectoryString "
+			"SINGLE-VALUE )",
+		NULL, NULL },
+	{ "network-timeout", "timeout", 2, 2, 0,
+		ARG_MAGIC|LDAP_BACK_CFG_NETWORK_TIMEOUT,
+		ldap_pbind_cf_gen, "( OLcfgDbAt:3.17 "
+			"NAME 'olcDbNetworkTimeout' "
+			"DESC 'connection network timeout' "
+			"SYNTAX OMsDirectoryString "
+			"SINGLE-VALUE )",
+		NULL, NULL },
+	{ "quarantine", "retrylist", 2, 2, 0,
+		ARG_MAGIC|LDAP_BACK_CFG_QUARANTINE,
+		ldap_pbind_cf_gen, "( OLcfgDbAt:3.21 "
+			"NAME 'olcDbQuarantine' "
+			"DESC 'Quarantine database if connection fails and retry according to rule' "
+			"SYNTAX OMsDirectoryString "
+			"SINGLE-VALUE )",
+		NULL, NULL },
+	{ NULL, NULL, 0, 0, 0, ARG_IGNORED,
+		NULL, NULL, NULL, NULL }
+};
+
+static ConfigOCs pbindocs[] = {
+	{ "( OLcfgOvOc:3.3 "
+		"NAME 'olcPBindConfig' "
+		"DESC 'Proxy Bind configuration' "
+		"SUP olcOverlayConfig "
+		"MUST olcDbURI "
+		"MAY ( olcDbStartTLS "
+			"$ olcDbNetworkTimeout "
+			"$ olcDbQuarantine "
+		") )",
+		 	Cft_Overlay, pbindcfg},
+	{ NULL, 0, NULL }
+};
+
 static slap_verbmasks idassert_mode[] = {
 	{ BER_BVC("self"),		LDAP_BACK_IDASSERT_SELF },
 	{ BER_BVC("anonymous"),		LDAP_BACK_IDASSERT_ANONYMOUS },
@@ -2038,6 +2090,26 @@ ldap_back_init_cf( BackendInfo *bi )
 	return 0;
 }
 
+static int
+ldap_pbind_cf_gen( ConfigArgs *c )
+{
+	slap_overinst	*on = (slap_overinst *)c->bi;
+	void	*private = c->be->be_private;
+	int		rc;
+
+	c->be->be_private = on->on_bi.bi_private;
+	rc = ldap_back_cf_gen( c );
+	c->be->be_private = private;
+	return rc;
+}
+
+int
+ldap_pbind_init_cf( BackendInfo *bi )
+{
+	bi->bi_cf_ocs = pbindocs;
+
+	return config_register_schema( pbindcfg, pbindocs );
+}
 
 static int
 ldap_back_exop_whoami(
diff --git a/servers/slapd/back-ldap/init.c b/servers/slapd/back-ldap/init.c
index b8b50b1847..729f611c11 100644
--- a/servers/slapd/back-ldap/init.c
+++ b/servers/slapd/back-ldap/init.c
@@ -104,6 +104,11 @@ ldap_back_initialize( BackendInfo *bi )
 		return rc;
 	}
 
+	rc = pbind_initialize();
+	if ( rc ) {
+		return rc;
+	}
+
 #ifdef SLAP_DISTPROC
 	rc = distproc_initialize();
 	if ( rc ) {
diff --git a/servers/slapd/back-ldap/pbind.c b/servers/slapd/back-ldap/pbind.c
new file mode 100644
index 0000000000..04dc99cf6b
--- /dev/null
+++ b/servers/slapd/back-ldap/pbind.c
@@ -0,0 +1,173 @@
+/* pbind.c - passthru Bind overlay */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2003-2010 The OpenLDAP Foundation.
+ * Portions Copyright 2003-2010 Howard Chu.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was initially developed by the Howard Chu for inclusion
+ * in OpenLDAP Software.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "lutil.h"
+#include "slap.h"
+#include "back-ldap.h"
+#include "config.h"
+
+static BackendInfo	*lback;
+
+static slap_overinst ldappbind;
+
+static int
+ldap_pbind_bind(
+	Operation	*op,
+	SlapReply	*rs )
+{
+	slap_overinst	*on = (slap_overinst *) op->o_bd->bd_info;
+	void *private = op->o_bd->be_private;
+	void *bi = op->o_bd->bd_info;
+	int rc;
+
+	op->o_bd->bd_info = lback;
+	op->o_bd->be_private = on->on_bi.bi_private;
+	rc = lback->bi_op_bind( op, rs );
+	op->o_bd->be_private = private;
+	op->o_bd->bd_info = bi;
+
+	return rc;
+}
+
+static int
+ldap_pbind_db_init(
+	BackendDB *be,
+	ConfigReply *cr )
+{
+	slap_overinst	*on = (slap_overinst *)be->bd_info;
+	ConfigOCs	*be_cf_ocs = be->be_cf_ocs;
+	void		*private = be->be_private;
+	int rc;
+
+	if ( lback == NULL ) {
+		lback = backend_info( "ldap" );
+
+		if ( lback == NULL ) {
+			return 1;
+		}
+	}
+
+	rc = lback->bi_db_init( be, cr );
+	on->on_bi.bi_private = be->be_private;
+	be->be_cf_ocs = be_cf_ocs;
+	be->be_private = private;
+
+	return rc;
+}
+
+static int
+ldap_pbind_db_open(
+	BackendDB	*be,
+	ConfigReply	*cr )
+{
+	slap_overinst	*on = (slap_overinst *) be->bd_info;
+	void	*private = be->be_private;
+	int		rc;
+	int		monitoring;
+
+    be->be_private = on->on_bi.bi_private;
+	monitoring = ( SLAP_DBFLAGS( be ) & SLAP_DBFLAG_MONITORING );
+	SLAP_DBFLAGS( be ) &= ~SLAP_DBFLAG_MONITORING;
+	rc = lback->bi_db_open( be, cr );
+	SLAP_DBFLAGS( be ) |= monitoring;
+	be->be_private = private;
+
+	return rc;
+}
+
+static int
+ldap_pbind_db_close(
+	BackendDB	*be,
+	ConfigReply	*cr )
+{
+	slap_overinst	*on = (slap_overinst *) be->bd_info;
+	void	*private = be->be_private;
+	int		rc;
+
+    be->be_private = on->on_bi.bi_private;
+	rc = lback->bi_db_close( be, cr );
+	be->be_private = private;
+
+	return rc;
+}
+
+static int
+ldap_pbind_db_destroy(
+	BackendDB	*be,
+	ConfigReply	*cr )
+{
+	slap_overinst	*on = (slap_overinst *) be->bd_info;
+	void	*private = be->be_private;
+	int		rc;
+
+    be->be_private = on->on_bi.bi_private;
+	rc = lback->bi_db_close( be, cr );
+	on->on_bi.bi_private = be->be_private;
+	be->be_private = private;
+
+	return rc;
+}
+
+static int
+ldap_pbind_connection_destroy(
+	BackendDB *be,
+	Connection *conn
+)
+{
+	slap_overinst	*on = (slap_overinst *) be->bd_info;
+	void			*private = be->be_private;
+	int				rc;
+
+	be->be_private = on->on_bi.bi_private;
+	rc = lback->bi_connection_destroy( be, conn );
+	be->be_private = private;
+
+	return rc;
+}
+
+int
+pbind_initialize( void )
+{
+	int rc;
+
+	ldappbind.on_bi.bi_type = "pbind";
+	ldappbind.on_bi.bi_db_init = ldap_pbind_db_init;
+	ldappbind.on_bi.bi_db_open = ldap_pbind_db_open;
+	ldappbind.on_bi.bi_db_close = ldap_pbind_db_close;
+	ldappbind.on_bi.bi_db_destroy = ldap_pbind_db_destroy;
+
+	ldappbind.on_bi.bi_op_bind = ldap_pbind_bind;
+	ldappbind.on_bi.bi_connection_destroy = ldap_pbind_connection_destroy;
+
+	rc = ldap_pbind_init_cf( &ldappbind.on_bi );
+	if ( rc ) {
+		return rc;
+	}
+
+	return overlay_register( &ldappbind );
+}
diff --git a/servers/slapd/back-ldap/proto-ldap.h b/servers/slapd/back-ldap/proto-ldap.h
index b9b1486a08..4960cc9288 100644
--- a/servers/slapd/back-ldap/proto-ldap.h
+++ b/servers/slapd/back-ldap/proto-ldap.h
@@ -55,6 +55,7 @@ int ldap_back_op_result( ldapconn_t *lc, Operation *op, SlapReply *rs,
 int ldap_back_cancel( ldapconn_t *lc, Operation *op, SlapReply *rs, ber_int_t msgid, ldap_back_send_t sendok );
 
 int ldap_back_init_cf( BackendInfo *bi );
+int ldap_pbind_init_cf( BackendInfo *bi );
 
 extern int ldap_back_conndn_cmp( const void *c1, const void *c2);
 extern int ldap_back_conn_cmp( const void *c1, const void *c2);
@@ -104,6 +105,7 @@ extern int slap_idassert_authzfrom_parse_cf( const char *fname, int lineno, cons
 extern int slap_idassert_parse_cf( const char *fname, int lineno, int argc, char *argv[], slap_idassert_t *si );
 
 extern int chain_initialize( void );
+extern int pbind_initialize( void );
 #ifdef SLAP_DISTPROC
 extern int distproc_initialize( void );
 #endif
-- 
GitLab